Annotation of embedaddon/nginx/src/http/ngx_http_request.c, revision 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>