Mercurial > hg > nginx
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 |