Fix memory leak by creating the SSL context once for ADC client.

This is done using reference counted global memory.
This commit is contained in:
Jan Vidar Krey 2014-08-06 17:37:06 +02:00
parent 4919aea8d5
commit d7c8c9426d
2 changed files with 42 additions and 3 deletions

View File

@ -155,7 +155,7 @@ struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const
return (struct ssl_context_handle*) ctx; return (struct ssl_context_handle*) ctx;
} }
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx_) void net_ssl_context_destroy(struct ssl_context_handle* ctx_)
{ {
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
SSL_CTX_free(ctx->ssl); SSL_CTX_free(ctx->ssl);
@ -266,6 +266,7 @@ ssize_t net_con_ssl_connect(struct net_connection* con)
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx) ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx)
{ {
uhub_assert(con); uhub_assert(con);
uhub_assert(ssl_ctx);
struct net_context_openssl* ctx = (struct net_context_openssl*) ssl_ctx; struct net_context_openssl* ctx = (struct net_context_openssl*) ssl_ctx;
struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl)); struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl));
@ -285,7 +286,7 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
} }
else else
{ {
handle->ssl = SSL_new(SSL_CTX_new(TLSv1_2_method())); handle->ssl = SSL_new(ctx->ssl);
SSL_set_fd(handle->ssl, con->sd); SSL_set_fd(handle->ssl, con->sd);
handle->bio = SSL_get_rbio(handle->ssl); handle->bio = SSL_get_rbio(handle->ssl);
con->ssl = (struct ssl_handle*) handle; con->ssl = (struct ssl_handle*) handle;
@ -353,6 +354,7 @@ void net_ssl_shutdown(struct net_connection* con)
void net_ssl_destroy(struct net_connection* con) void net_ssl_destroy(struct net_connection* con)
{ {
struct net_ssl_openssl* handle = get_handle(con); struct net_ssl_openssl* handle = get_handle(con);
LOG_TRACE("net_ssl_destroy: %p", con);
SSL_free(handle->ssl); SSL_free(handle->ssl);
hub_free(handle); hub_free(handle);
} }

View File

@ -27,6 +27,18 @@
// #define ADCC_DEBUG // #define ADCC_DEBUG
// #define ADC_CLIENT_DEBUG_PROTO // #define ADC_CLIENT_DEBUG_PROTO
struct ADC_client_global
{
size_t references;
#ifdef SSL_SUPPORT
struct ssl_context_handle* ctx;
#endif
};
static struct ADC_client_global* g_adc_client = NULL;
enum ADC_client_state enum ADC_client_state
{ {
ps_none, /* Not connected */ ps_none, /* Not connected */
@ -541,6 +553,17 @@ struct ADC_client* ADC_client_create(const char* nickname, const char* descripti
client->recv_queue = ioq_recv_create(); client->recv_queue = ioq_recv_create();
client->ptr = ptr; client->ptr = ptr;
if (!g_adc_client)
{
g_adc_client = (struct ADC_client_global*) hub_malloc_zero(sizeof(struct ADC_client_global));
#ifdef SSL_SUPPORT
g_adc_client->ctx = net_ssl_context_create("1.2", "HIGH");
#endif
}
g_adc_client->references++;
return client; return client;
} }
@ -556,6 +579,20 @@ void ADC_client_destroy(struct ADC_client* client)
hub_free(client->desc); hub_free(client->desc);
hub_free(client->address.hostname); hub_free(client->address.hostname);
hub_free(client); hub_free(client);
if (g_adc_client && g_adc_client->references > 0)
{
g_adc_client->references--;
if (!g_adc_client->references)
{
#ifdef SSL_SUPPORT
net_ssl_context_destroy(g_adc_client->ctx);
g_adc_client->ctx = NULL;
#endif
hub_free(g_adc_client);
g_adc_client = NULL;
}
}
} }
static void connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con, void* ptr) static void connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con, void* ptr)
@ -622,7 +659,7 @@ static void ADC_client_on_connected(struct ADC_client* client)
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0); client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0);
ADC_client_set_state(client, ps_conn_ssl); ADC_client_set_state(client, ps_conn_ssl);
net_con_ssl_handshake(client->con, net_con_ssl_mode_client, NULL); net_con_ssl_handshake(client->con, net_con_ssl_mode_client, g_adc_client->ctx);
} }
else else
#endif #endif