Annotation of embedaddon/nginx/src/http/ngx_http_request.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_http.h>
                     11: 
                     12: 
                     13: static void ngx_http_wait_request_handler(ngx_event_t *ev);
                     14: static void ngx_http_process_request_line(ngx_event_t *rev);
                     15: static void ngx_http_process_request_headers(ngx_event_t *rev);
                     16: static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
                     17: static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
                     18:     ngx_uint_t request_line);
                     19: 
                     20: static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
                     21:     ngx_table_elt_t *h, ngx_uint_t offset);
                     22: static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
                     23:     ngx_table_elt_t *h, ngx_uint_t offset);
                     24: static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
                     25:     ngx_table_elt_t *h, ngx_uint_t offset);
                     26: static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
                     27:     ngx_table_elt_t *h, ngx_uint_t offset);
                     28: static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
                     29:     ngx_table_elt_t *h, ngx_uint_t offset);
                     30: static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
                     31:     ngx_table_elt_t *h, ngx_uint_t offset);
                     32: 
                     33: static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
                     34:     ngx_uint_t alloc);
                     35: static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
                     36:     ngx_str_t *host);
                     37: static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
                     38:     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
                     39:     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
                     40: 
                     41: static void ngx_http_request_handler(ngx_event_t *ev);
                     42: static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
                     43: static void ngx_http_terminate_handler(ngx_http_request_t *r);
                     44: static void ngx_http_finalize_connection(ngx_http_request_t *r);
                     45: static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
                     46: static void ngx_http_writer(ngx_http_request_t *r);
                     47: static void ngx_http_request_finalizer(ngx_http_request_t *r);
                     48: 
                     49: static void ngx_http_set_keepalive(ngx_http_request_t *r);
                     50: static void ngx_http_keepalive_handler(ngx_event_t *ev);
                     51: static void ngx_http_set_lingering_close(ngx_http_request_t *r);
                     52: static void ngx_http_lingering_close_handler(ngx_event_t *ev);
                     53: static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
                     54: static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
                     55: static void ngx_http_log_request(ngx_http_request_t *r);
                     56: 
                     57: static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
                     58: static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
                     59:     ngx_http_request_t *sr, u_char *buf, size_t len);
                     60: 
                     61: #if (NGX_HTTP_SSL)
                     62: static void ngx_http_ssl_handshake(ngx_event_t *rev);
                     63: static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
                     64: #endif
                     65: 
                     66: 
                     67: static char *ngx_http_client_errors[] = {
                     68: 
                     69:     /* NGX_HTTP_PARSE_INVALID_METHOD */
                     70:     "client sent invalid method",
                     71: 
                     72:     /* NGX_HTTP_PARSE_INVALID_REQUEST */
                     73:     "client sent invalid request",
                     74: 
                     75:     /* NGX_HTTP_PARSE_INVALID_09_METHOD */
                     76:     "client sent invalid method in HTTP/0.9 request"
                     77: };
                     78: 
                     79: 
                     80: ngx_http_header_t  ngx_http_headers_in[] = {
                     81:     { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
                     82:                  ngx_http_process_host },
                     83: 
                     84:     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
                     85:                  ngx_http_process_connection },
                     86: 
                     87:     { ngx_string("If-Modified-Since"),
                     88:                  offsetof(ngx_http_headers_in_t, if_modified_since),
                     89:                  ngx_http_process_unique_header_line },
                     90: 
                     91:     { ngx_string("If-Unmodified-Since"),
                     92:                  offsetof(ngx_http_headers_in_t, if_unmodified_since),
                     93:                  ngx_http_process_unique_header_line },
                     94: 
                     95:     { ngx_string("If-Match"),
                     96:                  offsetof(ngx_http_headers_in_t, if_match),
                     97:                  ngx_http_process_unique_header_line },
                     98: 
                     99:     { ngx_string("If-None-Match"),
                    100:                  offsetof(ngx_http_headers_in_t, if_none_match),
                    101:                  ngx_http_process_unique_header_line },
                    102: 
                    103:     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
                    104:                  ngx_http_process_user_agent },
                    105: 
                    106:     { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
                    107:                  ngx_http_process_header_line },
                    108: 
                    109:     { ngx_string("Content-Length"),
                    110:                  offsetof(ngx_http_headers_in_t, content_length),
                    111:                  ngx_http_process_unique_header_line },
                    112: 
                    113:     { ngx_string("Content-Type"),
                    114:                  offsetof(ngx_http_headers_in_t, content_type),
                    115:                  ngx_http_process_header_line },
                    116: 
                    117:     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
                    118:                  ngx_http_process_header_line },
                    119: 
                    120:     { ngx_string("If-Range"),
                    121:                  offsetof(ngx_http_headers_in_t, if_range),
                    122:                  ngx_http_process_unique_header_line },
                    123: 
                    124:     { ngx_string("Transfer-Encoding"),
                    125:                  offsetof(ngx_http_headers_in_t, transfer_encoding),
                    126:                  ngx_http_process_header_line },
                    127: 
                    128:     { ngx_string("Expect"),
                    129:                  offsetof(ngx_http_headers_in_t, expect),
                    130:                  ngx_http_process_unique_header_line },
                    131: 
                    132:     { ngx_string("Upgrade"),
                    133:                  offsetof(ngx_http_headers_in_t, upgrade),
                    134:                  ngx_http_process_header_line },
                    135: 
                    136: #if (NGX_HTTP_GZIP)
                    137:     { ngx_string("Accept-Encoding"),
                    138:                  offsetof(ngx_http_headers_in_t, accept_encoding),
                    139:                  ngx_http_process_header_line },
                    140: 
                    141:     { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
                    142:                  ngx_http_process_header_line },
                    143: #endif
                    144: 
                    145:     { ngx_string("Authorization"),
                    146:                  offsetof(ngx_http_headers_in_t, authorization),
                    147:                  ngx_http_process_unique_header_line },
                    148: 
                    149:     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
                    150:                  ngx_http_process_header_line },
                    151: 
                    152: #if (NGX_HTTP_X_FORWARDED_FOR)
                    153:     { ngx_string("X-Forwarded-For"),
                    154:                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
                    155:                  ngx_http_process_multi_header_lines },
                    156: #endif
                    157: 
                    158: #if (NGX_HTTP_REALIP)
                    159:     { ngx_string("X-Real-IP"),
                    160:                  offsetof(ngx_http_headers_in_t, x_real_ip),
                    161:                  ngx_http_process_header_line },
                    162: #endif
                    163: 
                    164: #if (NGX_HTTP_HEADERS)
                    165:     { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
                    166:                  ngx_http_process_header_line },
                    167: 
                    168:     { ngx_string("Accept-Language"),
                    169:                  offsetof(ngx_http_headers_in_t, accept_language),
                    170:                  ngx_http_process_header_line },
                    171: #endif
                    172: 
                    173: #if (NGX_HTTP_DAV)
                    174:     { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
                    175:                  ngx_http_process_header_line },
                    176: 
                    177:     { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
                    178:                  ngx_http_process_header_line },
                    179: 
                    180:     { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
                    181:                  ngx_http_process_header_line },
                    182: 
                    183:     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
                    184:                  ngx_http_process_header_line },
                    185: #endif
                    186: 
                    187:     { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
                    188:                  ngx_http_process_multi_header_lines },
                    189: 
                    190:     { ngx_null_string, 0, NULL }
                    191: };
                    192: 
                    193: 
                    194: void
                    195: ngx_http_init_connection(ngx_connection_t *c)
                    196: {
                    197:     ngx_uint_t              i;
                    198:     ngx_event_t            *rev;
                    199:     struct sockaddr_in     *sin;
                    200:     ngx_http_port_t        *port;
                    201:     ngx_http_in_addr_t     *addr;
                    202:     ngx_http_log_ctx_t     *ctx;
                    203:     ngx_http_connection_t  *hc;
                    204: #if (NGX_HAVE_INET6)
                    205:     struct sockaddr_in6    *sin6;
                    206:     ngx_http_in6_addr_t    *addr6;
                    207: #endif
                    208: 
                    209:     hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
                    210:     if (hc == NULL) {
                    211:         ngx_http_close_connection(c);
                    212:         return;
                    213:     }
                    214: 
                    215:     c->data = hc;
                    216: 
                    217:     /* find the server configuration for the address:port */
                    218: 
                    219:     port = c->listening->servers;
                    220: 
                    221:     if (port->naddrs > 1) {
                    222: 
                    223:         /*
                    224:          * there are several addresses on this port and one of them
                    225:          * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
                    226:          * is required to determine a server address
                    227:          */
                    228: 
                    229:         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
                    230:             ngx_http_close_connection(c);
                    231:             return;
                    232:         }
                    233: 
                    234:         switch (c->local_sockaddr->sa_family) {
                    235: 
                    236: #if (NGX_HAVE_INET6)
                    237:         case AF_INET6:
                    238:             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
                    239: 
                    240:             addr6 = port->addrs;
                    241: 
                    242:             /* the last address is "*" */
                    243: 
                    244:             for (i = 0; i < port->naddrs - 1; i++) {
                    245:                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
                    246:                     break;
                    247:                 }
                    248:             }
                    249: 
                    250:             hc->addr_conf = &addr6[i].conf;
                    251: 
                    252:             break;
                    253: #endif
                    254: 
                    255:         default: /* AF_INET */
                    256:             sin = (struct sockaddr_in *) c->local_sockaddr;
                    257: 
                    258:             addr = port->addrs;
                    259: 
                    260:             /* the last address is "*" */
                    261: 
                    262:             for (i = 0; i < port->naddrs - 1; i++) {
                    263:                 if (addr[i].addr == sin->sin_addr.s_addr) {
                    264:                     break;
                    265:                 }
                    266:             }
                    267: 
                    268:             hc->addr_conf = &addr[i].conf;
                    269: 
                    270:             break;
                    271:         }
                    272: 
                    273:     } else {
                    274: 
                    275:         switch (c->local_sockaddr->sa_family) {
                    276: 
                    277: #if (NGX_HAVE_INET6)
                    278:         case AF_INET6:
                    279:             addr6 = port->addrs;
                    280:             hc->addr_conf = &addr6[0].conf;
                    281:             break;
                    282: #endif
                    283: 
                    284:         default: /* AF_INET */
                    285:             addr = port->addrs;
                    286:             hc->addr_conf = &addr[0].conf;
                    287:             break;
                    288:         }
                    289:     }
                    290: 
                    291:     /* the default server configuration for the address:port */
                    292:     hc->conf_ctx = hc->addr_conf->default_server->ctx;
                    293: 
                    294:     ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
                    295:     if (ctx == NULL) {
                    296:         ngx_http_close_connection(c);
                    297:         return;
                    298:     }
                    299: 
                    300:     ctx->connection = c;
                    301:     ctx->request = NULL;
                    302:     ctx->current_request = NULL;
                    303: 
                    304:     c->log->connection = c->number;
                    305:     c->log->handler = ngx_http_log_error;
                    306:     c->log->data = ctx;
                    307:     c->log->action = "waiting for request";
                    308: 
                    309:     c->log_error = NGX_ERROR_INFO;
                    310: 
                    311:     rev = c->read;
                    312:     rev->handler = ngx_http_wait_request_handler;
                    313:     c->write->handler = ngx_http_empty_handler;
                    314: 
                    315: #if (NGX_HTTP_SPDY)
                    316:     if (hc->addr_conf->spdy) {
                    317:         rev->handler = ngx_http_spdy_init;
                    318:     }
                    319: #endif
                    320: 
                    321: #if (NGX_HTTP_SSL)
                    322:     {
                    323:     ngx_http_ssl_srv_conf_t  *sscf;
                    324: 
                    325:     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
                    326: 
                    327:     if (sscf->enable || hc->addr_conf->ssl) {
                    328: 
                    329:         c->log->action = "SSL handshaking";
                    330: 
                    331:         if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
                    332:             ngx_log_error(NGX_LOG_ERR, c->log, 0,
                    333:                           "no \"ssl_certificate\" is defined "
                    334:                           "in server listening on SSL port");
                    335:             ngx_http_close_connection(c);
                    336:             return;
                    337:         }
                    338: 
                    339:         hc->ssl = 1;
                    340: 
                    341:         rev->handler = ngx_http_ssl_handshake;
                    342:     }
                    343:     }
                    344: #endif
                    345: 
                    346:     if (rev->ready) {
                    347:         /* the deferred accept(), rtsig, aio, iocp */
                    348: 
                    349:         if (ngx_use_accept_mutex) {
                    350:             ngx_post_event(rev, &ngx_posted_events);
                    351:             return;
                    352:         }
                    353: 
                    354:         rev->handler(rev);
                    355:         return;
                    356:     }
                    357: 
                    358:     ngx_add_timer(rev, c->listening->post_accept_timeout);
                    359:     ngx_reusable_connection(c, 1);
                    360: 
                    361:     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                    362:         ngx_http_close_connection(c);
                    363:         return;
                    364:     }
                    365: }
                    366: 
                    367: 
                    368: static void
                    369: ngx_http_wait_request_handler(ngx_event_t *rev)
                    370: {
                    371:     size_t                     size;
                    372:     ssize_t                    n;
                    373:     ngx_buf_t                 *b;
                    374:     ngx_connection_t          *c;
                    375:     ngx_http_connection_t     *hc;
                    376:     ngx_http_core_srv_conf_t  *cscf;
                    377: 
                    378:     c = rev->data;
                    379: 
                    380:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
                    381: 
                    382:     if (rev->timedout) {
                    383:         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
                    384:         ngx_http_close_connection(c);
                    385:         return;
                    386:     }
                    387: 
                    388:     if (c->close) {
                    389:         ngx_http_close_connection(c);
                    390:         return;
                    391:     }
                    392: 
                    393:     hc = c->data;
                    394:     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
                    395: 
                    396:     size = cscf->client_header_buffer_size;
                    397: 
                    398:     b = c->buffer;
                    399: 
                    400:     if (b == NULL) {
                    401:         b = ngx_create_temp_buf(c->pool, size);
                    402:         if (b == NULL) {
                    403:             ngx_http_close_connection(c);
                    404:             return;
                    405:         }
                    406: 
                    407:         c->buffer = b;
                    408: 
                    409:     } else if (b->start == NULL) {
                    410: 
                    411:         b->start = ngx_palloc(c->pool, size);
                    412:         if (b->start == NULL) {
                    413:             ngx_http_close_connection(c);
                    414:             return;
                    415:         }
                    416: 
                    417:         b->pos = b->start;
                    418:         b->last = b->start;
                    419:         b->end = b->last + size;
                    420:     }
                    421: 
                    422:     n = c->recv(c, b->last, size);
                    423: 
                    424:     if (n == NGX_AGAIN) {
                    425: 
                    426: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
                    427:         if (c->listening->deferred_accept
                    428: #if (NGX_HTTP_SSL)
                    429:             && c->ssl == NULL
                    430: #endif
                    431:             )
                    432:         {
                    433:             ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
                    434:                           "client timed out in deferred accept");
                    435:             ngx_http_close_connection(c);
                    436:             return;
                    437:         }
                    438: #endif
                    439: 
                    440:         if (!rev->timer_set) {
                    441:             ngx_add_timer(rev, c->listening->post_accept_timeout);
                    442:             ngx_reusable_connection(c, 1);
                    443:         }
                    444: 
                    445:         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                    446:             ngx_http_close_connection(c);
                    447:             return;
                    448:         }
                    449: 
                    450:         /*
                    451:          * We are trying to not hold c->buffer's memory for an idle connection.
                    452:          */
                    453: 
                    454:         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
                    455:             b->start = NULL;
                    456:         }
                    457: 
                    458:         return;
                    459:     }
                    460: 
                    461:     if (n == NGX_ERROR) {
                    462:         ngx_http_close_connection(c);
                    463:         return;
                    464:     }
                    465: 
                    466:     if (n == 0) {
                    467:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                    468:                       "client closed connection");
                    469:         ngx_http_close_connection(c);
                    470:         return;
                    471:     }
                    472: 
                    473:     b->last += n;
                    474: 
                    475:     c->log->action = "reading client request line";
                    476: 
                    477:     ngx_reusable_connection(c, 0);
                    478: 
                    479:     c->data = ngx_http_create_request(c);
                    480:     if (c->data == NULL) {
                    481:         ngx_http_close_connection(c);
                    482:         return;
                    483:     }
                    484: 
                    485:     rev->handler = ngx_http_process_request_line;
                    486:     ngx_http_process_request_line(rev);
                    487: }
                    488: 
                    489: 
                    490: ngx_http_request_t *
                    491: ngx_http_create_request(ngx_connection_t *c)
                    492: {
                    493:     ngx_pool_t                 *pool;
                    494:     ngx_time_t                 *tp;
                    495:     ngx_http_request_t         *r;
                    496:     ngx_http_log_ctx_t         *ctx;
                    497:     ngx_http_connection_t      *hc;
                    498:     ngx_http_core_srv_conf_t   *cscf;
                    499:     ngx_http_core_loc_conf_t   *clcf;
                    500:     ngx_http_core_main_conf_t  *cmcf;
                    501: 
                    502:     c->requests++;
                    503: 
                    504:     hc = c->data;
                    505: 
                    506:     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
                    507: 
                    508:     pool = ngx_create_pool(cscf->request_pool_size, c->log);
                    509:     if (pool == NULL) {
                    510:         return NULL;
                    511:     }
                    512: 
                    513:     r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
                    514:     if (r == NULL) {
                    515:         ngx_destroy_pool(pool);
                    516:         return NULL;
                    517:     }
                    518: 
                    519:     r->pool = pool;
                    520: 
                    521:     r->http_connection = hc;
                    522:     r->signature = NGX_HTTP_MODULE;
                    523:     r->connection = c;
                    524: 
                    525:     r->main_conf = hc->conf_ctx->main_conf;
                    526:     r->srv_conf = hc->conf_ctx->srv_conf;
                    527:     r->loc_conf = hc->conf_ctx->loc_conf;
                    528: 
                    529:     r->read_event_handler = ngx_http_block_reading;
                    530: 
                    531:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                    532: 
                    533:     ngx_http_set_connection_log(r->connection, clcf->error_log);
                    534: 
                    535:     r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
                    536: 
                    537:     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
                    538:                       sizeof(ngx_table_elt_t))
                    539:         != NGX_OK)
                    540:     {
                    541:         ngx_destroy_pool(r->pool);
                    542:         return NULL;
                    543:     }
                    544: 
                    545:     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
                    546:     if (r->ctx == NULL) {
                    547:         ngx_destroy_pool(r->pool);
                    548:         return NULL;
                    549:     }
                    550: 
                    551:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                    552: 
                    553:     r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
                    554:                                         * sizeof(ngx_http_variable_value_t));
                    555:     if (r->variables == NULL) {
                    556:         ngx_destroy_pool(r->pool);
                    557:         return NULL;
                    558:     }
                    559: 
                    560: #if (NGX_HTTP_SSL)
                    561:     if (c->ssl) {
                    562:         r->main_filter_need_in_memory = 1;
                    563:     }
                    564: #endif
                    565: 
                    566:     r->main = r;
                    567:     r->count = 1;
                    568: 
                    569:     tp = ngx_timeofday();
                    570:     r->start_sec = tp->sec;
                    571:     r->start_msec = tp->msec;
                    572: 
                    573:     r->method = NGX_HTTP_UNKNOWN;
                    574: 
                    575:     r->headers_in.content_length_n = -1;
                    576:     r->headers_in.keep_alive_n = -1;
                    577:     r->headers_out.content_length_n = -1;
                    578:     r->headers_out.last_modified_time = -1;
                    579: 
                    580:     r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
                    581:     r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
                    582: 
                    583:     r->http_state = NGX_HTTP_READING_REQUEST_STATE;
                    584: 
                    585:     ctx = c->log->data;
                    586:     ctx->request = r;
                    587:     ctx->current_request = r;
                    588:     r->log_handler = ngx_http_log_error_handler;
                    589: 
                    590: #if (NGX_STAT_STUB)
                    591:     (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
                    592:     r->stat_reading = 1;
                    593:     (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
                    594: #endif
                    595: 
                    596:     return r;
                    597: }
                    598: 
                    599: 
                    600: #if (NGX_HTTP_SSL)
                    601: 
                    602: static void
                    603: ngx_http_ssl_handshake(ngx_event_t *rev)
                    604: {
                    605:     u_char                    buf[1];
                    606:     ssize_t                   n;
                    607:     ngx_err_t                 err;
                    608:     ngx_int_t                 rc;
                    609:     ngx_connection_t         *c;
                    610:     ngx_http_connection_t    *hc;
                    611:     ngx_http_ssl_srv_conf_t  *sscf;
                    612: 
                    613:     c = rev->data;
                    614: 
                    615:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                    616:                    "http check ssl handshake");
                    617: 
                    618:     if (rev->timedout) {
                    619:         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
                    620:         ngx_http_close_connection(c);
                    621:         return;
                    622:     }
                    623: 
                    624:     if (c->close) {
                    625:         ngx_http_close_connection(c);
                    626:         return;
                    627:     }
                    628: 
                    629:     n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
                    630: 
                    631:     err = ngx_socket_errno;
                    632: 
                    633:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n);
                    634: 
                    635:     if (n == -1) {
                    636:         if (err == NGX_EAGAIN) {
                    637: 
                    638: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
                    639:             if (c->listening->deferred_accept) {
                    640:                 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
                    641:                               "client timed out in deferred accept");
                    642:                 ngx_http_close_connection(c);
                    643:                 return;
                    644:             }
                    645: #endif
                    646: 
                    647:             if (!rev->timer_set) {
                    648:                 ngx_add_timer(rev, c->listening->post_accept_timeout);
                    649:                 ngx_reusable_connection(c, 1);
                    650:             }
                    651: 
                    652:             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                    653:                 ngx_http_close_connection(c);
                    654:             }
                    655: 
                    656:             return;
                    657:         }
                    658: 
                    659:         ngx_connection_error(c, err, "recv() failed");
                    660:         ngx_http_close_connection(c);
                    661: 
                    662:         return;
                    663:     }
                    664: 
                    665:     if (n == 1) {
                    666:         if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
                    667:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                    668:                            "https ssl handshake: 0x%02Xd", buf[0]);
                    669: 
                    670:             hc = c->data;
                    671:             sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
                    672:                                                 ngx_http_ssl_module);
                    673: 
                    674:             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
                    675:                 != NGX_OK)
                    676:             {
                    677:                 ngx_http_close_connection(c);
                    678:                 return;
                    679:             }
                    680: 
                    681:             rc = ngx_ssl_handshake(c);
                    682: 
                    683:             if (rc == NGX_AGAIN) {
                    684: 
                    685:                 if (!rev->timer_set) {
                    686:                     ngx_add_timer(rev, c->listening->post_accept_timeout);
                    687:                 }
                    688: 
                    689:                 ngx_reusable_connection(c, 0);
                    690: 
                    691:                 c->ssl->handler = ngx_http_ssl_handshake_handler;
                    692:                 return;
                    693:             }
                    694: 
                    695:             ngx_http_ssl_handshake_handler(c);
                    696: 
                    697:             return;
                    698:         }
                    699: 
                    700:         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
                    701: 
                    702:         c->log->action = "waiting for request";
                    703: 
                    704:         rev->handler = ngx_http_wait_request_handler;
                    705:         ngx_http_wait_request_handler(rev);
                    706: 
                    707:         return;
                    708:     }
                    709: 
                    710:     ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
                    711:     ngx_http_close_connection(c);
                    712: }
                    713: 
                    714: 
                    715: static void
                    716: ngx_http_ssl_handshake_handler(ngx_connection_t *c)
                    717: {
                    718:     if (c->ssl->handshaked) {
                    719: 
                    720:         /*
                    721:          * The majority of browsers do not send the "close notify" alert.
                    722:          * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
                    723:          * and Links.  And what is more, MSIE ignores the server's alert.
                    724:          *
                    725:          * Opera and recent Mozilla send the alert.
                    726:          */
                    727: 
                    728:         c->ssl->no_wait_shutdown = 1;
                    729: 
                    730: #if (NGX_HTTP_SPDY && defined TLSEXT_TYPE_next_proto_neg)
                    731:         {
                    732:         unsigned int             len;
                    733:         const unsigned char     *data;
                    734:         static const ngx_str_t   spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED);
                    735: 
                    736:         SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
                    737: 
                    738:         if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) {
                    739:             ngx_http_spdy_init(c->read);
                    740:             return;
                    741:         }
                    742:         }
                    743: #endif
                    744: 
                    745:         c->log->action = "waiting for request";
                    746: 
                    747:         c->read->handler = ngx_http_wait_request_handler;
                    748:         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
                    749: 
                    750:         ngx_reusable_connection(c, 1);
                    751: 
                    752:         ngx_http_wait_request_handler(c->read);
                    753: 
                    754:         return;
                    755:     }
                    756: 
                    757:     if (c->read->timedout) {
                    758:         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
                    759:     }
                    760: 
                    761:     ngx_http_close_connection(c);
                    762: }
                    763: 
                    764: #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
                    765: 
                    766: int
                    767: ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
                    768: {
                    769:     ngx_str_t                  host;
                    770:     const char                *servername;
                    771:     ngx_connection_t          *c;
                    772:     ngx_http_connection_t     *hc;
                    773:     ngx_http_ssl_srv_conf_t   *sscf;
                    774:     ngx_http_core_loc_conf_t  *clcf;
                    775:     ngx_http_core_srv_conf_t  *cscf;
                    776: 
                    777:     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
                    778: 
                    779:     if (servername == NULL) {
                    780:         return SSL_TLSEXT_ERR_NOACK;
                    781:     }
                    782: 
                    783:     c = ngx_ssl_get_connection(ssl_conn);
                    784: 
                    785:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    786:                    "SSL server name: \"%s\"", servername);
                    787: 
                    788:     host.len = ngx_strlen(servername);
                    789: 
                    790:     if (host.len == 0) {
                    791:         return SSL_TLSEXT_ERR_NOACK;
                    792:     }
                    793: 
                    794:     host.data = (u_char *) servername;
                    795: 
                    796:     if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) {
                    797:         return SSL_TLSEXT_ERR_NOACK;
                    798:     }
                    799: 
                    800:     hc = c->data;
                    801: 
                    802:     if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
                    803:                                      NULL, &cscf)
                    804:         != NGX_OK)
                    805:     {
                    806:         return SSL_TLSEXT_ERR_NOACK;
                    807:     }
                    808: 
                    809:     hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
                    810:     if (hc->ssl_servername == NULL) {
                    811:         return SSL_TLSEXT_ERR_NOACK;
                    812:     }
                    813: 
                    814:     *hc->ssl_servername = host;
                    815: 
                    816:     hc->conf_ctx = cscf->ctx;
                    817: 
                    818:     clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
                    819: 
                    820:     ngx_http_set_connection_log(c, clcf->error_log);
                    821: 
                    822:     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
                    823: 
                    824:     if (sscf->ssl.ctx) {
                    825:         SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
                    826: 
                    827:         /*
                    828:          * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
                    829:          * adjust other things we care about
                    830:          */
                    831: 
                    832:         SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
                    833:                        SSL_CTX_get_verify_callback(sscf->ssl.ctx));
                    834: 
                    835:         SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
                    836: 
                    837: #ifdef SSL_CTRL_CLEAR_OPTIONS
                    838:         /* only in 0.9.8m+ */
                    839:         SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
                    840:                                     ~SSL_CTX_get_options(sscf->ssl.ctx));
                    841: #endif
                    842: 
                    843:         SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
                    844:     }
                    845: 
                    846:     return SSL_TLSEXT_ERR_OK;
                    847: }
                    848: 
                    849: #endif
                    850: 
                    851: #endif
                    852: 
                    853: 
                    854: static void
                    855: ngx_http_process_request_line(ngx_event_t *rev)
                    856: {
                    857:     ssize_t              n;
                    858:     ngx_int_t            rc, rv;
                    859:     ngx_str_t            host;
                    860:     ngx_connection_t    *c;
                    861:     ngx_http_request_t  *r;
                    862: 
                    863:     c = rev->data;
                    864:     r = c->data;
                    865: 
                    866:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                    867:                    "http process request line");
                    868: 
                    869:     if (rev->timedout) {
                    870:         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
                    871:         c->timedout = 1;
                    872:         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
                    873:         return;
                    874:     }
                    875: 
                    876:     rc = NGX_AGAIN;
                    877: 
                    878:     for ( ;; ) {
                    879: 
                    880:         if (rc == NGX_AGAIN) {
                    881:             n = ngx_http_read_request_header(r);
                    882: 
                    883:             if (n == NGX_AGAIN || n == NGX_ERROR) {
                    884:                 return;
                    885:             }
                    886:         }
                    887: 
                    888:         rc = ngx_http_parse_request_line(r, r->header_in);
                    889: 
                    890:         if (rc == NGX_OK) {
                    891: 
                    892:             /* the request line has been parsed successfully */
                    893: 
                    894:             r->request_line.len = r->request_end - r->request_start;
                    895:             r->request_line.data = r->request_start;
                    896:             r->request_length = r->header_in->pos - r->request_start;
                    897: 
                    898:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    899:                            "http request line: \"%V\"", &r->request_line);
                    900: 
                    901:             r->method_name.len = r->method_end - r->request_start + 1;
                    902:             r->method_name.data = r->request_line.data;
                    903: 
                    904:             if (r->http_protocol.data) {
                    905:                 r->http_protocol.len = r->request_end - r->http_protocol.data;
                    906:             }
                    907: 
                    908:             if (ngx_http_process_request_uri(r) != NGX_OK) {
                    909:                 return;
                    910:             }
                    911: 
                    912:             if (r->host_start && r->host_end) {
                    913: 
                    914:                 host.len = r->host_end - r->host_start;
                    915:                 host.data = r->host_start;
                    916: 
                    917:                 rc = ngx_http_validate_host(&host, r->pool, 0);
                    918: 
                    919:                 if (rc == NGX_DECLINED) {
                    920:                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
                    921:                                   "client sent invalid host in request line");
                    922:                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                    923:                     return;
                    924:                 }
                    925: 
                    926:                 if (rc == NGX_ERROR) {
                    927:                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                    928:                     return;
                    929:                 }
                    930: 
                    931:                 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
                    932:                     return;
                    933:                 }
                    934: 
                    935:                 r->headers_in.server = host;
                    936:             }
                    937: 
                    938:             if (r->http_version < NGX_HTTP_VERSION_10) {
                    939: 
                    940:                 if (r->headers_in.server.len == 0
                    941:                     && ngx_http_set_virtual_server(r, &r->headers_in.server)
                    942:                        == NGX_ERROR)
                    943:                 {
                    944:                     return;
                    945:                 }
                    946: 
                    947:                 ngx_http_process_request(r);
                    948:                 return;
                    949:             }
                    950: 
                    951: 
                    952:             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
                    953:                               sizeof(ngx_table_elt_t))
                    954:                 != NGX_OK)
                    955:             {
                    956:                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                    957:                 return;
                    958:             }
                    959: 
                    960:             c->log->action = "reading client request headers";
                    961: 
                    962:             rev->handler = ngx_http_process_request_headers;
                    963:             ngx_http_process_request_headers(rev);
                    964: 
                    965:             return;
                    966:         }
                    967: 
                    968:         if (rc != NGX_AGAIN) {
                    969: 
                    970:             /* there was error while a request line parsing */
                    971: 
                    972:             ngx_log_error(NGX_LOG_INFO, c->log, 0,
                    973:                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
                    974:             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                    975:             return;
                    976:         }
                    977: 
                    978:         /* NGX_AGAIN: a request line parsing is still incomplete */
                    979: 
                    980:         if (r->header_in->pos == r->header_in->end) {
                    981: 
                    982:             rv = ngx_http_alloc_large_header_buffer(r, 1);
                    983: 
                    984:             if (rv == NGX_ERROR) {
                    985:                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                    986:                 return;
                    987:             }
                    988: 
                    989:             if (rv == NGX_DECLINED) {
                    990:                 r->request_line.len = r->header_in->end - r->request_start;
                    991:                 r->request_line.data = r->request_start;
                    992: 
                    993:                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
                    994:                               "client sent too long URI");
                    995:                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
                    996:                 return;
                    997:             }
                    998:         }
                    999:     }
                   1000: }
                   1001: 
                   1002: 
                   1003: ngx_int_t
                   1004: ngx_http_process_request_uri(ngx_http_request_t *r)
                   1005: {
                   1006:     ngx_http_core_srv_conf_t  *cscf;
                   1007: 
                   1008:     if (r->args_start) {
                   1009:         r->uri.len = r->args_start - 1 - r->uri_start;
                   1010:     } else {
                   1011:         r->uri.len = r->uri_end - r->uri_start;
                   1012:     }
                   1013: 
                   1014:     if (r->complex_uri || r->quoted_uri) {
                   1015: 
                   1016:         r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
                   1017:         if (r->uri.data == NULL) {
                   1018:             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1019:             return NGX_ERROR;
                   1020:         }
                   1021: 
                   1022:         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   1023: 
                   1024:         if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
                   1025:             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1026:                           "client sent invalid request");
                   1027:             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1028:             return NGX_ERROR;
                   1029:         }
                   1030: 
                   1031:     } else {
                   1032:         r->uri.data = r->uri_start;
                   1033:     }
                   1034: 
                   1035:     r->unparsed_uri.len = r->uri_end - r->uri_start;
                   1036:     r->unparsed_uri.data = r->uri_start;
                   1037: 
                   1038:     r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
                   1039: 
                   1040:     if (r->uri_ext) {
                   1041:         if (r->args_start) {
                   1042:             r->exten.len = r->args_start - 1 - r->uri_ext;
                   1043:         } else {
                   1044:             r->exten.len = r->uri_end - r->uri_ext;
                   1045:         }
                   1046: 
                   1047:         r->exten.data = r->uri_ext;
                   1048:     }
                   1049: 
                   1050:     if (r->args_start && r->uri_end > r->args_start) {
                   1051:         r->args.len = r->uri_end - r->args_start;
                   1052:         r->args.data = r->args_start;
                   1053:     }
                   1054: 
                   1055: #if (NGX_WIN32)
                   1056:     {
                   1057:     u_char  *p, *last;
                   1058: 
                   1059:     p = r->uri.data;
                   1060:     last = r->uri.data + r->uri.len;
                   1061: 
                   1062:     while (p < last) {
                   1063: 
                   1064:         if (*p++ == ':') {
                   1065: 
                   1066:             /*
                   1067:              * this check covers "::$data", "::$index_allocation" and
                   1068:              * ":$i30:$index_allocation"
                   1069:              */
                   1070: 
                   1071:             if (p < last && *p == '$') {
                   1072:                 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1073:                               "client sent unsafe win32 URI");
                   1074:                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1075:                 return NGX_ERROR;
                   1076:             }
                   1077:         }
                   1078:     }
                   1079: 
                   1080:     p = r->uri.data + r->uri.len - 1;
                   1081: 
                   1082:     while (p > r->uri.data) {
                   1083: 
                   1084:         if (*p == ' ') {
                   1085:             p--;
                   1086:             continue;
                   1087:         }
                   1088: 
                   1089:         if (*p == '.') {
                   1090:             p--;
                   1091:             continue;
                   1092:         }
                   1093: 
                   1094:         break;
                   1095:     }
                   1096: 
                   1097:     if (p != r->uri.data + r->uri.len - 1) {
                   1098:         r->uri.len = p + 1 - r->uri.data;
                   1099:         ngx_http_set_exten(r);
                   1100:     }
                   1101: 
                   1102:     }
                   1103: #endif
                   1104: 
                   1105:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1106:                    "http uri: \"%V\"", &r->uri);
                   1107: 
                   1108:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1109:                    "http args: \"%V\"", &r->args);
                   1110: 
                   1111:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1112:                    "http exten: \"%V\"", &r->exten);
                   1113: 
                   1114:     return NGX_OK;
                   1115: }
                   1116: 
                   1117: 
                   1118: static void
                   1119: ngx_http_process_request_headers(ngx_event_t *rev)
                   1120: {
                   1121:     u_char                     *p;
                   1122:     size_t                      len;
                   1123:     ssize_t                     n;
                   1124:     ngx_int_t                   rc, rv;
                   1125:     ngx_table_elt_t            *h;
                   1126:     ngx_connection_t           *c;
                   1127:     ngx_http_header_t          *hh;
                   1128:     ngx_http_request_t         *r;
                   1129:     ngx_http_core_srv_conf_t   *cscf;
                   1130:     ngx_http_core_main_conf_t  *cmcf;
                   1131: 
                   1132:     c = rev->data;
                   1133:     r = c->data;
                   1134: 
                   1135:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                   1136:                    "http process request header line");
                   1137: 
                   1138:     if (rev->timedout) {
                   1139:         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
                   1140:         c->timedout = 1;
                   1141:         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
                   1142:         return;
                   1143:     }
                   1144: 
                   1145:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                   1146: 
                   1147:     rc = NGX_AGAIN;
                   1148: 
                   1149:     for ( ;; ) {
                   1150: 
                   1151:         if (rc == NGX_AGAIN) {
                   1152: 
                   1153:             if (r->header_in->pos == r->header_in->end) {
                   1154: 
                   1155:                 rv = ngx_http_alloc_large_header_buffer(r, 0);
                   1156: 
                   1157:                 if (rv == NGX_ERROR) {
                   1158:                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1159:                     return;
                   1160:                 }
                   1161: 
                   1162:                 if (rv == NGX_DECLINED) {
                   1163:                     p = r->header_name_start;
                   1164: 
                   1165:                     r->lingering_close = 1;
                   1166: 
                   1167:                     if (p == NULL) {
                   1168:                         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1169:                                       "client sent too large request");
                   1170:                         ngx_http_finalize_request(r,
                   1171:                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
                   1172:                         return;
                   1173:                     }
                   1174: 
                   1175:                     len = r->header_in->end - p;
                   1176: 
                   1177:                     if (len > NGX_MAX_ERROR_STR - 300) {
                   1178:                         len = NGX_MAX_ERROR_STR - 300;
                   1179:                         p[len++] = '.'; p[len++] = '.'; p[len++] = '.';
                   1180:                     }
                   1181: 
                   1182:                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1183:                                   "client sent too long header line: \"%*s\"",
                   1184:                                   len, r->header_name_start);
                   1185: 
                   1186:                     ngx_http_finalize_request(r,
                   1187:                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
                   1188:                     return;
                   1189:                 }
                   1190:             }
                   1191: 
                   1192:             n = ngx_http_read_request_header(r);
                   1193: 
                   1194:             if (n == NGX_AGAIN || n == NGX_ERROR) {
                   1195:                 return;
                   1196:             }
                   1197:         }
                   1198: 
                   1199:         /* the host header could change the server configuration context */
                   1200:         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   1201: 
                   1202:         rc = ngx_http_parse_header_line(r, r->header_in,
                   1203:                                         cscf->underscores_in_headers);
                   1204: 
                   1205:         if (rc == NGX_OK) {
                   1206: 
                   1207:             r->request_length += r->header_in->pos - r->header_name_start;
                   1208: 
                   1209:             if (r->invalid_header && cscf->ignore_invalid_headers) {
                   1210: 
                   1211:                 /* there was error while a header line parsing */
                   1212: 
                   1213:                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1214:                               "client sent invalid header line: \"%*s\"",
                   1215:                               r->header_end - r->header_name_start,
                   1216:                               r->header_name_start);
                   1217:                 continue;
                   1218:             }
                   1219: 
                   1220:             /* a header line has been parsed successfully */
                   1221: 
                   1222:             h = ngx_list_push(&r->headers_in.headers);
                   1223:             if (h == NULL) {
                   1224:                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1225:                 return;
                   1226:             }
                   1227: 
                   1228:             h->hash = r->header_hash;
                   1229: 
                   1230:             h->key.len = r->header_name_end - r->header_name_start;
                   1231:             h->key.data = r->header_name_start;
                   1232:             h->key.data[h->key.len] = '\0';
                   1233: 
                   1234:             h->value.len = r->header_end - r->header_start;
                   1235:             h->value.data = r->header_start;
                   1236:             h->value.data[h->value.len] = '\0';
                   1237: 
                   1238:             h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
                   1239:             if (h->lowcase_key == NULL) {
                   1240:                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1241:                 return;
                   1242:             }
                   1243: 
                   1244:             if (h->key.len == r->lowcase_index) {
                   1245:                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
                   1246: 
                   1247:             } else {
                   1248:                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
                   1249:             }
                   1250: 
                   1251:             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
                   1252:                                h->lowcase_key, h->key.len);
                   1253: 
                   1254:             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
                   1255:                 return;
                   1256:             }
                   1257: 
                   1258:             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1259:                            "http header: \"%V: %V\"",
                   1260:                            &h->key, &h->value);
                   1261: 
                   1262:             continue;
                   1263:         }
                   1264: 
                   1265:         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
                   1266: 
                   1267:             /* a whole header has been parsed successfully */
                   1268: 
                   1269:             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1270:                            "http header done");
                   1271: 
                   1272:             r->request_length += r->header_in->pos - r->header_name_start;
                   1273: 
                   1274:             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
                   1275: 
                   1276:             rc = ngx_http_process_request_header(r);
                   1277: 
                   1278:             if (rc != NGX_OK) {
                   1279:                 return;
                   1280:             }
                   1281: 
                   1282:             ngx_http_process_request(r);
                   1283: 
                   1284:             return;
                   1285:         }
                   1286: 
                   1287:         if (rc == NGX_AGAIN) {
                   1288: 
                   1289:             /* a header line parsing is still not complete */
                   1290: 
                   1291:             continue;
                   1292:         }
                   1293: 
                   1294:         /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
                   1295: 
                   1296:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1297:                       "client sent invalid header line: \"%*s\\r...\"",
                   1298:                       r->header_end - r->header_name_start,
                   1299:                       r->header_name_start);
                   1300:         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1301:         return;
                   1302:     }
                   1303: }
                   1304: 
                   1305: 
                   1306: static ssize_t
                   1307: ngx_http_read_request_header(ngx_http_request_t *r)
                   1308: {
                   1309:     ssize_t                    n;
                   1310:     ngx_event_t               *rev;
                   1311:     ngx_connection_t          *c;
                   1312:     ngx_http_core_srv_conf_t  *cscf;
                   1313: 
                   1314:     c = r->connection;
                   1315:     rev = c->read;
                   1316: 
                   1317:     n = r->header_in->last - r->header_in->pos;
                   1318: 
                   1319:     if (n > 0) {
                   1320:         return n;
                   1321:     }
                   1322: 
                   1323:     if (rev->ready) {
                   1324:         n = c->recv(c, r->header_in->last,
                   1325:                     r->header_in->end - r->header_in->last);
                   1326:     } else {
                   1327:         n = NGX_AGAIN;
                   1328:     }
                   1329: 
                   1330:     if (n == NGX_AGAIN) {
                   1331:         if (!rev->timer_set) {
                   1332:             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   1333:             ngx_add_timer(rev, cscf->client_header_timeout);
                   1334:         }
                   1335: 
                   1336:         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                   1337:             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1338:             return NGX_ERROR;
                   1339:         }
                   1340: 
                   1341:         return NGX_AGAIN;
                   1342:     }
                   1343: 
                   1344:     if (n == 0) {
                   1345:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1346:                       "client prematurely closed connection");
                   1347:     }
                   1348: 
                   1349:     if (n == 0 || n == NGX_ERROR) {
                   1350:         c->error = 1;
                   1351:         c->log->action = "reading client request headers";
                   1352: 
                   1353:         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1354:         return NGX_ERROR;
                   1355:     }
                   1356: 
                   1357:     r->header_in->last += n;
                   1358: 
                   1359:     return n;
                   1360: }
                   1361: 
                   1362: 
                   1363: static ngx_int_t
                   1364: ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
                   1365:     ngx_uint_t request_line)
                   1366: {
                   1367:     u_char                    *old, *new;
                   1368:     ngx_buf_t                 *b;
                   1369:     ngx_http_connection_t     *hc;
                   1370:     ngx_http_core_srv_conf_t  *cscf;
                   1371: 
                   1372:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1373:                    "http alloc large header buffer");
                   1374: 
                   1375:     if (request_line && r->state == 0) {
                   1376: 
                   1377:         /* the client fills up the buffer with "\r\n" */
                   1378: 
                   1379:         r->header_in->pos = r->header_in->start;
                   1380:         r->header_in->last = r->header_in->start;
                   1381: 
                   1382:         return NGX_OK;
                   1383:     }
                   1384: 
                   1385:     old = request_line ? r->request_start : r->header_name_start;
                   1386: 
                   1387:     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   1388: 
                   1389:     if (r->state != 0
                   1390:         && (size_t) (r->header_in->pos - old)
                   1391:                                      >= cscf->large_client_header_buffers.size)
                   1392:     {
                   1393:         return NGX_DECLINED;
                   1394:     }
                   1395: 
                   1396:     hc = r->http_connection;
                   1397: 
                   1398:     if (hc->nfree) {
                   1399:         b = hc->free[--hc->nfree];
                   1400: 
                   1401:         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1402:                        "http large header free: %p %uz",
                   1403:                        b->pos, b->end - b->last);
                   1404: 
                   1405:     } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
                   1406: 
                   1407:         if (hc->busy == NULL) {
                   1408:             hc->busy = ngx_palloc(r->connection->pool,
                   1409:                   cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
                   1410:             if (hc->busy == NULL) {
                   1411:                 return NGX_ERROR;
                   1412:             }
                   1413:         }
                   1414: 
                   1415:         b = ngx_create_temp_buf(r->connection->pool,
                   1416:                                 cscf->large_client_header_buffers.size);
                   1417:         if (b == NULL) {
                   1418:             return NGX_ERROR;
                   1419:         }
                   1420: 
                   1421:         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1422:                        "http large header alloc: %p %uz",
                   1423:                        b->pos, b->end - b->last);
                   1424: 
                   1425:     } else {
                   1426:         return NGX_DECLINED;
                   1427:     }
                   1428: 
                   1429:     hc->busy[hc->nbusy++] = b;
                   1430: 
                   1431:     if (r->state == 0) {
                   1432:         /*
                   1433:          * r->state == 0 means that a header line was parsed successfully
                   1434:          * and we do not need to copy incomplete header line and
                   1435:          * to relocate the parser header pointers
                   1436:          */
                   1437: 
                   1438:         r->header_in = b;
                   1439: 
                   1440:         return NGX_OK;
                   1441:     }
                   1442: 
                   1443:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1444:                    "http large header copy: %d", r->header_in->pos - old);
                   1445: 
                   1446:     new = b->start;
                   1447: 
                   1448:     ngx_memcpy(new, old, r->header_in->pos - old);
                   1449: 
                   1450:     b->pos = new + (r->header_in->pos - old);
                   1451:     b->last = new + (r->header_in->pos - old);
                   1452: 
                   1453:     if (request_line) {
                   1454:         r->request_start = new;
                   1455: 
                   1456:         if (r->request_end) {
                   1457:             r->request_end = new + (r->request_end - old);
                   1458:         }
                   1459: 
                   1460:         r->method_end = new + (r->method_end - old);
                   1461: 
                   1462:         r->uri_start = new + (r->uri_start - old);
                   1463:         r->uri_end = new + (r->uri_end - old);
                   1464: 
                   1465:         if (r->schema_start) {
                   1466:             r->schema_start = new + (r->schema_start - old);
                   1467:             r->schema_end = new + (r->schema_end - old);
                   1468:         }
                   1469: 
                   1470:         if (r->host_start) {
                   1471:             r->host_start = new + (r->host_start - old);
                   1472:             if (r->host_end) {
                   1473:                 r->host_end = new + (r->host_end - old);
                   1474:             }
                   1475:         }
                   1476: 
                   1477:         if (r->port_start) {
                   1478:             r->port_start = new + (r->port_start - old);
                   1479:             r->port_end = new + (r->port_end - old);
                   1480:         }
                   1481: 
                   1482:         if (r->uri_ext) {
                   1483:             r->uri_ext = new + (r->uri_ext - old);
                   1484:         }
                   1485: 
                   1486:         if (r->args_start) {
                   1487:             r->args_start = new + (r->args_start - old);
                   1488:         }
                   1489: 
                   1490:         if (r->http_protocol.data) {
                   1491:             r->http_protocol.data = new + (r->http_protocol.data - old);
                   1492:         }
                   1493: 
                   1494:     } else {
                   1495:         r->header_name_start = new;
                   1496:         r->header_name_end = new + (r->header_name_end - old);
                   1497:         r->header_start = new + (r->header_start - old);
                   1498:         r->header_end = new + (r->header_end - old);
                   1499:     }
                   1500: 
                   1501:     r->header_in = b;
                   1502: 
                   1503:     return NGX_OK;
                   1504: }
                   1505: 
                   1506: 
                   1507: static ngx_int_t
                   1508: ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
                   1509:     ngx_uint_t offset)
                   1510: {
                   1511:     ngx_table_elt_t  **ph;
                   1512: 
                   1513:     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
                   1514: 
                   1515:     if (*ph == NULL) {
                   1516:         *ph = h;
                   1517:     }
                   1518: 
                   1519:     return NGX_OK;
                   1520: }
                   1521: 
                   1522: 
                   1523: static ngx_int_t
                   1524: ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
                   1525:     ngx_uint_t offset)
                   1526: {
                   1527:     ngx_table_elt_t  **ph;
                   1528: 
                   1529:     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
                   1530: 
                   1531:     if (*ph == NULL) {
                   1532:         *ph = h;
                   1533:         return NGX_OK;
                   1534:     }
                   1535: 
                   1536:     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1537:                   "client sent duplicate header line: \"%V: %V\", "
                   1538:                   "previous value: \"%V: %V\"",
                   1539:                   &h->key, &h->value, &(*ph)->key, &(*ph)->value);
                   1540: 
                   1541:     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1542: 
                   1543:     return NGX_ERROR;
                   1544: }
                   1545: 
                   1546: 
                   1547: static ngx_int_t
                   1548: ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
                   1549:     ngx_uint_t offset)
                   1550: {
                   1551:     ngx_int_t  rc;
                   1552:     ngx_str_t  host;
                   1553: 
                   1554:     if (r->headers_in.host == NULL) {
                   1555:         r->headers_in.host = h;
                   1556:     }
                   1557: 
                   1558:     host = h->value;
                   1559: 
                   1560:     rc = ngx_http_validate_host(&host, r->pool, 0);
                   1561: 
                   1562:     if (rc == NGX_DECLINED) {
                   1563:         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1564:                       "client sent invalid host header");
                   1565:         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1566:         return NGX_ERROR;
                   1567:     }
                   1568: 
                   1569:     if (rc == NGX_ERROR) {
                   1570:         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1571:         return NGX_ERROR;
                   1572:     }
                   1573: 
                   1574:     if (r->headers_in.server.len) {
                   1575:         return NGX_OK;
                   1576:     }
                   1577: 
                   1578:     if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
                   1579:         return NGX_ERROR;
                   1580:     }
                   1581: 
                   1582:     r->headers_in.server = host;
                   1583: 
                   1584:     return NGX_OK;
                   1585: }
                   1586: 
                   1587: 
                   1588: static ngx_int_t
                   1589: ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
                   1590:     ngx_uint_t offset)
                   1591: {
                   1592:     if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
                   1593:         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
                   1594: 
                   1595:     } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
                   1596:         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
                   1597:     }
                   1598: 
                   1599:     return NGX_OK;
                   1600: }
                   1601: 
                   1602: 
                   1603: static ngx_int_t
                   1604: ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
                   1605:     ngx_uint_t offset)
                   1606: {
                   1607:     u_char  *user_agent, *msie;
                   1608: 
                   1609:     if (r->headers_in.user_agent) {
                   1610:         return NGX_OK;
                   1611:     }
                   1612: 
                   1613:     r->headers_in.user_agent = h;
                   1614: 
                   1615:     /* check some widespread browsers while the header is in CPU cache */
                   1616: 
                   1617:     user_agent = h->value.data;
                   1618: 
                   1619:     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
                   1620: 
                   1621:     if (msie && msie + 7 < user_agent + h->value.len) {
                   1622: 
                   1623:         r->headers_in.msie = 1;
                   1624: 
                   1625:         if (msie[6] == '.') {
                   1626: 
                   1627:             switch (msie[5]) {
                   1628:             case '4':
                   1629:             case '5':
                   1630:                 r->headers_in.msie6 = 1;
                   1631:                 break;
                   1632:             case '6':
                   1633:                 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
                   1634:                     r->headers_in.msie6 = 1;
                   1635:                 }
                   1636:                 break;
                   1637:             }
                   1638:         }
                   1639: 
                   1640: #if 0
                   1641:         /* MSIE ignores the SSL "close notify" alert */
                   1642:         if (c->ssl) {
                   1643:             c->ssl->no_send_shutdown = 1;
                   1644:         }
                   1645: #endif
                   1646:     }
                   1647: 
                   1648:     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
                   1649:         r->headers_in.opera = 1;
                   1650:         r->headers_in.msie = 0;
                   1651:         r->headers_in.msie6 = 0;
                   1652:     }
                   1653: 
                   1654:     if (!r->headers_in.msie && !r->headers_in.opera) {
                   1655: 
                   1656:         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
                   1657:             r->headers_in.gecko = 1;
                   1658: 
                   1659:         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
                   1660:             r->headers_in.chrome = 1;
                   1661: 
                   1662:         } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
                   1663:                    && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
                   1664:         {
                   1665:             r->headers_in.safari = 1;
                   1666: 
                   1667:         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
                   1668:             r->headers_in.konqueror = 1;
                   1669:         }
                   1670:     }
                   1671: 
                   1672:     return NGX_OK;
                   1673: }
                   1674: 
                   1675: 
                   1676: static ngx_int_t
                   1677: ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
                   1678:     ngx_uint_t offset)
                   1679: {
                   1680:     ngx_array_t       *headers;
                   1681:     ngx_table_elt_t  **ph;
                   1682: 
                   1683:     headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
                   1684: 
                   1685:     if (headers->elts == NULL) {
                   1686:         if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
                   1687:             != NGX_OK)
                   1688:         {
                   1689:             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1690:             return NGX_ERROR;
                   1691:         }
                   1692:     }
                   1693: 
                   1694:     ph = ngx_array_push(headers);
                   1695:     if (ph == NULL) {
                   1696:         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1697:         return NGX_ERROR;
                   1698:     }
                   1699: 
                   1700:     *ph = h;
                   1701:     return NGX_OK;
                   1702: }
                   1703: 
                   1704: 
                   1705: ngx_int_t
                   1706: ngx_http_process_request_header(ngx_http_request_t *r)
                   1707: {
                   1708:     if (r->headers_in.server.len == 0
                   1709:         && ngx_http_set_virtual_server(r, &r->headers_in.server)
                   1710:            == NGX_ERROR)
                   1711:     {
                   1712:         return NGX_ERROR;
                   1713:     }
                   1714: 
                   1715:     if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
                   1716:         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1717:                    "client sent HTTP/1.1 request without \"Host\" header");
                   1718:         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1719:         return NGX_ERROR;
                   1720:     }
                   1721: 
                   1722:     if (r->headers_in.content_length) {
                   1723:         r->headers_in.content_length_n =
                   1724:                             ngx_atoof(r->headers_in.content_length->value.data,
                   1725:                                       r->headers_in.content_length->value.len);
                   1726: 
                   1727:         if (r->headers_in.content_length_n == NGX_ERROR) {
                   1728:             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1729:                           "client sent invalid \"Content-Length\" header");
                   1730:             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   1731:             return NGX_ERROR;
                   1732:         }
                   1733:     }
                   1734: 
                   1735:     if (r->method & NGX_HTTP_TRACE) {
                   1736:         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1737:                       "client sent TRACE method");
                   1738:         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
                   1739:         return NGX_ERROR;
                   1740:     }
                   1741: 
                   1742:     if (r->headers_in.transfer_encoding) {
                   1743:         if (r->headers_in.transfer_encoding->value.len == 7
                   1744:             && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
                   1745:                                (u_char *) "chunked", 7) == 0)
                   1746:         {
                   1747:             r->headers_in.content_length = NULL;
                   1748:             r->headers_in.content_length_n = -1;
                   1749:             r->headers_in.chunked = 1;
                   1750: 
                   1751:         } else if (r->headers_in.transfer_encoding->value.len != 8
                   1752:             || ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
                   1753:                                (u_char *) "identity", 8) != 0)
                   1754:         {
                   1755:             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   1756:                           "client sent unknown \"Transfer-Encoding\": \"%V\"",
                   1757:                           &r->headers_in.transfer_encoding->value);
                   1758:             ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED);
                   1759:             return NGX_ERROR;
                   1760:         }
                   1761:     }
                   1762: 
                   1763:     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
                   1764:         if (r->headers_in.keep_alive) {
                   1765:             r->headers_in.keep_alive_n =
                   1766:                             ngx_atotm(r->headers_in.keep_alive->value.data,
                   1767:                                       r->headers_in.keep_alive->value.len);
                   1768:         }
                   1769:     }
                   1770: 
                   1771:     return NGX_OK;
                   1772: }
                   1773: 
                   1774: 
                   1775: void
                   1776: ngx_http_process_request(ngx_http_request_t *r)
                   1777: {
                   1778:     ngx_connection_t  *c;
                   1779: 
                   1780:     c = r->connection;
                   1781: 
                   1782: #if (NGX_HTTP_SSL)
                   1783: 
                   1784:     if (r->http_connection->ssl) {
                   1785:         long                      rc;
                   1786:         X509                     *cert;
                   1787:         ngx_http_ssl_srv_conf_t  *sscf;
                   1788: 
                   1789:         if (c->ssl == NULL) {
                   1790:             ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1791:                           "client sent plain HTTP request to HTTPS port");
                   1792:             ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
                   1793:             return;
                   1794:         }
                   1795: 
                   1796:         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
                   1797: 
                   1798:         if (sscf->verify) {
                   1799:             rc = SSL_get_verify_result(c->ssl->connection);
                   1800: 
                   1801:             if (rc != X509_V_OK
                   1802:                 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
                   1803:             {
                   1804:                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1805:                               "client SSL certificate verify error: (%l:%s)",
                   1806:                               rc, X509_verify_cert_error_string(rc));
                   1807: 
                   1808:                 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
                   1809:                                        (SSL_get0_session(c->ssl->connection)));
                   1810: 
                   1811:                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
                   1812:                 return;
                   1813:             }
                   1814: 
                   1815:             if (sscf->verify == 1) {
                   1816:                 cert = SSL_get_peer_certificate(c->ssl->connection);
                   1817: 
                   1818:                 if (cert == NULL) {
                   1819:                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1820:                                   "client sent no required SSL certificate");
                   1821: 
                   1822:                     ngx_ssl_remove_cached_session(sscf->ssl.ctx,
                   1823:                                        (SSL_get0_session(c->ssl->connection)));
                   1824: 
                   1825:                     ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
                   1826:                     return;
                   1827:                 }
                   1828: 
                   1829:                 X509_free(cert);
                   1830:             }
                   1831:         }
                   1832:     }
                   1833: 
                   1834: #endif
                   1835: 
                   1836:     if (c->read->timer_set) {
                   1837:         ngx_del_timer(c->read);
                   1838:     }
                   1839: 
                   1840: #if (NGX_STAT_STUB)
                   1841:     (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
                   1842:     r->stat_reading = 0;
                   1843:     (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
                   1844:     r->stat_writing = 1;
                   1845: #endif
                   1846: 
                   1847:     c->read->handler = ngx_http_request_handler;
                   1848:     c->write->handler = ngx_http_request_handler;
                   1849:     r->read_event_handler = ngx_http_block_reading;
                   1850: 
                   1851:     ngx_http_handler(r);
                   1852: 
                   1853:     ngx_http_run_posted_requests(c);
                   1854: }
                   1855: 
                   1856: 
                   1857: static ngx_int_t
                   1858: ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
                   1859: {
                   1860:     u_char  *h, ch;
                   1861:     size_t   i, dot_pos, host_len;
                   1862: 
                   1863:     enum {
                   1864:         sw_usual = 0,
                   1865:         sw_literal,
                   1866:         sw_rest
                   1867:     } state;
                   1868: 
                   1869:     dot_pos = host->len;
                   1870:     host_len = host->len;
                   1871: 
                   1872:     h = host->data;
                   1873: 
                   1874:     state = sw_usual;
                   1875: 
                   1876:     for (i = 0; i < host->len; i++) {
                   1877:         ch = h[i];
                   1878: 
                   1879:         switch (ch) {
                   1880: 
                   1881:         case '.':
                   1882:             if (dot_pos == i - 1) {
                   1883:                 return NGX_DECLINED;
                   1884:             }
                   1885:             dot_pos = i;
                   1886:             break;
                   1887: 
                   1888:         case ':':
                   1889:             if (state == sw_usual) {
                   1890:                 host_len = i;
                   1891:                 state = sw_rest;
                   1892:             }
                   1893:             break;
                   1894: 
                   1895:         case '[':
                   1896:             if (i == 0) {
                   1897:                 state = sw_literal;
                   1898:             }
                   1899:             break;
                   1900: 
                   1901:         case ']':
                   1902:             if (state == sw_literal) {
                   1903:                 host_len = i + 1;
                   1904:                 state = sw_rest;
                   1905:             }
                   1906:             break;
                   1907: 
                   1908:         case '\0':
                   1909:             return NGX_DECLINED;
                   1910: 
                   1911:         default:
                   1912: 
                   1913:             if (ngx_path_separator(ch)) {
                   1914:                 return NGX_DECLINED;
                   1915:             }
                   1916: 
                   1917:             if (ch >= 'A' && ch <= 'Z') {
                   1918:                 alloc = 1;
                   1919:             }
                   1920: 
                   1921:             break;
                   1922:         }
                   1923:     }
                   1924: 
                   1925:     if (dot_pos == host_len - 1) {
                   1926:         host_len--;
                   1927:     }
                   1928: 
                   1929:     if (host_len == 0) {
                   1930:         return NGX_DECLINED;
                   1931:     }
                   1932: 
                   1933:     if (alloc) {
                   1934:         host->data = ngx_pnalloc(pool, host_len);
                   1935:         if (host->data == NULL) {
                   1936:             return NGX_ERROR;
                   1937:         }
                   1938: 
                   1939:         ngx_strlow(host->data, h, host_len);
                   1940:     }
                   1941: 
                   1942:     host->len = host_len;
                   1943: 
                   1944:     return NGX_OK;
                   1945: }
                   1946: 
                   1947: 
                   1948: static ngx_int_t
                   1949: ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
                   1950: {
                   1951:     ngx_int_t                  rc;
                   1952:     ngx_http_connection_t     *hc;
                   1953:     ngx_http_core_loc_conf_t  *clcf;
                   1954:     ngx_http_core_srv_conf_t  *cscf;
                   1955: 
                   1956:     hc = r->http_connection;
                   1957: 
                   1958: #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
                   1959: 
                   1960:     if (hc->ssl_servername) {
                   1961:         if (hc->ssl_servername->len == host->len
                   1962:             && ngx_strncmp(hc->ssl_servername->data,
                   1963:                            host->data, host->len) == 0)
                   1964:         {
                   1965: #if (NGX_PCRE)
                   1966:             if (hc->ssl_servername_regex
                   1967:                 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
                   1968:                                           hc->ssl_servername) != NGX_OK)
                   1969:             {
                   1970:                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1971:                 return NGX_ERROR;
                   1972:             }
                   1973: #endif
                   1974:             return NGX_OK;
                   1975:         }
                   1976:     }
                   1977: 
                   1978: #endif
                   1979: 
                   1980:     rc = ngx_http_find_virtual_server(r->connection,
                   1981:                                       hc->addr_conf->virtual_names,
                   1982:                                       host, r, &cscf);
                   1983: 
                   1984:     if (rc == NGX_ERROR) {
                   1985:         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                   1986:         return NGX_ERROR;
                   1987:     }
                   1988: 
                   1989: #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
                   1990: 
                   1991:     if (hc->ssl_servername) {
                   1992:         ngx_http_ssl_srv_conf_t  *sscf;
                   1993: 
                   1994:         if (rc == NGX_DECLINED) {
                   1995:             cscf = hc->addr_conf->default_server;
                   1996:             rc = NGX_OK;
                   1997:         }
                   1998: 
                   1999:         sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
                   2000: 
                   2001:         if (sscf->verify) {
                   2002:             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                   2003:                           "client attempted to request the server name "
                   2004:                           "different from that one was negotiated");
                   2005:             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                   2006:             return NGX_ERROR;
                   2007:         }
                   2008:     }
                   2009: 
                   2010: #endif
                   2011: 
                   2012:     if (rc == NGX_DECLINED) {
                   2013:         return NGX_OK;
                   2014:     }
                   2015: 
                   2016:     r->srv_conf = cscf->ctx->srv_conf;
                   2017:     r->loc_conf = cscf->ctx->loc_conf;
                   2018: 
                   2019:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   2020: 
                   2021:     ngx_http_set_connection_log(r->connection, clcf->error_log);
                   2022: 
                   2023:     return NGX_OK;
                   2024: }
                   2025: 
                   2026: 
                   2027: static ngx_int_t
                   2028: ngx_http_find_virtual_server(ngx_connection_t *c,
                   2029:     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
                   2030:     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
                   2031: {
                   2032:     ngx_http_core_srv_conf_t  *cscf;
                   2033: 
                   2034:     if (virtual_names == NULL) {
                   2035:         return NGX_DECLINED;
                   2036:     }
                   2037: 
                   2038:     cscf = ngx_hash_find_combined(&virtual_names->names,
                   2039:                                   ngx_hash_key(host->data, host->len),
                   2040:                                   host->data, host->len);
                   2041: 
                   2042:     if (cscf) {
                   2043:         *cscfp = cscf;
                   2044:         return NGX_OK;
                   2045:     }
                   2046: 
                   2047: #if (NGX_PCRE)
                   2048: 
                   2049:     if (host->len && virtual_names->nregex) {
                   2050:         ngx_int_t                n;
                   2051:         ngx_uint_t               i;
                   2052:         ngx_http_server_name_t  *sn;
                   2053: 
                   2054:         sn = virtual_names->regex;
                   2055: 
                   2056: #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
                   2057: 
                   2058:         if (r == NULL) {
                   2059:             ngx_http_connection_t  *hc;
                   2060: 
                   2061:             for (i = 0; i < virtual_names->nregex; i++) {
                   2062: 
                   2063:                 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
                   2064: 
                   2065:                 if (n == NGX_REGEX_NO_MATCHED) {
                   2066:                     continue;
                   2067:                 }
                   2068: 
                   2069:                 if (n >= 0) {
                   2070:                     hc = c->data;
                   2071:                     hc->ssl_servername_regex = sn[i].regex;
                   2072: 
                   2073:                     *cscfp = sn[i].server;
                   2074:                     return NGX_OK;
                   2075:                 }
                   2076: 
                   2077:                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                   2078:                               ngx_regex_exec_n " failed: %i "
                   2079:                               "on \"%V\" using \"%V\"",
                   2080:                               n, host, &sn[i].regex->name);
                   2081: 
                   2082:                 return NGX_ERROR;
                   2083:             }
                   2084: 
                   2085:             return NGX_DECLINED;
                   2086:         }
                   2087: 
                   2088: #endif /* NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME */
                   2089: 
                   2090:         for (i = 0; i < virtual_names->nregex; i++) {
                   2091: 
                   2092:             n = ngx_http_regex_exec(r, sn[i].regex, host);
                   2093: 
                   2094:             if (n == NGX_DECLINED) {
                   2095:                 continue;
                   2096:             }
                   2097: 
                   2098:             if (n == NGX_OK) {
                   2099:                 *cscfp = sn[i].server;
                   2100:                 return NGX_OK;
                   2101:             }
                   2102: 
                   2103:             return NGX_ERROR;
                   2104:         }
                   2105:     }
                   2106: 
                   2107: #endif /* NGX_PCRE */
                   2108: 
                   2109:     return NGX_DECLINED;
                   2110: }
                   2111: 
                   2112: 
                   2113: static void
                   2114: ngx_http_request_handler(ngx_event_t *ev)
                   2115: {
                   2116:     ngx_connection_t    *c;
                   2117:     ngx_http_request_t  *r;
                   2118:     ngx_http_log_ctx_t  *ctx;
                   2119: 
                   2120:     c = ev->data;
                   2121:     r = c->data;
                   2122: 
                   2123:     ctx = c->log->data;
                   2124:     ctx->current_request = r;
                   2125: 
                   2126:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   2127:                    "http run request: \"%V?%V\"", &r->uri, &r->args);
                   2128: 
                   2129:     if (ev->write) {
                   2130:         r->write_event_handler(r);
                   2131: 
                   2132:     } else {
                   2133:         r->read_event_handler(r);
                   2134:     }
                   2135: 
                   2136:     ngx_http_run_posted_requests(c);
                   2137: }
                   2138: 
                   2139: 
                   2140: void
                   2141: ngx_http_run_posted_requests(ngx_connection_t *c)
                   2142: {
                   2143:     ngx_http_request_t         *r;
                   2144:     ngx_http_log_ctx_t         *ctx;
                   2145:     ngx_http_posted_request_t  *pr;
                   2146: 
                   2147:     for ( ;; ) {
                   2148: 
                   2149:         if (c->destroyed) {
                   2150:             return;
                   2151:         }
                   2152: 
                   2153:         r = c->data;
                   2154:         pr = r->main->posted_requests;
                   2155: 
                   2156:         if (pr == NULL) {
                   2157:             return;
                   2158:         }
                   2159: 
                   2160:         r->main->posted_requests = pr->next;
                   2161: 
                   2162:         r = pr->request;
                   2163: 
                   2164:         ctx = c->log->data;
                   2165:         ctx->current_request = r;
                   2166: 
                   2167:         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   2168:                        "http posted request: \"%V?%V\"", &r->uri, &r->args);
                   2169: 
                   2170:         r->write_event_handler(r);
                   2171:     }
                   2172: }
                   2173: 
                   2174: 
                   2175: ngx_int_t
                   2176: ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
                   2177: {
                   2178:     ngx_http_posted_request_t  **p;
                   2179: 
                   2180:     if (pr == NULL) {
                   2181:         pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
                   2182:         if (pr == NULL) {
                   2183:             return NGX_ERROR;
                   2184:         }
                   2185:     }
                   2186: 
                   2187:     pr->request = r;
                   2188:     pr->next = NULL;
                   2189: 
                   2190:     for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
                   2191: 
                   2192:     *p = pr;
                   2193: 
                   2194:     return NGX_OK;
                   2195: }
                   2196: 
                   2197: 
                   2198: void
                   2199: ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
                   2200: {
                   2201:     ngx_connection_t          *c;
                   2202:     ngx_http_request_t        *pr;
                   2203:     ngx_http_core_loc_conf_t  *clcf;
                   2204: 
                   2205:     c = r->connection;
                   2206: 
                   2207:     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   2208:                    "http finalize request: %d, \"%V?%V\" a:%d, c:%d",
                   2209:                    rc, &r->uri, &r->args, r == c->data, r->main->count);
                   2210: 
                   2211:     if (rc == NGX_DONE) {
                   2212:         ngx_http_finalize_connection(r);
                   2213:         return;
                   2214:     }
                   2215: 
                   2216:     if (rc == NGX_OK && r->filter_finalize) {
                   2217:         c->error = 1;
                   2218:     }
                   2219: 
                   2220:     if (rc == NGX_DECLINED) {
                   2221:         r->content_handler = NULL;
                   2222:         r->write_event_handler = ngx_http_core_run_phases;
                   2223:         ngx_http_core_run_phases(r);
                   2224:         return;
                   2225:     }
                   2226: 
                   2227:     if (r != r->main && r->post_subrequest) {
                   2228:         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
                   2229:     }
                   2230: 
                   2231:     if (rc == NGX_ERROR
                   2232:         || rc == NGX_HTTP_REQUEST_TIME_OUT
                   2233:         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
                   2234:         || c->error)
                   2235:     {
                   2236:         if (ngx_http_post_action(r) == NGX_OK) {
                   2237:             return;
                   2238:         }
                   2239: 
                   2240:         if (r->main->blocked) {
                   2241:             r->write_event_handler = ngx_http_request_finalizer;
                   2242:         }
                   2243: 
                   2244:         ngx_http_terminate_request(r, rc);
                   2245:         return;
                   2246:     }
                   2247: 
                   2248:     if (rc >= NGX_HTTP_SPECIAL_RESPONSE
                   2249:         || rc == NGX_HTTP_CREATED
                   2250:         || rc == NGX_HTTP_NO_CONTENT)
                   2251:     {
                   2252:         if (rc == NGX_HTTP_CLOSE) {
                   2253:             ngx_http_terminate_request(r, rc);
                   2254:             return;
                   2255:         }
                   2256: 
                   2257:         if (r == r->main) {
                   2258:             if (c->read->timer_set) {
                   2259:                 ngx_del_timer(c->read);
                   2260:             }
                   2261: 
                   2262:             if (c->write->timer_set) {
                   2263:                 ngx_del_timer(c->write);
                   2264:             }
                   2265:         }
                   2266: 
                   2267:         c->read->handler = ngx_http_request_handler;
                   2268:         c->write->handler = ngx_http_request_handler;
                   2269: 
                   2270:         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
                   2271:         return;
                   2272:     }
                   2273: 
                   2274:     if (r != r->main) {
                   2275: 
                   2276:         if (r->buffered || r->postponed) {
                   2277: 
                   2278:             if (ngx_http_set_write_handler(r) != NGX_OK) {
                   2279:                 ngx_http_terminate_request(r, 0);
                   2280:             }
                   2281: 
                   2282:             return;
                   2283:         }
                   2284: 
                   2285:         pr = r->parent;
                   2286: 
                   2287:         if (r == c->data) {
                   2288: 
                   2289:             r->main->count--;
                   2290:             r->main->subrequests++;
                   2291: 
                   2292:             if (!r->logged) {
                   2293: 
                   2294:                 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   2295: 
                   2296:                 if (clcf->log_subrequest) {
                   2297:                     ngx_http_log_request(r);
                   2298:                 }
                   2299: 
                   2300:                 r->logged = 1;
                   2301: 
                   2302:             } else {
                   2303:                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                   2304:                               "subrequest: \"%V?%V\" logged again",
                   2305:                               &r->uri, &r->args);
                   2306:             }
                   2307: 
                   2308:             r->done = 1;
                   2309: 
                   2310:             if (pr->postponed && pr->postponed->request == r) {
                   2311:                 pr->postponed = pr->postponed->next;
                   2312:             }
                   2313: 
                   2314:             c->data = pr;
                   2315: 
                   2316:         } else {
                   2317: 
                   2318:             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   2319:                            "http finalize non-active request: \"%V?%V\"",
                   2320:                            &r->uri, &r->args);
                   2321: 
                   2322:             r->write_event_handler = ngx_http_request_finalizer;
                   2323: 
                   2324:             if (r->waited) {
                   2325:                 r->done = 1;
                   2326:             }
                   2327:         }
                   2328: 
                   2329:         if (ngx_http_post_request(pr, NULL) != NGX_OK) {
                   2330:             r->main->count++;
                   2331:             ngx_http_terminate_request(r, 0);
                   2332:             return;
                   2333:         }
                   2334: 
                   2335:         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   2336:                        "http wake parent request: \"%V?%V\"",
                   2337:                        &pr->uri, &pr->args);
                   2338: 
                   2339:         return;
                   2340:     }
                   2341: 
                   2342:     if (r->buffered || c->buffered || r->postponed || r->blocked) {
                   2343: 
                   2344:         if (ngx_http_set_write_handler(r) != NGX_OK) {
                   2345:             ngx_http_terminate_request(r, 0);
                   2346:         }
                   2347: 
                   2348:         return;
                   2349:     }
                   2350: 
                   2351:     if (r != c->data) {
                   2352:         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                   2353:                       "http finalize non-active request: \"%V?%V\"",
                   2354:                       &r->uri, &r->args);
                   2355:         return;
                   2356:     }
                   2357: 
                   2358:     r->done = 1;
                   2359:     r->write_event_handler = ngx_http_request_empty_handler;
                   2360: 
                   2361:     if (!r->post_action) {
                   2362:         r->request_complete = 1;
                   2363:     }
                   2364: 
                   2365:     if (ngx_http_post_action(r) == NGX_OK) {
                   2366:         return;
                   2367:     }
                   2368: 
                   2369:     if (c->read->timer_set) {
                   2370:         ngx_del_timer(c->read);
                   2371:     }
                   2372: 
                   2373:     if (c->write->timer_set) {
                   2374:         c->write->delayed = 0;
                   2375:         ngx_del_timer(c->write);
                   2376:     }
                   2377: 
                   2378:     if (c->read->eof) {
                   2379:         ngx_http_close_request(r, 0);
                   2380:         return;
                   2381:     }
                   2382: 
                   2383:     ngx_http_finalize_connection(r);
                   2384: }
                   2385: 
                   2386: 
                   2387: static void
                   2388: ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
                   2389: {
                   2390:     ngx_http_cleanup_t    *cln;
                   2391:     ngx_http_request_t    *mr;
                   2392:     ngx_http_ephemeral_t  *e;
                   2393: 
                   2394:     mr = r->main;
                   2395: 
                   2396:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   2397:                    "http terminate request count:%d", mr->count);
                   2398: 
                   2399:     if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
                   2400:         mr->headers_out.status = rc;
                   2401:     }
                   2402: 
                   2403:     cln = mr->cleanup;
                   2404:     mr->cleanup = NULL;
                   2405: 
                   2406:     while (cln) {
                   2407:         if (cln->handler) {
                   2408:             cln->handler(cln->data);
                   2409:         }
                   2410: 
                   2411:         cln = cln->next;
                   2412:     }
                   2413: 
                   2414:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   2415:                    "http terminate cleanup count:%d blk:%d",
                   2416:                    mr->count, mr->blocked);
                   2417: 
                   2418:     if (mr->write_event_handler) {
                   2419: 
                   2420:         if (mr->blocked) {
                   2421:             return;
                   2422:         }
                   2423: 
                   2424:         e = ngx_http_ephemeral(mr);
                   2425:         mr->posted_requests = NULL;
                   2426:         mr->write_event_handler = ngx_http_terminate_handler;
                   2427:         (void) ngx_http_post_request(mr, &e->terminal_posted_request);
                   2428:         return;
                   2429:     }
                   2430: 
                   2431:     ngx_http_close_request(mr, rc);
                   2432: }
                   2433: 
                   2434: 
                   2435: static void
                   2436: ngx_http_terminate_handler(ngx_http_request_t *r)
                   2437: {
                   2438:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   2439:                    "http terminate handler count:%d", r->count);
                   2440: 
                   2441:     r->count = 1;
                   2442: 
                   2443:     ngx_http_close_request(r, 0);
                   2444: }
                   2445: 
                   2446: 
                   2447: static void
                   2448: ngx_http_finalize_connection(ngx_http_request_t *r)
                   2449: {
                   2450:     ngx_http_core_loc_conf_t  *clcf;
                   2451: 
                   2452: #if (NGX_HTTP_SPDY)
                   2453:     if (r->spdy_stream) {
                   2454:         ngx_http_close_request(r, 0);
                   2455:         return;
                   2456:     }
                   2457: #endif
                   2458: 
                   2459:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   2460: 
                   2461:     if (r->main->count != 1) {
                   2462: 
                   2463:         if (r->discard_body) {
                   2464:             r->read_event_handler = ngx_http_discarded_request_body_handler;
                   2465:             ngx_add_timer(r->connection->read, clcf->lingering_timeout);
                   2466: 
                   2467:             if (r->lingering_time == 0) {
                   2468:                 r->lingering_time = ngx_time()
                   2469:                                       + (time_t) (clcf->lingering_time / 1000);
                   2470:             }
                   2471:         }
                   2472: 
                   2473:         ngx_http_close_request(r, 0);
                   2474:         return;
                   2475:     }
                   2476: 
                   2477:     if (!ngx_terminate
                   2478:          && !ngx_exiting
                   2479:          && r->keepalive
                   2480:          && clcf->keepalive_timeout > 0)
                   2481:     {
                   2482:         ngx_http_set_keepalive(r);
                   2483:         return;
                   2484:     }
                   2485: 
                   2486:     if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
                   2487:         || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
                   2488:             && (r->lingering_close
                   2489:                 || r->header_in->pos < r->header_in->last
                   2490:                 || r->connection->read->ready)))
                   2491:     {
                   2492:         ngx_http_set_lingering_close(r);
                   2493:         return;
                   2494:     }
                   2495: 
                   2496:     ngx_http_close_request(r, 0);
                   2497: }
                   2498: 
                   2499: 
                   2500: static ngx_int_t
                   2501: ngx_http_set_write_handler(ngx_http_request_t *r)
                   2502: {
                   2503:     ngx_event_t               *wev;
                   2504:     ngx_http_core_loc_conf_t  *clcf;
                   2505: 
                   2506:     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
                   2507: 
                   2508:     r->read_event_handler = r->discard_body ?
                   2509:                                 ngx_http_discarded_request_body_handler:
                   2510:                                 ngx_http_test_reading;
                   2511:     r->write_event_handler = ngx_http_writer;
                   2512: 
                   2513: #if (NGX_HTTP_SPDY)
                   2514:     if (r->spdy_stream) {
                   2515:         return NGX_OK;
                   2516:     }
                   2517: #endif
                   2518: 
                   2519:     wev = r->connection->write;
                   2520: 
                   2521:     if (wev->ready && wev->delayed) {
                   2522:         return NGX_OK;
                   2523:     }
                   2524: 
                   2525:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   2526:     if (!wev->delayed) {
                   2527:         ngx_add_timer(wev, clcf->send_timeout);
                   2528:     }
                   2529: 
                   2530:     if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
                   2531:         ngx_http_close_request(r, 0);
                   2532:         return NGX_ERROR;
                   2533:     }
                   2534: 
                   2535:     return NGX_OK;
                   2536: }
                   2537: 
                   2538: 
                   2539: static void
                   2540: ngx_http_writer(ngx_http_request_t *r)
                   2541: {
                   2542:     int                        rc;
                   2543:     ngx_event_t               *wev;
                   2544:     ngx_connection_t          *c;
                   2545:     ngx_http_core_loc_conf_t  *clcf;
                   2546: 
                   2547:     c = r->connection;
                   2548:     wev = c->write;
                   2549: 
                   2550:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
                   2551:                    "http writer handler: \"%V?%V\"", &r->uri, &r->args);
                   2552: 
                   2553:     clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
                   2554: 
                   2555:     if (wev->timedout) {
                   2556:         if (!wev->delayed) {
                   2557:             ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
                   2558:                           "client timed out");
                   2559:             c->timedout = 1;
                   2560: 
                   2561:             ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
                   2562:             return;
                   2563:         }
                   2564: 
                   2565:         wev->timedout = 0;
                   2566:         wev->delayed = 0;
                   2567: 
                   2568:         if (!wev->ready) {
                   2569:             ngx_add_timer(wev, clcf->send_timeout);
                   2570: 
                   2571:             if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
                   2572:                 ngx_http_close_request(r, 0);
                   2573:             }
                   2574: 
                   2575:             return;
                   2576:         }
                   2577: 
                   2578:     }
                   2579: 
                   2580:     if (wev->delayed || r->aio) {
                   2581:         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
                   2582:                        "http writer delayed");
                   2583: 
                   2584:         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
                   2585:             ngx_http_close_request(r, 0);
                   2586:         }
                   2587: 
                   2588:         return;
                   2589:     }
                   2590: 
                   2591:     rc = ngx_http_output_filter(r, NULL);
                   2592: 
                   2593:     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   2594:                    "http writer output filter: %d, \"%V?%V\"",
                   2595:                    rc, &r->uri, &r->args);
                   2596: 
                   2597:     if (rc == NGX_ERROR) {
                   2598:         ngx_http_finalize_request(r, rc);
                   2599:         return;
                   2600:     }
                   2601: 
                   2602:     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
                   2603: 
                   2604:         if (!wev->delayed) {
                   2605:             ngx_add_timer(wev, clcf->send_timeout);
                   2606:         }
                   2607: 
                   2608:         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
                   2609:             ngx_http_close_request(r, 0);
                   2610:         }
                   2611: 
                   2612:         return;
                   2613:     }
                   2614: 
                   2615:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
                   2616:                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
                   2617: 
                   2618:     r->write_event_handler = ngx_http_request_empty_handler;
                   2619: 
                   2620:     ngx_http_finalize_request(r, rc);
                   2621: }
                   2622: 
                   2623: 
                   2624: static void
                   2625: ngx_http_request_finalizer(ngx_http_request_t *r)
                   2626: {
                   2627:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   2628:                    "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
                   2629: 
                   2630:     ngx_http_finalize_request(r, 0);
                   2631: }
                   2632: 
                   2633: 
                   2634: void
                   2635: ngx_http_block_reading(ngx_http_request_t *r)
                   2636: {
                   2637:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   2638:                    "http reading blocked");
                   2639: 
                   2640:     /* aio does not call this handler */
                   2641: 
                   2642:     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
                   2643:         && r->connection->read->active)
                   2644:     {
                   2645:         if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
                   2646:             ngx_http_close_request(r, 0);
                   2647:         }
                   2648:     }
                   2649: }
                   2650: 
                   2651: 
                   2652: void
                   2653: ngx_http_test_reading(ngx_http_request_t *r)
                   2654: {
                   2655:     int                n;
                   2656:     char               buf[1];
                   2657:     ngx_err_t          err;
                   2658:     ngx_event_t       *rev;
                   2659:     ngx_connection_t  *c;
                   2660: 
                   2661:     c = r->connection;
                   2662:     rev = c->read;
                   2663: 
                   2664:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
                   2665: 
                   2666: #if (NGX_HTTP_SPDY)
                   2667: 
                   2668:     if (r->spdy_stream) {
                   2669:         if (c->error) {
                   2670:             err = 0;
                   2671:             goto closed;
                   2672:         }
                   2673: 
                   2674:         return;
                   2675:     }
                   2676: 
                   2677: #endif
                   2678: 
                   2679: #if (NGX_HAVE_KQUEUE)
                   2680: 
                   2681:     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
                   2682: 
                   2683:         if (!rev->pending_eof) {
                   2684:             return;
                   2685:         }
                   2686: 
                   2687:         rev->eof = 1;
                   2688:         c->error = 1;
                   2689:         err = rev->kq_errno;
                   2690: 
                   2691:         goto closed;
                   2692:     }
                   2693: 
                   2694: #endif
                   2695: 
                   2696:     n = recv(c->fd, buf, 1, MSG_PEEK);
                   2697: 
                   2698:     if (n == 0) {
                   2699:         rev->eof = 1;
                   2700:         c->error = 1;
                   2701:         err = 0;
                   2702: 
                   2703:         goto closed;
                   2704: 
                   2705:     } else if (n == -1) {
                   2706:         err = ngx_socket_errno;
                   2707: 
                   2708:         if (err != NGX_EAGAIN) {
                   2709:             rev->eof = 1;
                   2710:             c->error = 1;
                   2711: 
                   2712:             goto closed;
                   2713:         }
                   2714:     }
                   2715: 
                   2716:     /* aio does not call this handler */
                   2717: 
                   2718:     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
                   2719: 
                   2720:         if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
                   2721:             ngx_http_close_request(r, 0);
                   2722:         }
                   2723:     }
                   2724: 
                   2725:     return;
                   2726: 
                   2727: closed:
                   2728: 
                   2729:     if (err) {
                   2730:         rev->error = 1;
                   2731:     }
                   2732: 
                   2733:     ngx_log_error(NGX_LOG_INFO, c->log, err,
                   2734:                   "client prematurely closed connection");
                   2735: 
                   2736:     ngx_http_finalize_request(r, 0);
                   2737: }
                   2738: 
                   2739: 
                   2740: static void
                   2741: ngx_http_set_keepalive(ngx_http_request_t *r)
                   2742: {
                   2743:     int                        tcp_nodelay;
                   2744:     ngx_int_t                  i;
                   2745:     ngx_buf_t                 *b, *f;
                   2746:     ngx_event_t               *rev, *wev;
                   2747:     ngx_connection_t          *c;
                   2748:     ngx_http_connection_t     *hc;
                   2749:     ngx_http_core_srv_conf_t  *cscf;
                   2750:     ngx_http_core_loc_conf_t  *clcf;
                   2751: 
                   2752:     c = r->connection;
                   2753:     rev = c->read;
                   2754: 
                   2755:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   2756: 
                   2757:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
                   2758: 
                   2759:     if (r->discard_body) {
                   2760:         r->write_event_handler = ngx_http_request_empty_handler;
                   2761:         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
                   2762:         ngx_add_timer(rev, clcf->lingering_timeout);
                   2763:         return;
                   2764:     }
                   2765: 
                   2766:     c->log->action = "closing request";
                   2767: 
                   2768:     hc = r->http_connection;
                   2769:     b = r->header_in;
                   2770: 
                   2771:     if (b->pos < b->last) {
                   2772: 
                   2773:         /* the pipelined request */
                   2774: 
                   2775:         if (b != c->buffer) {
                   2776: 
                   2777:             /*
                   2778:              * If the large header buffers were allocated while the previous
                   2779:              * request processing then we do not use c->buffer for
                   2780:              * the pipelined request (see ngx_http_create_request()).
                   2781:              *
                   2782:              * Now we would move the large header buffers to the free list.
                   2783:              */
                   2784: 
                   2785:             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   2786: 
                   2787:             if (hc->free == NULL) {
                   2788:                 hc->free = ngx_palloc(c->pool,
                   2789:                   cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
                   2790: 
                   2791:                 if (hc->free == NULL) {
                   2792:                     ngx_http_close_request(r, 0);
                   2793:                     return;
                   2794:                 }
                   2795:             }
                   2796: 
                   2797:             for (i = 0; i < hc->nbusy - 1; i++) {
                   2798:                 f = hc->busy[i];
                   2799:                 hc->free[hc->nfree++] = f;
                   2800:                 f->pos = f->start;
                   2801:                 f->last = f->start;
                   2802:             }
                   2803: 
                   2804:             hc->busy[0] = b;
                   2805:             hc->nbusy = 1;
                   2806:         }
                   2807:     }
                   2808: 
                   2809:     /* guard against recursive call from ngx_http_finalize_connection() */
                   2810:     r->keepalive = 0;
                   2811: 
                   2812:     ngx_http_free_request(r, 0);
                   2813: 
                   2814:     c->data = hc;
                   2815: 
                   2816:     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                   2817:         ngx_http_close_connection(c);
                   2818:         return;
                   2819:     }
                   2820: 
                   2821:     wev = c->write;
                   2822:     wev->handler = ngx_http_empty_handler;
                   2823: 
                   2824:     if (b->pos < b->last) {
                   2825: 
                   2826:         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
                   2827: 
                   2828:         c->log->action = "reading client pipelined request line";
                   2829: 
                   2830:         r = ngx_http_create_request(c);
                   2831:         if (r == NULL) {
                   2832:             ngx_http_close_connection(c);
                   2833:             return;
                   2834:         }
                   2835: 
                   2836:         r->pipeline = 1;
                   2837: 
                   2838:         c->data = r;
                   2839: 
                   2840:         c->sent = 0;
                   2841:         c->destroyed = 0;
                   2842: 
                   2843:         if (rev->timer_set) {
                   2844:             ngx_del_timer(rev);
                   2845:         }
                   2846: 
                   2847:         rev->handler = ngx_http_process_request_line;
                   2848:         ngx_post_event(rev, &ngx_posted_events);
                   2849:         return;
                   2850:     }
                   2851: 
                   2852:     /*
                   2853:      * To keep a memory footprint as small as possible for an idle keepalive
                   2854:      * connection we try to free c->buffer's memory if it was allocated outside
                   2855:      * the c->pool.  The large header buffers are always allocated outside the
                   2856:      * c->pool and are freed too.
                   2857:      */
                   2858: 
                   2859:     b = c->buffer;
                   2860: 
                   2861:     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
                   2862: 
                   2863:         /*
                   2864:          * the special note for ngx_http_keepalive_handler() that
                   2865:          * c->buffer's memory was freed
                   2866:          */
                   2867: 
                   2868:         b->pos = NULL;
                   2869: 
                   2870:     } else {
                   2871:         b->pos = b->start;
                   2872:         b->last = b->start;
                   2873:     }
                   2874: 
                   2875:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
                   2876:                    hc->free, hc->nfree);
                   2877: 
                   2878:     if (hc->free) {
                   2879:         for (i = 0; i < hc->nfree; i++) {
                   2880:             ngx_pfree(c->pool, hc->free[i]->start);
                   2881:             hc->free[i] = NULL;
                   2882:         }
                   2883: 
                   2884:         hc->nfree = 0;
                   2885:     }
                   2886: 
                   2887:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
                   2888:                    hc->busy, hc->nbusy);
                   2889: 
                   2890:     if (hc->busy) {
                   2891:         for (i = 0; i < hc->nbusy; i++) {
                   2892:             ngx_pfree(c->pool, hc->busy[i]->start);
                   2893:             hc->busy[i] = NULL;
                   2894:         }
                   2895: 
                   2896:         hc->nbusy = 0;
                   2897:     }
                   2898: 
                   2899: #if (NGX_HTTP_SSL)
                   2900:     if (c->ssl) {
                   2901:         ngx_ssl_free_buffer(c);
                   2902:     }
                   2903: #endif
                   2904: 
                   2905:     rev->handler = ngx_http_keepalive_handler;
                   2906: 
                   2907:     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
                   2908:         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
                   2909:             ngx_http_close_connection(c);
                   2910:             return;
                   2911:         }
                   2912:     }
                   2913: 
                   2914:     c->log->action = "keepalive";
                   2915: 
                   2916:     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
                   2917:         if (ngx_tcp_push(c->fd) == -1) {
                   2918:             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
                   2919:             ngx_http_close_connection(c);
                   2920:             return;
                   2921:         }
                   2922: 
                   2923:         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
                   2924:         tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
                   2925: 
                   2926:     } else {
                   2927:         tcp_nodelay = 1;
                   2928:     }
                   2929: 
                   2930:     if (tcp_nodelay
                   2931:         && clcf->tcp_nodelay
                   2932:         && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
                   2933:     {
                   2934:         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
                   2935: 
                   2936:         if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
                   2937:                        (const void *) &tcp_nodelay, sizeof(int))
                   2938:             == -1)
                   2939:         {
                   2940: #if (NGX_SOLARIS)
                   2941:             /* Solaris returns EINVAL if a socket has been shut down */
                   2942:             c->log_error = NGX_ERROR_IGNORE_EINVAL;
                   2943: #endif
                   2944: 
                   2945:             ngx_connection_error(c, ngx_socket_errno,
                   2946:                                  "setsockopt(TCP_NODELAY) failed");
                   2947: 
                   2948:             c->log_error = NGX_ERROR_INFO;
                   2949:             ngx_http_close_connection(c);
                   2950:             return;
                   2951:         }
                   2952: 
                   2953:         c->tcp_nodelay = NGX_TCP_NODELAY_SET;
                   2954:     }
                   2955: 
                   2956: #if 0
                   2957:     /* if ngx_http_request_t was freed then we need some other place */
                   2958:     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
                   2959: #endif
                   2960: 
                   2961:     c->idle = 1;
                   2962:     ngx_reusable_connection(c, 1);
                   2963: 
                   2964:     ngx_add_timer(rev, clcf->keepalive_timeout);
                   2965: 
                   2966:     if (rev->ready) {
                   2967:         ngx_post_event(rev, &ngx_posted_events);
                   2968:     }
                   2969: }
                   2970: 
                   2971: 
                   2972: static void
                   2973: ngx_http_keepalive_handler(ngx_event_t *rev)
                   2974: {
                   2975:     size_t             size;
                   2976:     ssize_t            n;
                   2977:     ngx_buf_t         *b;
                   2978:     ngx_connection_t  *c;
                   2979: 
                   2980:     c = rev->data;
                   2981: 
                   2982:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
                   2983: 
                   2984:     if (rev->timedout || c->close) {
                   2985:         ngx_http_close_connection(c);
                   2986:         return;
                   2987:     }
                   2988: 
                   2989: #if (NGX_HAVE_KQUEUE)
                   2990: 
                   2991:     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
                   2992:         if (rev->pending_eof) {
                   2993:             c->log->handler = NULL;
                   2994:             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
                   2995:                           "kevent() reported that client %V closed "
                   2996:                           "keepalive connection", &c->addr_text);
                   2997: #if (NGX_HTTP_SSL)
                   2998:             if (c->ssl) {
                   2999:                 c->ssl->no_send_shutdown = 1;
                   3000:             }
                   3001: #endif
                   3002:             ngx_http_close_connection(c);
                   3003:             return;
                   3004:         }
                   3005:     }
                   3006: 
                   3007: #endif
                   3008: 
                   3009:     b = c->buffer;
                   3010:     size = b->end - b->start;
                   3011: 
                   3012:     if (b->pos == NULL) {
                   3013: 
                   3014:         /*
                   3015:          * The c->buffer's memory was freed by ngx_http_set_keepalive().
                   3016:          * However, the c->buffer->start and c->buffer->end were not changed
                   3017:          * to keep the buffer size.
                   3018:          */
                   3019: 
                   3020:         b->pos = ngx_palloc(c->pool, size);
                   3021:         if (b->pos == NULL) {
                   3022:             ngx_http_close_connection(c);
                   3023:             return;
                   3024:         }
                   3025: 
                   3026:         b->start = b->pos;
                   3027:         b->last = b->pos;
                   3028:         b->end = b->pos + size;
                   3029:     }
                   3030: 
                   3031:     /*
                   3032:      * MSIE closes a keepalive connection with RST flag
                   3033:      * so we ignore ECONNRESET here.
                   3034:      */
                   3035: 
                   3036:     c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
                   3037:     ngx_set_socket_errno(0);
                   3038: 
                   3039:     n = c->recv(c, b->last, size);
                   3040:     c->log_error = NGX_ERROR_INFO;
                   3041: 
                   3042:     if (n == NGX_AGAIN) {
                   3043:         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                   3044:             ngx_http_close_connection(c);
                   3045:             return;
                   3046:         }
                   3047: 
                   3048:         /*
                   3049:          * Like ngx_http_set_keepalive() we are trying to not hold
                   3050:          * c->buffer's memory for a keepalive connection.
                   3051:          */
                   3052: 
                   3053:         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
                   3054: 
                   3055:             /*
                   3056:              * the special note that c->buffer's memory was freed
                   3057:              */
                   3058: 
                   3059:             b->pos = NULL;
                   3060:         }
                   3061: 
                   3062:         return;
                   3063:     }
                   3064: 
                   3065:     if (n == NGX_ERROR) {
                   3066:         ngx_http_close_connection(c);
                   3067:         return;
                   3068:     }
                   3069: 
                   3070:     c->log->handler = NULL;
                   3071: 
                   3072:     if (n == 0) {
                   3073:         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
                   3074:                       "client %V closed keepalive connection", &c->addr_text);
                   3075:         ngx_http_close_connection(c);
                   3076:         return;
                   3077:     }
                   3078: 
                   3079:     b->last += n;
                   3080: 
                   3081:     c->log->handler = ngx_http_log_error;
                   3082:     c->log->action = "reading client request line";
                   3083: 
                   3084:     c->idle = 0;
                   3085:     ngx_reusable_connection(c, 0);
                   3086: 
                   3087:     c->data = ngx_http_create_request(c);
                   3088:     if (c->data == NULL) {
                   3089:         ngx_http_close_connection(c);
                   3090:         return;
                   3091:     }
                   3092: 
                   3093:     c->sent = 0;
                   3094:     c->destroyed = 0;
                   3095: 
                   3096:     ngx_del_timer(rev);
                   3097: 
                   3098:     rev->handler = ngx_http_process_request_line;
                   3099:     ngx_http_process_request_line(rev);
                   3100: }
                   3101: 
                   3102: 
                   3103: static void
                   3104: ngx_http_set_lingering_close(ngx_http_request_t *r)
                   3105: {
                   3106:     ngx_event_t               *rev, *wev;
                   3107:     ngx_connection_t          *c;
                   3108:     ngx_http_core_loc_conf_t  *clcf;
                   3109: 
                   3110:     c = r->connection;
                   3111: 
                   3112:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   3113: 
                   3114:     rev = c->read;
                   3115:     rev->handler = ngx_http_lingering_close_handler;
                   3116: 
                   3117:     r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
                   3118:     ngx_add_timer(rev, clcf->lingering_timeout);
                   3119: 
                   3120:     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                   3121:         ngx_http_close_request(r, 0);
                   3122:         return;
                   3123:     }
                   3124: 
                   3125:     wev = c->write;
                   3126:     wev->handler = ngx_http_empty_handler;
                   3127: 
                   3128:     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
                   3129:         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
                   3130:             ngx_http_close_request(r, 0);
                   3131:             return;
                   3132:         }
                   3133:     }
                   3134: 
                   3135:     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
                   3136:         ngx_connection_error(c, ngx_socket_errno,
                   3137:                              ngx_shutdown_socket_n " failed");
                   3138:         ngx_http_close_request(r, 0);
                   3139:         return;
                   3140:     }
                   3141: 
                   3142:     if (rev->ready) {
                   3143:         ngx_http_lingering_close_handler(rev);
                   3144:     }
                   3145: }
                   3146: 
                   3147: 
                   3148: static void
                   3149: ngx_http_lingering_close_handler(ngx_event_t *rev)
                   3150: {
                   3151:     ssize_t                    n;
                   3152:     ngx_msec_t                 timer;
                   3153:     ngx_connection_t          *c;
                   3154:     ngx_http_request_t        *r;
                   3155:     ngx_http_core_loc_conf_t  *clcf;
                   3156:     u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
                   3157: 
                   3158:     c = rev->data;
                   3159:     r = c->data;
                   3160: 
                   3161:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   3162:                    "http lingering close handler");
                   3163: 
                   3164:     if (rev->timedout) {
                   3165:         ngx_http_close_request(r, 0);
                   3166:         return;
                   3167:     }
                   3168: 
                   3169:     timer = (ngx_msec_t) (r->lingering_time - ngx_time());
                   3170:     if (timer <= 0) {
                   3171:         ngx_http_close_request(r, 0);
                   3172:         return;
                   3173:     }
                   3174: 
                   3175:     do {
                   3176:         n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
                   3177: 
                   3178:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
                   3179: 
                   3180:         if (n == NGX_ERROR || n == 0) {
                   3181:             ngx_http_close_request(r, 0);
                   3182:             return;
                   3183:         }
                   3184: 
                   3185:     } while (rev->ready);
                   3186: 
                   3187:     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
                   3188:         ngx_http_close_request(r, 0);
                   3189:         return;
                   3190:     }
                   3191: 
                   3192:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   3193: 
                   3194:     timer *= 1000;
                   3195: 
                   3196:     if (timer > clcf->lingering_timeout) {
                   3197:         timer = clcf->lingering_timeout;
                   3198:     }
                   3199: 
                   3200:     ngx_add_timer(rev, timer);
                   3201: }
                   3202: 
                   3203: 
                   3204: void
                   3205: ngx_http_empty_handler(ngx_event_t *wev)
                   3206: {
                   3207:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
                   3208: 
                   3209:     return;
                   3210: }
                   3211: 
                   3212: 
                   3213: void
                   3214: ngx_http_request_empty_handler(ngx_http_request_t *r)
                   3215: {
                   3216:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   3217:                    "http request empty handler");
                   3218: 
                   3219:     return;
                   3220: }
                   3221: 
                   3222: 
                   3223: ngx_int_t
                   3224: ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
                   3225: {
                   3226:     ngx_buf_t    *b;
                   3227:     ngx_chain_t   out;
                   3228: 
                   3229:     b = ngx_calloc_buf(r->pool);
                   3230:     if (b == NULL) {
                   3231:         return NGX_ERROR;
                   3232:     }
                   3233: 
                   3234:     if (flags & NGX_HTTP_LAST) {
                   3235: 
                   3236:         if (r == r->main && !r->post_action) {
                   3237:             b->last_buf = 1;
                   3238: 
                   3239:         } else {
                   3240:             b->sync = 1;
                   3241:             b->last_in_chain = 1;
                   3242:         }
                   3243:     }
                   3244: 
                   3245:     if (flags & NGX_HTTP_FLUSH) {
                   3246:         b->flush = 1;
                   3247:     }
                   3248: 
                   3249:     out.buf = b;
                   3250:     out.next = NULL;
                   3251: 
                   3252:     return ngx_http_output_filter(r, &out);
                   3253: }
                   3254: 
                   3255: 
                   3256: static ngx_int_t
                   3257: ngx_http_post_action(ngx_http_request_t *r)
                   3258: {
                   3259:     ngx_http_core_loc_conf_t  *clcf;
                   3260: 
                   3261:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   3262: 
                   3263:     if (clcf->post_action.data == NULL) {
                   3264:         return NGX_DECLINED;
                   3265:     }
                   3266: 
                   3267:     if (r->post_action && r->uri_changes == 0) {
                   3268:         return NGX_DECLINED;
                   3269:     }
                   3270: 
                   3271:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   3272:                    "post action: \"%V\"", &clcf->post_action);
                   3273: 
                   3274:     r->main->count--;
                   3275: 
                   3276:     r->http_version = NGX_HTTP_VERSION_9;
                   3277:     r->header_only = 1;
                   3278:     r->post_action = 1;
                   3279: 
                   3280:     r->read_event_handler = ngx_http_block_reading;
                   3281: 
                   3282:     if (clcf->post_action.data[0] == '/') {
                   3283:         ngx_http_internal_redirect(r, &clcf->post_action, NULL);
                   3284: 
                   3285:     } else {
                   3286:         ngx_http_named_location(r, &clcf->post_action);
                   3287:     }
                   3288: 
                   3289:     return NGX_OK;
                   3290: }
                   3291: 
                   3292: 
                   3293: static void
                   3294: ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
                   3295: {
                   3296:     ngx_connection_t  *c;
                   3297: 
                   3298:     r = r->main;
                   3299:     c = r->connection;
                   3300: 
                   3301:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   3302:                    "http request count:%d blk:%d", r->count, r->blocked);
                   3303: 
                   3304:     if (r->count == 0) {
                   3305:         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
                   3306:     }
                   3307: 
                   3308:     r->count--;
                   3309: 
                   3310:     if (r->count || r->blocked) {
                   3311:         return;
                   3312:     }
                   3313: 
                   3314: #if (NGX_HTTP_SPDY)
                   3315:     if (r->spdy_stream) {
                   3316:         ngx_http_spdy_close_stream(r->spdy_stream, rc);
                   3317:         return;
                   3318:     }
                   3319: #endif
                   3320: 
                   3321:     ngx_http_free_request(r, rc);
                   3322:     ngx_http_close_connection(c);
                   3323: }
                   3324: 
                   3325: 
                   3326: void
                   3327: ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
                   3328: {
                   3329:     ngx_log_t                 *log;
                   3330:     ngx_pool_t                *pool;
                   3331:     struct linger              linger;
                   3332:     ngx_http_cleanup_t        *cln;
                   3333:     ngx_http_log_ctx_t        *ctx;
                   3334:     ngx_http_core_loc_conf_t  *clcf;
                   3335: 
                   3336:     log = r->connection->log;
                   3337: 
                   3338:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
                   3339: 
                   3340:     if (r->pool == NULL) {
                   3341:         ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
                   3342:         return;
                   3343:     }
                   3344: 
                   3345:     for (cln = r->cleanup; cln; cln = cln->next) {
                   3346:         if (cln->handler) {
                   3347:             cln->handler(cln->data);
                   3348:         }
                   3349:     }
                   3350: 
                   3351: #if (NGX_STAT_STUB)
                   3352: 
                   3353:     if (r->stat_reading) {
                   3354:         (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
                   3355:     }
                   3356: 
                   3357:     if (r->stat_writing) {
                   3358:         (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
                   3359:     }
                   3360: 
                   3361: #endif
                   3362: 
                   3363:     if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
                   3364:         r->headers_out.status = rc;
                   3365:     }
                   3366: 
                   3367:     log->action = "logging request";
                   3368: 
                   3369:     ngx_http_log_request(r);
                   3370: 
                   3371:     log->action = "closing request";
                   3372: 
                   3373:     if (r->connection->timedout) {
                   3374:         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   3375: 
                   3376:         if (clcf->reset_timedout_connection) {
                   3377:             linger.l_onoff = 1;
                   3378:             linger.l_linger = 0;
                   3379: 
                   3380:             if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
                   3381:                            (const void *) &linger, sizeof(struct linger)) == -1)
                   3382:             {
                   3383:                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
                   3384:                               "setsockopt(SO_LINGER) failed");
                   3385:             }
                   3386:         }
                   3387:     }
                   3388: 
                   3389:     /* the various request strings were allocated from r->pool */
                   3390:     ctx = log->data;
                   3391:     ctx->request = NULL;
                   3392: 
                   3393:     r->request_line.len = 0;
                   3394: 
                   3395:     r->connection->destroyed = 1;
                   3396: 
                   3397:     /*
                   3398:      * Setting r->pool to NULL will increase probability to catch double close
                   3399:      * of request since the request object is allocated from its own pool.
                   3400:      */
                   3401: 
                   3402:     pool = r->pool;
                   3403:     r->pool = NULL;
                   3404: 
                   3405:     ngx_destroy_pool(pool);
                   3406: }
                   3407: 
                   3408: 
                   3409: static void
                   3410: ngx_http_log_request(ngx_http_request_t *r)
                   3411: {
                   3412:     ngx_uint_t                  i, n;
                   3413:     ngx_http_handler_pt        *log_handler;
                   3414:     ngx_http_core_main_conf_t  *cmcf;
                   3415: 
                   3416:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                   3417: 
                   3418:     log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
                   3419:     n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
                   3420: 
                   3421:     for (i = 0; i < n; i++) {
                   3422:         log_handler[i](r);
                   3423:     }
                   3424: }
                   3425: 
                   3426: 
                   3427: void
                   3428: ngx_http_close_connection(ngx_connection_t *c)
                   3429: {
                   3430:     ngx_pool_t  *pool;
                   3431: 
                   3432:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   3433:                    "close http connection: %d", c->fd);
                   3434: 
                   3435: #if (NGX_HTTP_SSL)
                   3436: 
                   3437:     if (c->ssl) {
                   3438:         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
                   3439:             c->ssl->handler = ngx_http_close_connection;
                   3440:             return;
                   3441:         }
                   3442:     }
                   3443: 
                   3444: #endif
                   3445: 
                   3446: #if (NGX_STAT_STUB)
                   3447:     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
                   3448: #endif
                   3449: 
                   3450:     c->destroyed = 1;
                   3451: 
                   3452:     pool = c->pool;
                   3453: 
                   3454:     ngx_close_connection(c);
                   3455: 
                   3456:     ngx_destroy_pool(pool);
                   3457: }
                   3458: 
                   3459: 
                   3460: static u_char *
                   3461: ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
                   3462: {
                   3463:     u_char              *p;
                   3464:     ngx_http_request_t  *r;
                   3465:     ngx_http_log_ctx_t  *ctx;
                   3466: 
                   3467:     if (log->action) {
                   3468:         p = ngx_snprintf(buf, len, " while %s", log->action);
                   3469:         len -= p - buf;
                   3470:         buf = p;
                   3471:     }
                   3472: 
                   3473:     ctx = log->data;
                   3474: 
                   3475:     p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
                   3476:     len -= p - buf;
                   3477: 
                   3478:     r = ctx->request;
                   3479: 
                   3480:     if (r) {
                   3481:         return r->log_handler(r, ctx->current_request, p, len);
                   3482: 
                   3483:     } else {
                   3484:         p = ngx_snprintf(p, len, ", server: %V",
                   3485:                          &ctx->connection->listening->addr_text);
                   3486:     }
                   3487: 
                   3488:     return p;
                   3489: }
                   3490: 
                   3491: 
                   3492: static u_char *
                   3493: ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
                   3494:     u_char *buf, size_t len)
                   3495: {
                   3496:     char                      *uri_separator;
                   3497:     u_char                    *p;
                   3498:     ngx_http_upstream_t       *u;
                   3499:     ngx_http_core_srv_conf_t  *cscf;
                   3500: 
                   3501:     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   3502: 
                   3503:     p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
                   3504:     len -= p - buf;
                   3505:     buf = p;
                   3506: 
                   3507:     if (r->request_line.data == NULL && r->request_start) {
                   3508:         for (p = r->request_start; p < r->header_in->last; p++) {
                   3509:             if (*p == CR || *p == LF) {
                   3510:                 break;
                   3511:             }
                   3512:         }
                   3513: 
                   3514:         r->request_line.len = p - r->request_start;
                   3515:         r->request_line.data = r->request_start;
                   3516:     }
                   3517: 
                   3518:     if (r->request_line.len) {
                   3519:         p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
                   3520:         len -= p - buf;
                   3521:         buf = p;
                   3522:     }
                   3523: 
                   3524:     if (r != sr) {
                   3525:         p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
                   3526:         len -= p - buf;
                   3527:         buf = p;
                   3528:     }
                   3529: 
                   3530:     u = sr->upstream;
                   3531: 
                   3532:     if (u && u->peer.name) {
                   3533: 
                   3534:         uri_separator = "";
                   3535: 
                   3536: #if (NGX_HAVE_UNIX_DOMAIN)
                   3537:         if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
                   3538:             uri_separator = ":";
                   3539:         }
                   3540: #endif
                   3541: 
                   3542:         p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
                   3543:                          &u->schema, u->peer.name,
                   3544:                          uri_separator, &u->uri);
                   3545:         len -= p - buf;
                   3546:         buf = p;
                   3547:     }
                   3548: 
                   3549:     if (r->headers_in.host) {
                   3550:         p = ngx_snprintf(buf, len, ", host: \"%V\"",
                   3551:                          &r->headers_in.host->value);
                   3552:         len -= p - buf;
                   3553:         buf = p;
                   3554:     }
                   3555: 
                   3556:     if (r->headers_in.referer) {
                   3557:         p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
                   3558:                          &r->headers_in.referer->value);
                   3559:         buf = p;
                   3560:     }
                   3561: 
                   3562:     return buf;
                   3563: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>