comparison src/event/ngx_event_openssl.c @ 1014:5ffd76a9ccf3

optimize the SSL session cache allocations
author Igor Sysoev <igor@sysoev.ru>
date Thu, 11 Jan 2007 17:39:02 +0000
parents 7dd987e09701
children 32ebb6b13ff3
comparison
equal deleted inserted replaced
1013:7dd987e09701 1014:5ffd76a9ccf3
1230 return NGX_OK; 1230 return NGX_OK;
1231 } 1231 }
1232 1232
1233 1233
1234 /* 1234 /*
1235 * The length of the session id is 16 bytes for SSLv2 sessions and
1236 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1237 * It seems that the typical length of the external ASN1 representation
1238 * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1239 * Thus we allocate separatly an rbtree node, a session id, and an ASN1
1240 * representation and on 32-bit platforms they take accordingly 64, 32, and
1241 * 128 bytes.
1242 *
1235 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow, 1243 * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1236 * so they are outside the code locked by shared pool mutex 1244 * so they are outside the code locked by shared pool mutex
1237 */ 1245 */
1238 1246
1239 static int 1247 static int
1240 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) 1248 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1241 { 1249 {
1242 int len; 1250 int len;
1243 u_char *p, *id; 1251 u_char *p, *id, *cached_sess;
1244 uint32_t hash; 1252 uint32_t hash;
1245 SSL_CTX *ssl_ctx; 1253 SSL_CTX *ssl_ctx;
1246 ngx_time_t *tp; 1254 ngx_time_t *tp;
1247 ngx_shm_zone_t *shm_zone; 1255 ngx_shm_zone_t *shm_zone;
1248 ngx_connection_t *c; 1256 ngx_connection_t *c;
1249 ngx_slab_pool_t *shpool; 1257 ngx_slab_pool_t *shpool;
1250 ngx_ssl_sess_id_t *sess_id; 1258 ngx_ssl_sess_id_t *sess_id;
1251 ngx_ssl_cached_sess_t *cached_sess;
1252 ngx_ssl_session_cache_t *cache; 1259 ngx_ssl_session_cache_t *cache;
1253 u_char buf[NGX_SSL_MAX_SESSION_SIZE]; 1260 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1254 1261
1255 len = i2d_SSL_SESSION(sess, NULL); 1262 len = i2d_SSL_SESSION(sess, NULL);
1256 1263
1274 ngx_shmtx_lock(&shpool->mutex); 1281 ngx_shmtx_lock(&shpool->mutex);
1275 1282
1276 /* drop one or two expired sessions */ 1283 /* drop one or two expired sessions */
1277 ngx_ssl_expire_sessions(cache, shpool, 1); 1284 ngx_ssl_expire_sessions(cache, shpool, 1);
1278 1285
1279 cached_sess = ngx_slab_alloc_locked(shpool, 1286 cached_sess = ngx_slab_alloc_locked(shpool, len);
1280 offsetof(ngx_ssl_cached_sess_t, asn1) + len);
1281 1287
1282 if (cached_sess == NULL) { 1288 if (cached_sess == NULL) {
1283 1289
1284 /* drop the oldest non-expired session and try once more */ 1290 /* drop the oldest non-expired session and try once more */
1285 1291
1286 ngx_ssl_expire_sessions(cache, shpool, 0); 1292 ngx_ssl_expire_sessions(cache, shpool, 0);
1287 1293
1288 cached_sess = ngx_slab_alloc_locked(shpool, 1294 cached_sess = ngx_slab_alloc_locked(shpool, len);
1289 offsetof(ngx_ssl_cached_sess_t, asn1) + len);
1290 1295
1291 if (cached_sess == NULL) { 1296 if (cached_sess == NULL) {
1292 id = NULL; 1297 id = NULL;
1293 goto failed; 1298 goto failed;
1294 } 1299 }
1302 sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t)); 1307 sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1303 if (sess_id == NULL) { 1308 if (sess_id == NULL) {
1304 goto failed; 1309 goto failed;
1305 } 1310 }
1306 1311
1307 ngx_memcpy(&cached_sess->asn1[0], buf, len); 1312 ngx_memcpy(cached_sess, buf, len);
1308 1313
1309 ngx_memcpy(id, sess->session_id, sess->session_id_length); 1314 ngx_memcpy(id, sess->session_id, sess->session_id_length);
1310 1315
1311 hash = ngx_crc32_short(sess->session_id, sess->session_id_length); 1316 hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
1312 1317
1313 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 1318 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1314 "http ssl new session: %08XD:%d:%d", 1319 "http ssl new session: %08XD:%d:%d",
1315 hash, sess->session_id_length, len); 1320 hash, sess->session_id_length, len);
1321
1322 tp = ngx_timeofday();
1316 1323
1317 sess_id->node.key = hash; 1324 sess_id->node.key = hash;
1318 sess_id->node.data = (u_char) sess->session_id_length; 1325 sess_id->node.data = (u_char) sess->session_id_length;
1319 sess_id->id = id; 1326 sess_id->id = id;
1320 sess_id->len = len; 1327 sess_id->len = len;
1321 sess_id->session = cached_sess; 1328 sess_id->session = cached_sess;
1322 1329
1323 tp = ngx_timeofday(); 1330 sess_id->expire = tp->sec + SSL_CTX_get_timeout(ssl_ctx);
1324 1331
1325 cached_sess->expire = tp->sec + SSL_CTX_get_timeout(ssl_ctx); 1332 sess_id->next = cache->session_cache_head.next;
1326 cached_sess->sess_id = sess_id; 1333 sess_id->next->prev = sess_id;
1327 1334 sess_id->prev = &cache->session_cache_head;
1328 cached_sess->next = cache->session_cache_head.next; 1335 cache->session_cache_head.next = sess_id;
1329 cached_sess->next->prev = cached_sess;
1330 cached_sess->prev = &cache->session_cache_head;
1331 cache->session_cache_head.next = cached_sess;
1332 1336
1333 ngx_rbtree_insert(cache->session_rbtree, &sess_id->node); 1337 ngx_rbtree_insert(cache->session_rbtree, &sess_id->node);
1334 1338
1335 ngx_shmtx_unlock(&shpool->mutex); 1339 ngx_shmtx_unlock(&shpool->mutex);
1336 1340
1369 ngx_slab_pool_t *shpool; 1373 ngx_slab_pool_t *shpool;
1370 ngx_connection_t *c; 1374 ngx_connection_t *c;
1371 ngx_rbtree_node_t *node, *sentinel; 1375 ngx_rbtree_node_t *node, *sentinel;
1372 ngx_ssl_session_t *sess; 1376 ngx_ssl_session_t *sess;
1373 ngx_ssl_sess_id_t *sess_id; 1377 ngx_ssl_sess_id_t *sess_id;
1374 ngx_ssl_cached_sess_t *cached_sess;
1375 ngx_ssl_session_cache_t *cache; 1378 ngx_ssl_session_cache_t *cache;
1376 u_char buf[NGX_SSL_MAX_SESSION_SIZE]; 1379 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
1377 1380
1378 c = ngx_ssl_get_connection(ssl_conn); 1381 c = ngx_ssl_get_connection(ssl_conn);
1379 1382
1419 if ((u_char) len == node->data) { 1422 if ((u_char) len == node->data) {
1420 sess_id = (ngx_ssl_sess_id_t *) node; 1423 sess_id = (ngx_ssl_sess_id_t *) node;
1421 1424
1422 if (ngx_strncmp(id, sess_id->id, len) == 0) { 1425 if (ngx_strncmp(id, sess_id->id, len) == 0) {
1423 1426
1424 cached_sess = sess_id->session;
1425
1426 tp = ngx_timeofday(); 1427 tp = ngx_timeofday();
1427 1428
1428 if (cached_sess->expire > tp->sec) { 1429 if (sess_id->expire > tp->sec) {
1429 ngx_memcpy(buf, &cached_sess->asn1[0], sess_id->len); 1430 ngx_memcpy(buf, sess_id->session, sess_id->len);
1430 1431
1431 ngx_shmtx_unlock(&shpool->mutex); 1432 ngx_shmtx_unlock(&shpool->mutex);
1432 1433
1433 p = buf; 1434 p = buf;
1434 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len); 1435 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
1435 1436
1436 return sess; 1437 return sess;
1437 } 1438 }
1438 1439
1439 cached_sess->next->prev = cached_sess->prev; 1440 sess_id->next->prev = sess_id->prev;
1440 cached_sess->prev->next = cached_sess->next; 1441 sess_id->prev->next = sess_id->next;
1441 1442
1442 ngx_rbtree_delete(cache->session_rbtree, node); 1443 ngx_rbtree_delete(cache->session_rbtree, node);
1443 1444
1444 ngx_slab_free_locked(shpool, cached_sess); 1445 ngx_slab_free_locked(shpool, sess_id->session);
1445 ngx_slab_free_locked(shpool, sess_id->id); 1446 ngx_slab_free_locked(shpool, sess_id->id);
1446 ngx_slab_free_locked(shpool, sess_id); 1447 ngx_slab_free_locked(shpool, sess_id);
1447 1448
1448 sess = NULL; 1449 sess = NULL;
1449 1450
1473 uint32_t hash; 1474 uint32_t hash;
1474 ngx_shm_zone_t *shm_zone; 1475 ngx_shm_zone_t *shm_zone;
1475 ngx_slab_pool_t *shpool; 1476 ngx_slab_pool_t *shpool;
1476 ngx_rbtree_node_t *node, *sentinel; 1477 ngx_rbtree_node_t *node, *sentinel;
1477 ngx_ssl_sess_id_t *sess_id; 1478 ngx_ssl_sess_id_t *sess_id;
1478 ngx_ssl_cached_sess_t *cached_sess;
1479 ngx_ssl_session_cache_t *cache; 1479 ngx_ssl_session_cache_t *cache;
1480 1480
1481 shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index); 1481 shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
1482 1482
1483 cache = shm_zone->data; 1483 cache = shm_zone->data;
1515 if ((u_char) len == node->data) { 1515 if ((u_char) len == node->data) {
1516 sess_id = (ngx_ssl_sess_id_t *) node; 1516 sess_id = (ngx_ssl_sess_id_t *) node;
1517 1517
1518 if (ngx_strncmp(id, sess_id->id, (size_t) len) == 0) { 1518 if (ngx_strncmp(id, sess_id->id, (size_t) len) == 0) {
1519 1519
1520 cached_sess = sess_id->session; 1520 sess_id->next->prev = sess_id->prev;
1521 1521 sess_id->prev->next = sess_id->next;
1522 cached_sess->next->prev = cached_sess->prev;
1523 cached_sess->prev->next = cached_sess->next;
1524 1522
1525 ngx_rbtree_delete(cache->session_rbtree, node); 1523 ngx_rbtree_delete(cache->session_rbtree, node);
1526 1524
1527 ngx_slab_free_locked(shpool, cached_sess); 1525 ngx_slab_free_locked(shpool, sess_id->session);
1528 ngx_slab_free_locked(shpool, sess_id->id); 1526 ngx_slab_free_locked(shpool, sess_id->id);
1529 ngx_slab_free_locked(shpool, sess_id); 1527 ngx_slab_free_locked(shpool, sess_id);
1530 1528
1531 goto done; 1529 goto done;
1532 } 1530 }
1547 1545
1548 static void 1546 static void
1549 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache, 1547 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
1550 ngx_slab_pool_t *shpool, ngx_uint_t n) 1548 ngx_slab_pool_t *shpool, ngx_uint_t n)
1551 { 1549 {
1552 ngx_time_t *tp; 1550 ngx_time_t *tp;
1553 ngx_ssl_sess_id_t *sess_id; 1551 ngx_ssl_sess_id_t *sess_id;
1554 ngx_ssl_cached_sess_t *sess;
1555 1552
1556 tp = ngx_timeofday(); 1553 tp = ngx_timeofday();
1557 1554
1558 while (n < 3) { 1555 while (n < 3) {
1559 1556
1560 sess = cache->session_cache_tail.prev; 1557 sess_id = cache->session_cache_tail.prev;
1561 1558
1562 if (sess == &cache->session_cache_head) { 1559 if (sess_id == &cache->session_cache_head) {
1563 return; 1560 return;
1564 } 1561 }
1565 1562
1566 if (n++ != 0 && sess->expire > tp->sec) { 1563 if (n++ != 0 && sess_id->expire > tp->sec) {
1567 break; 1564 break;
1568 } 1565 }
1569 1566
1570 sess->next->prev = sess->prev; 1567 sess_id->next->prev = sess_id->prev;
1571 sess->prev->next = sess->next; 1568 sess_id->prev->next = sess_id->next;
1572
1573 sess_id = sess->sess_id;
1574 1569
1575 ngx_rbtree_delete(cache->session_rbtree, &sess_id->node); 1570 ngx_rbtree_delete(cache->session_rbtree, &sess_id->node);
1576 1571
1577 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, 1572 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1578 "expire session: %08Xi", sess_id->node.key); 1573 "expire session: %08Xi", sess_id->node.key);
1579 1574
1580 ngx_slab_free_locked(shpool, sess); 1575 ngx_slab_free_locked(shpool, sess_id->session);
1581 ngx_slab_free_locked(shpool, sess_id->id); 1576 ngx_slab_free_locked(shpool, sess_id->id);
1582 ngx_slab_free_locked(shpool, sess_id); 1577 ngx_slab_free_locked(shpool, sess_id);
1583 } 1578 }
1584 } 1579 }
1585 1580