int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { int ret = 0; SSL_SESSION *s; /* add just 1 reference count for the SSL_CTX's session cache even though it * has two ways of access: each session is in a doubly linked list and an * lhash */ SSL_SESSION_up_ref(c); /* if session c is in already in cache, we take back the increment later */ CRYPTO_MUTEX_lock_write(&ctx->lock); if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) { CRYPTO_MUTEX_unlock(&ctx->lock); return 0; } /* s != NULL iff we already had a session with the given PID. In this case, s * == c should hold (then we did not really modify ctx->sessions), or we're * in trouble. */ if (s != NULL && s != c) { /* We *are* in trouble ... */ SSL_SESSION_list_remove(ctx, s); SSL_SESSION_free(s); /* ... so pretend the other session did not exist in cache (we cannot * handle two SSL_SESSION structures with identical session ID in the same * cache, which could happen e.g. when two threads concurrently obtain the * same session from an external cache) */ s = NULL; } /* Put at the head of the queue unless it is already in the cache */ if (s == NULL) { SSL_SESSION_list_add(ctx, c); } if (s != NULL) { /* existing cache entry -- decrement previously incremented reference count * because it already takes into account the cache */ SSL_SESSION_free(s); /* s == c */ ret = 0; } else { /* new cache entry -- remove old ones if cache has become too large */ ret = 1; if (SSL_CTX_sess_get_cache_size(ctx) > 0) { while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) { break; } } } } CRYPTO_MUTEX_unlock(&ctx->lock); return ret; }
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) { /* Although |session| is inserted into two structures (a doubly-linked list * and the hash table), |ctx| only takes one reference. */ SSL_SESSION_up_ref(session); SSL_SESSION *old_session; CRYPTO_MUTEX_lock_write(&ctx->lock); if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) { CRYPTO_MUTEX_unlock(&ctx->lock); SSL_SESSION_free(session); return 0; } if (old_session != NULL) { if (old_session == session) { /* |session| was already in the cache. */ CRYPTO_MUTEX_unlock(&ctx->lock); SSL_SESSION_free(old_session); return 0; } /* There was a session ID collision. |old_session| must be removed from * the linked list and released. */ SSL_SESSION_list_remove(ctx, old_session); SSL_SESSION_free(old_session); } SSL_SESSION_list_add(ctx, session); /* Enforce any cache size limits. */ if (SSL_CTX_sess_get_cache_size(ctx) > 0) { while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) { break; } } } CRYPTO_MUTEX_unlock(&ctx->lock); return 1; }
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { int ret = 0; SSL_SESSION *s; /* * add just 1 reference count for the SSL_CTX's session cache even though * it has two ways of access: each session is in a doubly linked list and * an lhash */ SSL_SESSION_up_ref(c); /* * if session c is in already in cache, we take back the increment later */ CRYPTO_THREAD_write_lock(ctx->lock); s = lh_SSL_SESSION_insert(ctx->sessions, c); /* * s != NULL iff we already had a session with the given PID. In this * case, s == c should hold (then we did not really modify * ctx->sessions), or we're in trouble. */ if (s != NULL && s != c) { /* We *are* in trouble ... */ SSL_SESSION_list_remove(ctx, s); SSL_SESSION_free(s); /* * ... so pretend the other session did not exist in cache (we cannot * handle two SSL_SESSION structures with identical session ID in the * same cache, which could happen e.g. when two threads concurrently * obtain the same session from an external cache) */ s = NULL; } else if (s == NULL && lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) { /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */ /* * ... so take back the extra reference and also don't add * the session to the SSL_SESSION_list at this time */ s = c; } /* Put at the head of the queue unless it is already in the cache */ if (s == NULL) SSL_SESSION_list_add(ctx, c); if (s != NULL) { /* * existing cache entry -- decrement previously incremented reference * count because it already takes into account the cache */ SSL_SESSION_free(s); /* s == c */ ret = 0; } else { /* * new cache entry -- remove old ones if cache has become too large */ ret = 1; if (SSL_CTX_sess_get_cache_size(ctx) > 0) { while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) break; else ctx->stats.sess_cache_full++; } } } CRYPTO_THREAD_unlock(ctx->lock); return ret; }
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { int ret = 0; SSL_SESSION *s; /* * Add just 1 reference count for the SSL_CTX's session cache * even though it has two ways of access: each session is in a * doubly linked list and an lhash. */ CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION); /* * If session c is in already in cache, we take back the increment * later. */ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); s = lh_SSL_SESSION_insert(ctx->internal->sessions, c); /* * s != NULL iff we already had a session with the given PID. * In this case, s == c should hold (then we did not really modify * ctx->internal->sessions), or we're in trouble. */ if (s != NULL && s != c) { /* We *are* in trouble ... */ SSL_SESSION_list_remove(ctx, s); SSL_SESSION_free(s); /* * ... so pretend the other session did not exist in cache * (we cannot handle two SSL_SESSION structures with identical * session ID in the same cache, which could happen e.g. when * two threads concurrently obtain the same session from an * external cache). */ s = NULL; } /* Put at the head of the queue unless it is already in the cache */ if (s == NULL) SSL_SESSION_list_add(ctx, c); if (s != NULL) { /* * existing cache entry -- decrement previously incremented * reference count because it already takes into account the * cache. */ SSL_SESSION_free(s); /* s == c */ ret = 0; } else { /* * New cache entry -- remove old ones if cache has become * too large. */ ret = 1; if (SSL_CTX_sess_get_cache_size(ctx) > 0) { while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { if (!remove_session_lock(ctx, ctx->internal->session_cache_tail, 0)) break; else ctx->internal->stats.sess_cache_full++; } } } CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); return (ret); }