diff options
author | Ben Laurie <ben@openssl.org> | 2008-06-03 02:48:34 +0000 |
---|---|---|
committer | Ben Laurie <ben@openssl.org> | 2008-06-03 02:48:34 +0000 |
commit | 8671b898609777c95aedf33743419a523874e6e8 (patch) | |
tree | c990da274ac4414776ab16f8f755133ec010c7be /ssl/s3_both.c | |
parent | 4f7f4117194c44fede3a32baf0f5905c4800ffa2 (diff) |
Memory saving patch.
Diffstat (limited to 'ssl/s3_both.c')
-rw-r--r-- | ssl/s3_both.c | 136 |
1 files changed, 130 insertions, 6 deletions
diff --git a/ssl/s3_both.c b/ssl/s3_both.c index 1a45e677a4..88bed0fa6b 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -591,7 +591,81 @@ int ssl_verify_alarm_type(long type) return(al); } -int ssl3_setup_buffers(SSL *s) +#if !defined(OPENSSL_NO_BUF_FREELISTS) && !defined(OPENSSL_NO_RELEASE_BUFFERS) +/* On some platforms, malloc() performance is bad enough that you can't just + * free() and malloc() buffers all the time, so we need to use freelists from + * unused buffers. Currently, each freelist holds memory chunks of only a + * given size (list->chunklen); other sized chunks are freed and malloced. + * This doesn't help much if you're using many different SSL option settings + * with a given context. (The options affecting buffer size are + * max_send_fragment, read buffer vs write buffer, + * SSL_OP_MICROSOFT_BIG_WRITE_BUFFER, SSL_OP_NO_COMPRESSION, and + * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.) Using a separate freelist for every + * possible size is not an option, since max_send_fragment can take on many + * different values. + * + * If you are on a platform with a slow malloc(), and you're using SSL + * connections with many different settings for these options, and you need to + * use the SSL_MOD_RELEASE_BUFFERS feature, you have a few options: + * - Link against a faster malloc implementation. + * - Use a separate SSL_CTX for each option set. + * - Improve this code. + */ +static void * +freelist_extract(SSL_CTX *ctx, int for_read, int sz) + { + SSL3_BUF_FREELIST *list; + SSL3_BUF_FREELIST_ENTRY *ent = NULL; + void *result = NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; + if (list != NULL && sz == list->chunklen) + ent = list->head; + if (ent != NULL) + { + list->head = ent->next; + result = ent; + if (--list->len == 0) + list->chunklen = 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + if (!result) + result = OPENSSL_malloc(sz); + return result; +} + +static void +freelist_insert(SSL_CTX *ctx, int for_read, size_t sz, void *mem) + { + SSL3_BUF_FREELIST *list; + SSL3_BUF_FREELIST_ENTRY *ent; + + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; + if (list != NULL && + (sz == list->chunklen || list->chunklen == 0) && + list->len < ctx->freelist_max_len && + sz >= sizeof(*ent)) + { + list->chunklen = sz; + ent = mem; + ent->next = list->head; + list->head = ent; + ++list->len; + mem = NULL; + } + + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + if (mem) + OPENSSL_free(mem); + } +#else +#define freelist_extract(c,fr,sz) OPENSSL_malloc(sz) +#define freelist_insert(c,fr,sz,m) OPENSSL_free(m) +#endif + +int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; size_t len,align=0; @@ -614,12 +688,29 @@ int ssl3_setup_buffers(SSL *s) if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif - if ((p=OPENSSL_malloc(len)) == NULL) + if ((p=freelist_extract(s->ctx, 1, len)) == NULL) goto err; s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } + s->packet= &(s->s3->rbuf.buf[0]); + return 1; + +err: + SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); + return 0; + } + +int ssl3_setup_write_buffer(SSL *s) + { + unsigned char *p; + size_t len,align=0; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 + align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); +#endif + if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment @@ -632,14 +723,47 @@ int ssl3_setup_buffers(SSL *s) if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += SSL3_RT_HEADER_LENGTH + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; - if ((p=OPENSSL_malloc(len)) == NULL) + + if ((p=freelist_extract(s->ctx, 0, len)) == NULL) goto err; s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } - s->packet= &(s->s3->rbuf.buf[0]); - return(1); + + return 1; + err: SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); - return(0); + return 0; + } + + +int ssl3_setup_buffers(SSL *s) + { + if (!ssl3_setup_read_buffer(s)) + return 0; + if (!ssl3_setup_write_buffer(s)) + return 0; + return 1; + } + +int ssl3_release_write_buffer(SSL *s) + { + if (s->s3->wbuf.buf != NULL) + { + freelist_insert(s->ctx, 0, s->s3->wbuf.len, s->s3->wbuf.buf); + s->s3->wbuf.buf = NULL; + } + return 1; } + +int ssl3_release_read_buffer(SSL *s) + { + if (s->s3->rbuf.buf != NULL) + { + freelist_insert(s->ctx, 1, s->s3->rbuf.len, s->s3->rbuf.buf); + s->s3->rbuf.buf = NULL; + } + return 1; + } + |