httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From do...@apache.org
Subject cvs commit: httpd-2.0/modules/ssl ssl_engine_io.c
Date Tue, 27 Nov 2001 23:37:20 GMT
dougm       01/11/27 15:37:20

  Modified:    modules/ssl ssl_engine_io.c
  Log:
  implement a custom BIO which allows us to hook SSL_write directly into
  an apr_bucket_brigade and use transient buckets with the SSL
  malloc-ed buffer, rather than copying into a mem BIO.
  
  also allows us to pass the brigade as data is being written
  rather than buffering up the entire response in the mem BIO.
  
  Reviewed by:	Justin Erenkrantz, Ryan Bloom
  
  Revision  Changes    Path
  1.45      +210 -33   httpd-2.0/modules/ssl/ssl_engine_io.c
  
  Index: ssl_engine_io.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_io.c,v
  retrieving revision 1.44
  retrieving revision 1.45
  diff -u -r1.44 -r1.45
  --- ssl_engine_io.c	2001/11/19 22:37:57	1.44
  +++ ssl_engine_io.c	2001/11/27 23:37:20	1.45
  @@ -70,6 +70,213 @@
   
   /* XXX THIS STUFF NEEDS A MAJOR CLEANUP -RSE XXX */
   
  +/* this custom BIO allows us to hook SSL_write directly into 
  + * an apr_bucket_brigade and use transient buckets with the SSL
  + * malloc-ed buffer, rather than copying into a mem BIO.
  + * also allows us to pass the brigade as data is being written
  + * rather than buffering up the entire response in the mem BIO.
  + */
  +
  +typedef struct {
  +    SSLFilterRec *frec;
  +    conn_rec *c;
  +    apr_bucket_brigade *bb;
  +    apr_size_t length;
  +    char buffer[AP_IOBUFSIZE];
  +    apr_size_t blen;
  +} BIO_bucket_t;
  +
  +static BIO_bucket_t *BIO_bucket_new(SSLFilterRec *frec, conn_rec *c)
  +{
  +    BIO_bucket_t *b = apr_palloc(c->pool, sizeof(*b));
  +
  +    b->frec = frec;
  +    b->c = c;
  +    b->bb = apr_brigade_create(c->pool);
  +    b->blen = 0;
  +    b->length = 0;
  +
  +    return b;
  +}
  +
  +#define BIO_bucket_ptr(bio) (BIO_bucket_t *)bio->ptr
  +
  +static int BIO_bucket_flush(BIO *bio)
  +{
  +    BIO_bucket_t *b = BIO_bucket_ptr(bio);
  +
  +    if (!(b->blen || b->length)) {
  +        return APR_SUCCESS;
  +    }
  +
  +    if (b->blen) {
  +        apr_bucket *bucket = 
  +            apr_bucket_transient_create(b->buffer,
  +                                        b->blen);
  +        /* we filled this buffer first so add it to the 
  +         * head of the brigade
  +         */
  +        APR_BRIGADE_INSERT_HEAD(b->bb, bucket);
  +        b->blen = 0;
  +    }
  +
  +    b->length = 0;
  +    APR_BRIGADE_INSERT_TAIL(b->bb, apr_bucket_flush_create());
  +
  +    return ap_pass_brigade(b->frec->pOutputFilter->next, b->bb);
  +}
  +
  +static int bio_bucket_new(BIO *bio)
  +{
  +    bio->shutdown = 1;
  +    bio->init = 1;
  +    bio->num = -1;
  +    bio->ptr = NULL;
  +
  +    return 1;
  +}
  +
  +static int bio_bucket_free(BIO *bio)
  +{
  +    if (bio == NULL) {
  +        return 0;
  +    }
  +
  +    /* nothing to free here.
  +     * apache will destroy the bucket brigade for us
  +     */
  +    return 1;
  +}
  +	
  +static int bio_bucket_read(BIO *bio, char *out, int outl)
  +{
  +    /* this is never called */
  +    return -1;
  +}
  +
  +static int bio_bucket_write(BIO *bio, const char *in, int inl)
  +{
  +    BIO_bucket_t *b = BIO_bucket_ptr(bio);
  +
  +    /* when handshaking we'll have a small number of bytes.
  +     * max size SSL will pass us here is about 16k.
  +     * (16413 bytes to be exact)
  +     */
  +    BIO_clear_retry_flags(bio);
  +
  +    if (!b->length && (inl < (sizeof(b->buffer) - b->blen))) {
  +        /* the first two SSL_writes (of 1024 and 261 bytes)
  +         * need to be in the same packet (vec[0].iov_base)
  +         */
  +        /* XXX: could use apr_brigade_write() to make code look cleaner
  +         * but this way we avoid the malloc(APR_BUCKET_BUFF_SIZE)
  +         * and free() of it later
  +         */
  +        memcpy(&b->buffer[b->blen], in, inl);
  +        b->blen += inl;
  +    }
  +    else {
  +        /* pass along the encrypted data
  +         * need to flush since we're using SSL's malloc-ed buffer 
  +         * which will be overwritten once we leave here
  +         */
  +        apr_bucket *bucket = apr_bucket_transient_create(in, inl);
  +
  +        b->length += inl;
  +        APR_BRIGADE_INSERT_TAIL(b->bb, bucket);
  +
  +        BIO_bucket_flush(bio);
  +    }
  +
  +    return inl;
  +}
  +
  +static long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr)
  +{
  +    long ret = 1;
  +    char **pptr;
  +
  +    BIO_bucket_t *b = BIO_bucket_ptr(bio);
  +
  +    switch (cmd) {
  +      case BIO_CTRL_RESET:
  +        b->blen = b->length = 0;
  +        break;
  +      case BIO_CTRL_EOF:
  +        ret = (long)((b->blen + b->length) == 0);
  +        break;
  +      case BIO_C_SET_BUF_MEM_EOF_RETURN:
  +        b->blen = b->length = (apr_size_t)num;
  +        break;
  +      case BIO_CTRL_INFO:
  +        ret = (long)(b->blen + b->length);
  +        if (ptr) {
  +            pptr = (char **)ptr;
  +            *pptr = (char *)&(b->buffer[0]);
  +        }
  +        break;
  +      case BIO_CTRL_GET_CLOSE:
  +        ret = (long)bio->shutdown;
  +        break;
  +      case BIO_CTRL_SET_CLOSE:
  +        bio->shutdown = (int)num;
  +        break;
  +      case BIO_CTRL_WPENDING:
  +        ret = 0L;
  +        break;
  +      case BIO_CTRL_PENDING:
  +        ret = (long)(b->blen + b->length);
  +        break;
  +      case BIO_CTRL_FLUSH:
  +        ret = (BIO_bucket_flush(bio) == APR_SUCCESS);
  +        break;
  +      case BIO_CTRL_DUP:
  +        ret = 1;
  +        break;
  +        /* N/A */
  +      case BIO_C_SET_BUF_MEM:
  +      case BIO_C_GET_BUF_MEM_PTR:
  +        /* we don't care */
  +      case BIO_CTRL_PUSH:
  +      case BIO_CTRL_POP:
  +      default:
  +        ret = 0;
  +        break;
  +    }
  +
  +    return ret;
  +}
  +
  +static int bio_bucket_gets(BIO *bio, char *buf, int size)
  +{
  +    /* this is never called */
  +    return -1;
  +}
  +
  +static int bio_bucket_puts(BIO *bio, const char *str)
  +{
  +    /* this is never called */
  +    return -1;
  +}
  +
  +static BIO_METHOD bio_bucket_method = {
  +    BIO_TYPE_MEM,
  +    "APR bucket brigade",
  +    bio_bucket_write,
  +    bio_bucket_read,
  +    bio_bucket_puts,
  +    bio_bucket_gets,
  +    bio_bucket_ctrl,
  +    bio_bucket_new,
  +    bio_bucket_free,
  +    NULL,
  +};
  +
  +static BIO_METHOD *BIO_s_bucket(void)
  +{
  +    return &bio_bucket_method;
  +}
  +
   static const char ssl_io_filter[] = "SSL/TLS Filter";
   
   static int ssl_io_hook_read(SSL *ssl, char *buf, int len)
  @@ -146,45 +353,14 @@
       return rc;
   }
   
  -#define BIO_mem(b) ((BUF_MEM *)b->ptr)
  -
   static apr_status_t churn_output(SSLFilterRec *ctx)
   {
  -    ap_filter_t *f = ctx->pOutputFilter;
  -    apr_pool_t *p = f->c->pool;
  -
       if (!ctx->pssl) {
           /* we've been shutdown */
           return APR_EOF;
       }
  -
  -    if (BIO_pending(ctx->pbioWrite)) {
  -        BUF_MEM *bm = BIO_mem(ctx->pbioWrite);
  -        apr_bucket_brigade *bb = apr_brigade_create(p);
  -        apr_bucket *bucket; 
  -
  -        /*
  -         * use the BIO memory buffer that has already been allocated,
  -         * rather than making another copy of it.
  -         * use bm directly here is *much* faster than calling BIO_read()
  -         * look at crypto/bio/bss_mem.c:mem_read and you'll see why
  -         */
  -
  -        bucket = apr_bucket_transient_create((const char *)bm->data,
  -                                             bm->length);
  -
  -        bm->length = 0; /* reset */
  -
  -        APR_BRIGADE_INSERT_TAIL(bb, bucket);
  -
  -	/* XXX: it may be possible to not always flush */
  -        bucket = apr_bucket_flush_create();
  -        APR_BRIGADE_INSERT_TAIL(bb, bucket);
  -
  -        return ap_pass_brigade(f->next, bb);
  -    }
   
  -    return APR_SUCCESS;
  +    return BIO_bucket_flush(ctx->pbioWrite);
   }
   
   #define bio_is_renegotiating(bio) \
  @@ -583,7 +759,8 @@
       filter->b               = apr_brigade_create(c->pool);
       filter->rawb            = apr_brigade_create(c->pool);
       filter->pbioRead        = BIO_new(BIO_s_mem());
  -    filter->pbioWrite       = BIO_new(BIO_s_mem());
  +    filter->pbioWrite       = BIO_new(BIO_s_bucket());
  +    filter->pbioWrite->ptr  = BIO_bucket_new(filter, c);
       SSL_set_bio(ssl, filter->pbioRead, filter->pbioWrite);
       filter->pssl            = ssl;
   
  
  
  

Mime
View raw message