comparison src/event/ngx_event_openssl.c @ 358:9121a0a91f47 NGINX_0_6_23

nginx 0.6.23 *) Change: the "off" parameter in the "ssl_session_cache" directive; now this is default parameter. *) Change: the "open_file_cache_retest" directive was renamed to the "open_file_cache_valid". *) Feature: the "open_file_cache_min_uses" directive. *) Feature: the ngx_http_gzip_static_module. *) Feature: the "gzip_disable" directive. *) Feature: the "memcached_pass" directive may be used inside the "if" block. *) Bugfix: a segmentation fault occurred in worker process, if the "memcached_pass" and "if" directives were used in the same location. *) Bugfix: if a "satisfy_any on" directive was used and not all access and auth modules directives were set, then other given access and auth directives were not tested; *) Bugfix: regex parameters in a "valid_referers" directive were not inherited from previous level. *) Bugfix: a "post_action" directive did run if a request was completed with 499 status code. *) Bugfix: optimization of 16K buffer usage in a SSL connection. Thanks to Ben Maurer. *) Bugfix: the STARTTLS in SMTP mode did not work. Thanks to Oleg Motienko. *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" error; bug appeared in 0.5.13.
author Igor Sysoev <http://sysoev.ru>
date Thu, 27 Dec 2007 00:00:00 +0300
parents b743d290eb3b
children 2b41fbc2e39e
comparison
equal deleted inserted replaced
357:16d557a75356 358:9121a0a91f47
20 static void ngx_ssl_write_handler(ngx_event_t *wev); 20 static void ngx_ssl_write_handler(ngx_event_t *wev);
21 static void ngx_ssl_read_handler(ngx_event_t *rev); 21 static void ngx_ssl_read_handler(ngx_event_t *rev);
22 static void ngx_ssl_shutdown_handler(ngx_event_t *ev); 22 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
23 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, 23 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
24 ngx_err_t err, char *text); 24 ngx_err_t err, char *text);
25 static void ngx_ssl_clear_error(ngx_log_t *log);
25 26
26 static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, 27 static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone,
27 void *data); 28 void *data);
28 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, 29 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
29 ngx_ssl_session_t *sess); 30 ngx_ssl_session_t *sess);
184 185
185 if (ngx_ssl_protocols[protocols >> 1] != 0) { 186 if (ngx_ssl_protocols[protocols >> 1] != 0) {
186 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); 187 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
187 } 188 }
188 189
189 SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
190
191 SSL_CTX_set_read_ahead(ssl->ctx, 1); 190 SSL_CTX_set_read_ahead(ssl->ctx, 1);
192 191
193 return NGX_OK; 192 return NGX_OK;
194 } 193 }
195 194
343 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t)); 342 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
344 if (sc == NULL) { 343 if (sc == NULL) {
345 return NGX_ERROR; 344 return NGX_ERROR;
346 } 345 }
347 346
348 if (flags & NGX_SSL_BUFFER) { 347 sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
349 sc->buffer = 1;
350
351 sc->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
352 if (sc->buf == NULL) {
353 return NGX_ERROR;
354 }
355 }
356 348
357 sc->connection = SSL_new(ssl->ctx); 349 sc->connection = SSL_new(ssl->ctx);
358 350
359 if (sc->connection == NULL) { 351 if (sc->connection == NULL) {
360 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed"); 352 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
402 ngx_ssl_handshake(ngx_connection_t *c) 394 ngx_ssl_handshake(ngx_connection_t *c)
403 { 395 {
404 int n, sslerr; 396 int n, sslerr;
405 ngx_err_t err; 397 ngx_err_t err;
406 398
399 ngx_ssl_clear_error(c->log);
400
407 n = SSL_do_handshake(c->ssl->connection); 401 n = SSL_do_handshake(c->ssl->connection);
408 402
409 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); 403 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
410 404
411 if (n == 1) { 405 if (n == 1) {
602 c->read->eof = 1; 596 c->read->eof = 1;
603 return 0; 597 return 0;
604 } 598 }
605 599
606 bytes = 0; 600 bytes = 0;
601
602 ngx_ssl_clear_error(c->log);
607 603
608 /* 604 /*
609 * SSL_read() may return data in parts, so try to read 605 * SSL_read() may return data in parts, so try to read
610 * until SSL_read() would return no data 606 * until SSL_read() would return no data
611 */ 607 */
799 795
800 if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) { 796 if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {
801 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; 797 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
802 } 798 }
803 799
804
805 buf = c->ssl->buf; 800 buf = c->ssl->buf;
801
802 if (buf == NULL) {
803 buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
804 if (buf == NULL) {
805 return NGX_CHAIN_ERROR;
806 }
807
808 c->ssl->buf = buf;
809 }
810
811 if (buf->start == NULL) {
812 buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
813 if (buf->start == NULL) {
814 return NGX_CHAIN_ERROR;
815 }
816
817 buf->pos = buf->start;
818 buf->last = buf->start;
819 buf->end = buf->start + NGX_SSL_BUFSIZE;
820 }
821
806 send = 0; 822 send = 0;
807 flush = (in == NULL) ? 1 : 0; 823 flush = (in == NULL) ? 1 : 0;
808 824
809 for ( ;; ) { 825 for ( ;; ) {
810 826
893 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) 909 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
894 { 910 {
895 int n, sslerr; 911 int n, sslerr;
896 ngx_err_t err; 912 ngx_err_t err;
897 913
914 ngx_ssl_clear_error(c->log);
915
898 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size); 916 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
899 917
900 n = SSL_write(c->ssl->connection, data, size); 918 n = SSL_write(c->ssl->connection, data, size);
901 919
902 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n); 920 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
973 991
974 c->write->handler(c->write); 992 c->write->handler(c->write);
975 } 993 }
976 994
977 995
996 void
997 ngx_ssl_free_buffer(ngx_connection_t *c)
998 {
999 if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1000 c->ssl->buf->start = NULL;
1001 }
1002 }
1003
1004
978 ngx_int_t 1005 ngx_int_t
979 ngx_ssl_shutdown(ngx_connection_t *c) 1006 ngx_ssl_shutdown(ngx_connection_t *c)
980 { 1007 {
981 int n, sslerr, mode; 1008 int n, sslerr, mode;
982 ngx_err_t err; 1009 ngx_err_t err;
983 ngx_uint_t again;
984 1010
985 if (c->timedout) { 1011 if (c->timedout) {
986 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; 1012 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
987 1013
988 } else { 1014 } else {
997 } 1023 }
998 } 1024 }
999 1025
1000 SSL_set_shutdown(c->ssl->connection, mode); 1026 SSL_set_shutdown(c->ssl->connection, mode);
1001 1027
1002 again = 0; 1028 ngx_ssl_clear_error(c->log);
1029
1030 n = SSL_shutdown(c->ssl->connection);
1031
1032 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1033
1003 sslerr = 0; 1034 sslerr = 0;
1004 1035
1005 for ( ;; ) { 1036 /* SSL_shutdown() never return -1, on error it return 0 */
1006 n = SSL_shutdown(c->ssl->connection); 1037
1007 1038 if (n != 1) {
1008 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1009
1010 if (n == 1 || (n == 0 && c->timedout)) {
1011 SSL_free(c->ssl->connection);
1012 c->ssl = NULL;
1013
1014 return NGX_OK;
1015 }
1016
1017 if (n == 0) {
1018 again = 1;
1019 break;
1020 }
1021
1022 break;
1023 }
1024
1025 if (!again) {
1026 sslerr = SSL_get_error(c->ssl->connection, n); 1039 sslerr = SSL_get_error(c->ssl->connection, n);
1027 1040
1028 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 1041 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1029 "SSL_get_error: %d", sslerr); 1042 "SSL_get_error: %d", sslerr);
1030 } 1043 }
1031 1044
1032 if (again 1045 if (n == 1
1033 || sslerr == SSL_ERROR_WANT_READ 1046 || sslerr == SSL_ERROR_ZERO_RETURN
1034 || sslerr == SSL_ERROR_WANT_WRITE) 1047 || (sslerr == 0 && c->timedout))
1035 { 1048 {
1049 SSL_free(c->ssl->connection);
1050 c->ssl = NULL;
1051
1052 return NGX_OK;
1053 }
1054
1055 if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1036 c->read->handler = ngx_ssl_shutdown_handler; 1056 c->read->handler = ngx_ssl_shutdown_handler;
1037 c->write->handler = ngx_ssl_shutdown_handler; 1057 c->write->handler = ngx_ssl_shutdown_handler;
1038 1058
1039 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { 1059 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
1040 return NGX_ERROR; 1060 return NGX_ERROR;
1042 1062
1043 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { 1063 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
1044 return NGX_ERROR; 1064 return NGX_ERROR;
1045 } 1065 }
1046 1066
1047 if (again || sslerr == SSL_ERROR_WANT_READ) { 1067 if (sslerr == SSL_ERROR_WANT_READ) {
1048 ngx_add_timer(c->read, 30000); 1068 ngx_add_timer(c->read, 30000);
1049 } 1069 }
1050 1070
1051 return NGX_AGAIN; 1071 return NGX_AGAIN;
1052 } 1072 }
1123 1143
1124 ngx_ssl_error(level, c->log, err, text); 1144 ngx_ssl_error(level, c->log, err, text);
1125 } 1145 }
1126 1146
1127 1147
1148 static void
1149 ngx_ssl_clear_error(ngx_log_t *log)
1150 {
1151 if (ERR_peek_error()) {
1152 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
1153 }
1154 }
1155
1156
1128 void ngx_cdecl 1157 void ngx_cdecl
1129 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) 1158 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1130 { 1159 {
1131 u_long n; 1160 u_long n;
1132 va_list args; 1161 va_list args;
1164 ngx_int_t 1193 ngx_int_t
1165 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, 1194 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
1166 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) 1195 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
1167 { 1196 {
1168 long cache_mode; 1197 long cache_mode;
1198
1199 if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1200 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1201 return NGX_OK;
1202 }
1169 1203
1170 cache_mode = SSL_SESS_CACHE_SERVER; 1204 cache_mode = SSL_SESS_CACHE_SERVER;
1171 1205
1172 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) { 1206 if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
1173 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL; 1207 cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
1208 1242
1209 static ngx_int_t 1243 static ngx_int_t
1210 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) 1244 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
1211 { 1245 {
1212 ngx_slab_pool_t *shpool; 1246 ngx_slab_pool_t *shpool;
1213 ngx_rbtree_node_t *sentinel;
1214 ngx_ssl_session_cache_t *cache; 1247 ngx_ssl_session_cache_t *cache;
1215 1248
1216 if (data) { 1249 if (data) {
1217 shm_zone->data = data; 1250 shm_zone->data = data;
1218 return NGX_OK; 1251 return NGX_OK;
1223 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t)); 1256 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
1224 if (cache == NULL) { 1257 if (cache == NULL) {
1225 return NGX_ERROR; 1258 return NGX_ERROR;
1226 } 1259 }
1227 1260
1228 cache->session_cache_head.prev = NULL; 1261 ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
1229 cache->session_cache_head.next = &cache->session_cache_tail;
1230
1231 cache->session_cache_tail.prev = &cache->session_cache_head;
1232 cache->session_cache_tail.next = NULL;
1233
1234 cache->session_rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
1235 if (cache->session_rbtree == NULL) {
1236 return NGX_ERROR;
1237 }
1238
1239 sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
1240 if (sentinel == NULL) {
1241 return NGX_ERROR;
1242 }
1243
1244 ngx_rbtree_init(cache->session_rbtree, sentinel,
1245 ngx_ssl_session_rbtree_insert_value); 1262 ngx_ssl_session_rbtree_insert_value);
1263
1264 ngx_queue_init(&cache->expire_queue);
1246 1265
1247 shm_zone->data = cache; 1266 shm_zone->data = cache;
1248 1267
1249 return NGX_OK; 1268 return NGX_OK;
1250 } 1269 }
1272 { 1291 {
1273 int len; 1292 int len;
1274 u_char *p, *id, *cached_sess; 1293 u_char *p, *id, *cached_sess;
1275 uint32_t hash; 1294 uint32_t hash;
1276 SSL_CTX *ssl_ctx; 1295 SSL_CTX *ssl_ctx;
1277 ngx_time_t *tp;
1278 ngx_shm_zone_t *shm_zone; 1296 ngx_shm_zone_t *shm_zone;
1279 ngx_connection_t *c; 1297 ngx_connection_t *c;
1280 ngx_slab_pool_t *shpool; 1298 ngx_slab_pool_t *shpool;
1281 ngx_ssl_sess_id_t *sess_id; 1299 ngx_ssl_sess_id_t *sess_id;
1282 ngx_ssl_session_cache_t *cache; 1300 ngx_ssl_session_cache_t *cache;
1348 1366
1349 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 1367 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1350 "http ssl new session: %08XD:%d:%d", 1368 "http ssl new session: %08XD:%d:%d",
1351 hash, sess->session_id_length, len); 1369 hash, sess->session_id_length, len);
1352 1370
1353 tp = ngx_timeofday();
1354
1355 sess_id->node.key = hash; 1371 sess_id->node.key = hash;
1356 sess_id->node.data = (u_char) sess->session_id_length; 1372 sess_id->node.data = (u_char) sess->session_id_length;
1357 sess_id->id = id; 1373 sess_id->id = id;
1358 sess_id->len = len; 1374 sess_id->len = len;
1359 sess_id->session = cached_sess; 1375 sess_id->session = cached_sess;
1360 1376
1361 sess_id->expire = tp->sec + SSL_CTX_get_timeout(ssl_ctx); 1377 sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
1362 1378
1363 sess_id->next = cache->session_cache_head.next; 1379 ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
1364 sess_id->next->prev = sess_id; 1380
1365 sess_id->prev = &cache->session_cache_head; 1381 ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
1366 cache->session_cache_head.next = sess_id;
1367
1368 ngx_rbtree_insert(cache->session_rbtree, &sess_id->node);
1369 1382
1370 ngx_shmtx_unlock(&shpool->mutex); 1383 ngx_shmtx_unlock(&shpool->mutex);
1371 1384
1372 return 0; 1385 return 0;
1373 1386
1398 const 1411 const
1399 #endif 1412 #endif
1400 u_char *p; 1413 u_char *p;
1401 uint32_t hash; 1414 uint32_t hash;
1402 ngx_int_t rc; 1415 ngx_int_t rc;
1403 ngx_time_t *tp;
1404 ngx_shm_zone_t *shm_zone; 1416 ngx_shm_zone_t *shm_zone;
1405 ngx_slab_pool_t *shpool; 1417 ngx_slab_pool_t *shpool;
1406 ngx_connection_t *c; 1418 ngx_connection_t *c;
1407 ngx_rbtree_node_t *node, *sentinel; 1419 ngx_rbtree_node_t *node, *sentinel;
1408 ngx_ssl_session_t *sess; 1420 ngx_ssl_session_t *sess;
1421 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), 1433 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
1422 ngx_ssl_session_cache_index); 1434 ngx_ssl_session_cache_index);
1423 1435
1424 cache = shm_zone->data; 1436 cache = shm_zone->data;
1425 1437
1426 if (cache->session_rbtree == NULL) {
1427 return NULL;
1428 }
1429
1430 sess = NULL; 1438 sess = NULL;
1431 1439
1432 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 1440 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1433 1441
1434 ngx_shmtx_lock(&shpool->mutex); 1442 ngx_shmtx_lock(&shpool->mutex);
1435 1443
1436 node = cache->session_rbtree->root; 1444 node = cache->session_rbtree.root;
1437 sentinel = cache->session_rbtree->sentinel; 1445 sentinel = cache->session_rbtree.sentinel;
1438 1446
1439 while (node != sentinel) { 1447 while (node != sentinel) {
1440 1448
1441 if (hash < node->key) { 1449 if (hash < node->key) {
1442 node = node->left; 1450 node = node->left;
1455 1463
1456 rc = ngx_memn2cmp(id, sess_id->id, 1464 rc = ngx_memn2cmp(id, sess_id->id,
1457 (size_t) len, (size_t) node->data); 1465 (size_t) len, (size_t) node->data);
1458 if (rc == 0) { 1466 if (rc == 0) {
1459 1467
1460 tp = ngx_timeofday(); 1468 if (sess_id->expire > ngx_time()) {
1461
1462 if (sess_id->expire > tp->sec) {
1463 ngx_memcpy(buf, sess_id->session, sess_id->len); 1469 ngx_memcpy(buf, sess_id->session, sess_id->len);
1464 1470
1465 ngx_shmtx_unlock(&shpool->mutex); 1471 ngx_shmtx_unlock(&shpool->mutex);
1466 1472
1467 p = buf; 1473 p = buf;
1468 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len); 1474 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
1469 1475
1470 return sess; 1476 return sess;
1471 } 1477 }
1472 1478
1473 sess_id->next->prev = sess_id->prev; 1479 ngx_queue_remove(&sess_id->queue);
1474 sess_id->prev->next = sess_id->next; 1480
1475 1481 ngx_rbtree_delete(&cache->session_rbtree, node);
1476 ngx_rbtree_delete(cache->session_rbtree, node);
1477 1482
1478 ngx_slab_free_locked(shpool, sess_id->session); 1483 ngx_slab_free_locked(shpool, sess_id->session);
1479 #if (NGX_PTR_SIZE == 4) 1484 #if (NGX_PTR_SIZE == 4)
1480 ngx_slab_free_locked(shpool, sess_id->id); 1485 ngx_slab_free_locked(shpool, sess_id->id);
1481 #endif 1486 #endif
1528 1533
1529 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 1534 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1530 1535
1531 ngx_shmtx_lock(&shpool->mutex); 1536 ngx_shmtx_lock(&shpool->mutex);
1532 1537
1533 node = cache->session_rbtree->root; 1538 node = cache->session_rbtree.root;
1534 sentinel = cache->session_rbtree->sentinel; 1539 sentinel = cache->session_rbtree.sentinel;
1535 1540
1536 while (node != sentinel) { 1541 while (node != sentinel) {
1537 1542
1538 if (hash < node->key) { 1543 if (hash < node->key) {
1539 node = node->left; 1544 node = node->left;
1551 sess_id = (ngx_ssl_sess_id_t *) node; 1556 sess_id = (ngx_ssl_sess_id_t *) node;
1552 1557
1553 rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data); 1558 rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
1554 1559
1555 if (rc == 0) { 1560 if (rc == 0) {
1556 sess_id->next->prev = sess_id->prev; 1561
1557 sess_id->prev->next = sess_id->next; 1562 ngx_queue_remove(&sess_id->queue);
1558 1563
1559 ngx_rbtree_delete(cache->session_rbtree, node); 1564 ngx_rbtree_delete(&cache->session_rbtree, node);
1560 1565
1561 ngx_slab_free_locked(shpool, sess_id->session); 1566 ngx_slab_free_locked(shpool, sess_id->session);
1562 #if (NGX_PTR_SIZE == 4) 1567 #if (NGX_PTR_SIZE == 4)
1563 ngx_slab_free_locked(shpool, sess_id->id); 1568 ngx_slab_free_locked(shpool, sess_id->id);
1564 #endif 1569 #endif
1582 1587
1583 static void 1588 static void
1584 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache, 1589 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
1585 ngx_slab_pool_t *shpool, ngx_uint_t n) 1590 ngx_slab_pool_t *shpool, ngx_uint_t n)
1586 { 1591 {
1587 ngx_time_t *tp; 1592 time_t now;
1593 ngx_queue_t *q;
1588 ngx_ssl_sess_id_t *sess_id; 1594 ngx_ssl_sess_id_t *sess_id;
1589 1595
1590 tp = ngx_timeofday(); 1596 now = ngx_time();
1591 1597
1592 while (n < 3) { 1598 while (n < 3) {
1593 1599
1594 sess_id = cache->session_cache_tail.prev; 1600 if (ngx_queue_empty(&cache->expire_queue)) {
1595
1596 if (sess_id == &cache->session_cache_head) {
1597 return; 1601 return;
1598 } 1602 }
1599 1603
1600 if (n++ != 0 && sess_id->expire > tp->sec) { 1604 q = ngx_queue_last(&cache->expire_queue);
1605
1606 sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
1607
1608 if (n++ != 0 && sess_id->expire > now) {
1601 return; 1609 return;
1602 } 1610 }
1603 1611
1604 sess_id->next->prev = sess_id->prev; 1612 ngx_queue_remove(q);
1605 sess_id->prev->next = sess_id->next;
1606
1607 ngx_rbtree_delete(cache->session_rbtree, &sess_id->node);
1608 1613
1609 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, 1614 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1610 "expire session: %08Xi", sess_id->node.key); 1615 "expire session: %08Xi", sess_id->node.key);
1616
1617 ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
1611 1618
1612 ngx_slab_free_locked(shpool, sess_id->session); 1619 ngx_slab_free_locked(shpool, sess_id->session);
1613 #if (NGX_PTR_SIZE == 4) 1620 #if (NGX_PTR_SIZE == 4)
1614 ngx_slab_free_locked(shpool, sess_id->id); 1621 ngx_slab_free_locked(shpool, sess_id->id);
1615 #endif 1622 #endif