Annotation of embedaddon/nginx/src/http/ngx_http_upstream.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: #if (NGX_HTTP_CACHE)
        !            14: static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
        !            15:     ngx_http_upstream_t *u);
        !            16: static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
        !            17:     ngx_http_upstream_t *u);
        !            18: static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
        !            19:     ngx_http_variable_value_t *v, uintptr_t data);
        !            20: #endif
        !            21: 
        !            22: static void ngx_http_upstream_init_request(ngx_http_request_t *r);
        !            23: static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
        !            24: static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
        !            25: static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
        !            26: static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
        !            27:     ngx_event_t *ev);
        !            28: static void ngx_http_upstream_connect(ngx_http_request_t *r,
        !            29:     ngx_http_upstream_t *u);
        !            30: static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
        !            31:     ngx_http_upstream_t *u);
        !            32: static void ngx_http_upstream_send_request(ngx_http_request_t *r,
        !            33:     ngx_http_upstream_t *u);
        !            34: static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
        !            35:     ngx_http_upstream_t *u);
        !            36: static void ngx_http_upstream_process_header(ngx_http_request_t *r,
        !            37:     ngx_http_upstream_t *u);
        !            38: static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
        !            39:     ngx_http_upstream_t *u);
        !            40: static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
        !            41:     ngx_http_upstream_t *u);
        !            42: static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
        !            43: static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
        !            44:     ngx_http_upstream_t *u);
        !            45: static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
        !            46:     ngx_http_upstream_t *u);
        !            47: static void ngx_http_upstream_send_response(ngx_http_request_t *r,
        !            48:     ngx_http_upstream_t *u);
        !            49: static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
        !            50:     ngx_http_upstream_t *u);
        !            51: static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r);
        !            52: static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r);
        !            53: static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
        !            54:     ngx_http_upstream_t *u);
        !            55: static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
        !            56:     ngx_http_upstream_t *u);
        !            57: static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
        !            58:     ngx_uint_t from_upstream, ngx_uint_t do_write);
        !            59: static void
        !            60:     ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
        !            61: static void
        !            62:     ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
        !            63:     ngx_http_upstream_t *u);
        !            64: static void
        !            65:     ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
        !            66:     ngx_uint_t do_write);
        !            67: static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
        !            68: static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
        !            69:     ssize_t bytes);
        !            70: static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
        !            71: static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
        !            72:     ngx_http_upstream_t *u);
        !            73: static void ngx_http_upstream_process_request(ngx_http_request_t *r);
        !            74: static void ngx_http_upstream_store(ngx_http_request_t *r,
        !            75:     ngx_http_upstream_t *u);
        !            76: static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
        !            77:     ngx_http_upstream_t *u);
        !            78: static void ngx_http_upstream_next(ngx_http_request_t *r,
        !            79:     ngx_http_upstream_t *u, ngx_uint_t ft_type);
        !            80: static void ngx_http_upstream_cleanup(void *data);
        !            81: static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
        !            82:     ngx_http_upstream_t *u, ngx_int_t rc);
        !            83: 
        !            84: static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
        !            85:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            86: static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
        !            87:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            88: static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
        !            89:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            90: static ngx_int_t
        !            91:     ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
        !            92:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            93: static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
        !            94:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            95: static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
        !            96:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            97: static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
        !            98:     ngx_table_elt_t *h, ngx_uint_t offset);
        !            99: static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
        !           100:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           101: static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
        !           102:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           103: static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
        !           104:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           105: static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
        !           106:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           107: static ngx_int_t
        !           108:     ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
        !           109:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           110: static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
        !           111:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           112: static ngx_int_t
        !           113:     ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
        !           114:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           115: static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
        !           116:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           117: static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
        !           118:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           119: static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
        !           120:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           121: static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
        !           122:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           123: static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
        !           124:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           125: static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
        !           126:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           127: 
        !           128: #if (NGX_HTTP_GZIP)
        !           129: static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
        !           130:     ngx_table_elt_t *h, ngx_uint_t offset);
        !           131: #endif
        !           132: 
        !           133: static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
        !           134: static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r,
        !           135:     ngx_http_variable_value_t *v, uintptr_t data);
        !           136: static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
        !           137:     ngx_http_variable_value_t *v, uintptr_t data);
        !           138: static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
        !           139:     ngx_http_variable_value_t *v, uintptr_t data);
        !           140: static ngx_int_t ngx_http_upstream_response_length_variable(
        !           141:     ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
        !           142: 
        !           143: static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
        !           144: static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
        !           145:     void *conf);
        !           146: 
        !           147: static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
        !           148:     ngx_http_upstream_local_t *local);
        !           149: 
        !           150: static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
        !           151: static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
        !           152: 
        !           153: #if (NGX_HTTP_SSL)
        !           154: static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
        !           155:     ngx_http_upstream_t *u, ngx_connection_t *c);
        !           156: static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
        !           157: #endif
        !           158: 
        !           159: 
        !           160: ngx_http_upstream_header_t  ngx_http_upstream_headers_in[] = {
        !           161: 
        !           162:     { ngx_string("Status"),
        !           163:                  ngx_http_upstream_process_header_line,
        !           164:                  offsetof(ngx_http_upstream_headers_in_t, status),
        !           165:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           166: 
        !           167:     { ngx_string("Content-Type"),
        !           168:                  ngx_http_upstream_process_header_line,
        !           169:                  offsetof(ngx_http_upstream_headers_in_t, content_type),
        !           170:                  ngx_http_upstream_copy_content_type, 0, 1 },
        !           171: 
        !           172:     { ngx_string("Content-Length"),
        !           173:                  ngx_http_upstream_process_content_length,
        !           174:                  offsetof(ngx_http_upstream_headers_in_t, content_length),
        !           175:                  ngx_http_upstream_ignore_header_line, 0, 0 },
        !           176: 
        !           177:     { ngx_string("Date"),
        !           178:                  ngx_http_upstream_process_header_line,
        !           179:                  offsetof(ngx_http_upstream_headers_in_t, date),
        !           180:                  ngx_http_upstream_copy_header_line,
        !           181:                  offsetof(ngx_http_headers_out_t, date), 0 },
        !           182: 
        !           183:     { ngx_string("Last-Modified"),
        !           184:                  ngx_http_upstream_process_header_line,
        !           185:                  offsetof(ngx_http_upstream_headers_in_t, last_modified),
        !           186:                  ngx_http_upstream_copy_last_modified, 0, 0 },
        !           187: 
        !           188:     { ngx_string("ETag"),
        !           189:                  ngx_http_upstream_process_header_line,
        !           190:                  offsetof(ngx_http_upstream_headers_in_t, etag),
        !           191:                  ngx_http_upstream_copy_header_line,
        !           192:                  offsetof(ngx_http_headers_out_t, etag), 0 },
        !           193: 
        !           194:     { ngx_string("Server"),
        !           195:                  ngx_http_upstream_process_header_line,
        !           196:                  offsetof(ngx_http_upstream_headers_in_t, server),
        !           197:                  ngx_http_upstream_copy_header_line,
        !           198:                  offsetof(ngx_http_headers_out_t, server), 0 },
        !           199: 
        !           200:     { ngx_string("WWW-Authenticate"),
        !           201:                  ngx_http_upstream_process_header_line,
        !           202:                  offsetof(ngx_http_upstream_headers_in_t, www_authenticate),
        !           203:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           204: 
        !           205:     { ngx_string("Location"),
        !           206:                  ngx_http_upstream_process_header_line,
        !           207:                  offsetof(ngx_http_upstream_headers_in_t, location),
        !           208:                  ngx_http_upstream_rewrite_location, 0, 0 },
        !           209: 
        !           210:     { ngx_string("Refresh"),
        !           211:                  ngx_http_upstream_ignore_header_line, 0,
        !           212:                  ngx_http_upstream_rewrite_refresh, 0, 0 },
        !           213: 
        !           214:     { ngx_string("Set-Cookie"),
        !           215:                  ngx_http_upstream_process_set_cookie, 0,
        !           216:                  ngx_http_upstream_rewrite_set_cookie, 0, 1 },
        !           217: 
        !           218:     { ngx_string("Content-Disposition"),
        !           219:                  ngx_http_upstream_ignore_header_line, 0,
        !           220:                  ngx_http_upstream_copy_header_line, 0, 1 },
        !           221: 
        !           222:     { ngx_string("Cache-Control"),
        !           223:                  ngx_http_upstream_process_cache_control, 0,
        !           224:                  ngx_http_upstream_copy_multi_header_lines,
        !           225:                  offsetof(ngx_http_headers_out_t, cache_control), 1 },
        !           226: 
        !           227:     { ngx_string("Expires"),
        !           228:                  ngx_http_upstream_process_expires, 0,
        !           229:                  ngx_http_upstream_copy_header_line,
        !           230:                  offsetof(ngx_http_headers_out_t, expires), 1 },
        !           231: 
        !           232:     { ngx_string("Accept-Ranges"),
        !           233:                  ngx_http_upstream_process_header_line,
        !           234:                  offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
        !           235:                  ngx_http_upstream_copy_allow_ranges,
        !           236:                  offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
        !           237: 
        !           238:     { ngx_string("Connection"),
        !           239:                  ngx_http_upstream_process_connection, 0,
        !           240:                  ngx_http_upstream_ignore_header_line, 0, 0 },
        !           241: 
        !           242:     { ngx_string("Keep-Alive"),
        !           243:                  ngx_http_upstream_ignore_header_line, 0,
        !           244:                  ngx_http_upstream_ignore_header_line, 0, 0 },
        !           245: 
        !           246:     { ngx_string("X-Powered-By"),
        !           247:                  ngx_http_upstream_ignore_header_line, 0,
        !           248:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           249: 
        !           250:     { ngx_string("X-Accel-Expires"),
        !           251:                  ngx_http_upstream_process_accel_expires, 0,
        !           252:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           253: 
        !           254:     { ngx_string("X-Accel-Redirect"),
        !           255:                  ngx_http_upstream_process_header_line,
        !           256:                  offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect),
        !           257:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           258: 
        !           259:     { ngx_string("X-Accel-Limit-Rate"),
        !           260:                  ngx_http_upstream_process_limit_rate, 0,
        !           261:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           262: 
        !           263:     { ngx_string("X-Accel-Buffering"),
        !           264:                  ngx_http_upstream_process_buffering, 0,
        !           265:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           266: 
        !           267:     { ngx_string("X-Accel-Charset"),
        !           268:                  ngx_http_upstream_process_charset, 0,
        !           269:                  ngx_http_upstream_copy_header_line, 0, 0 },
        !           270: 
        !           271:     { ngx_string("Transfer-Encoding"),
        !           272:                  ngx_http_upstream_process_transfer_encoding, 0,
        !           273:                  ngx_http_upstream_ignore_header_line, 0, 0 },
        !           274: 
        !           275: #if (NGX_HTTP_GZIP)
        !           276:     { ngx_string("Content-Encoding"),
        !           277:                  ngx_http_upstream_process_header_line,
        !           278:                  offsetof(ngx_http_upstream_headers_in_t, content_encoding),
        !           279:                  ngx_http_upstream_copy_content_encoding, 0, 0 },
        !           280: #endif
        !           281: 
        !           282:     { ngx_null_string, NULL, 0, NULL, 0, 0 }
        !           283: };
        !           284: 
        !           285: 
        !           286: static ngx_command_t  ngx_http_upstream_commands[] = {
        !           287: 
        !           288:     { ngx_string("upstream"),
        !           289:       NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1,
        !           290:       ngx_http_upstream,
        !           291:       0,
        !           292:       0,
        !           293:       NULL },
        !           294: 
        !           295:     { ngx_string("server"),
        !           296:       NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
        !           297:       ngx_http_upstream_server,
        !           298:       NGX_HTTP_SRV_CONF_OFFSET,
        !           299:       0,
        !           300:       NULL },
        !           301: 
        !           302:       ngx_null_command
        !           303: };
        !           304: 
        !           305: 
        !           306: static ngx_http_module_t  ngx_http_upstream_module_ctx = {
        !           307:     ngx_http_upstream_add_variables,       /* preconfiguration */
        !           308:     NULL,                                  /* postconfiguration */
        !           309: 
        !           310:     ngx_http_upstream_create_main_conf,    /* create main configuration */
        !           311:     ngx_http_upstream_init_main_conf,      /* init main configuration */
        !           312: 
        !           313:     NULL,                                  /* create server configuration */
        !           314:     NULL,                                  /* merge server configuration */
        !           315: 
        !           316:     NULL,                                  /* create location configuration */
        !           317:     NULL                                   /* merge location configuration */
        !           318: };
        !           319: 
        !           320: 
        !           321: ngx_module_t  ngx_http_upstream_module = {
        !           322:     NGX_MODULE_V1,
        !           323:     &ngx_http_upstream_module_ctx,         /* module context */
        !           324:     ngx_http_upstream_commands,            /* module directives */
        !           325:     NGX_HTTP_MODULE,                       /* module type */
        !           326:     NULL,                                  /* init master */
        !           327:     NULL,                                  /* init module */
        !           328:     NULL,                                  /* init process */
        !           329:     NULL,                                  /* init thread */
        !           330:     NULL,                                  /* exit thread */
        !           331:     NULL,                                  /* exit process */
        !           332:     NULL,                                  /* exit master */
        !           333:     NGX_MODULE_V1_PADDING
        !           334: };
        !           335: 
        !           336: 
        !           337: static ngx_http_variable_t  ngx_http_upstream_vars[] = {
        !           338: 
        !           339:     { ngx_string("upstream_addr"), NULL,
        !           340:       ngx_http_upstream_addr_variable, 0,
        !           341:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           342: 
        !           343:     { ngx_string("upstream_status"), NULL,
        !           344:       ngx_http_upstream_status_variable, 0,
        !           345:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           346: 
        !           347:     { ngx_string("upstream_response_time"), NULL,
        !           348:       ngx_http_upstream_response_time_variable, 0,
        !           349:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           350: 
        !           351:     { ngx_string("upstream_response_length"), NULL,
        !           352:       ngx_http_upstream_response_length_variable, 0,
        !           353:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           354: 
        !           355: #if (NGX_HTTP_CACHE)
        !           356: 
        !           357:     { ngx_string("upstream_cache_status"), NULL,
        !           358:       ngx_http_upstream_cache_status, 0,
        !           359:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           360: 
        !           361: #endif
        !           362: 
        !           363:     { ngx_null_string, NULL, NULL, 0, 0, 0 }
        !           364: };
        !           365: 
        !           366: 
        !           367: static ngx_http_upstream_next_t  ngx_http_upstream_next_errors[] = {
        !           368:     { 500, NGX_HTTP_UPSTREAM_FT_HTTP_500 },
        !           369:     { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502 },
        !           370:     { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503 },
        !           371:     { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 },
        !           372:     { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 },
        !           373:     { 0, 0 }
        !           374: };
        !           375: 
        !           376: 
        !           377: ngx_conf_bitmask_t  ngx_http_upstream_cache_method_mask[] = {
        !           378:    { ngx_string("GET"),  NGX_HTTP_GET},
        !           379:    { ngx_string("HEAD"), NGX_HTTP_HEAD },
        !           380:    { ngx_string("POST"), NGX_HTTP_POST },
        !           381:    { ngx_null_string, 0 }
        !           382: };
        !           383: 
        !           384: 
        !           385: ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[] = {
        !           386:     { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
        !           387:     { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
        !           388:     { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE },
        !           389:     { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING },
        !           390:     { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET },
        !           391:     { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
        !           392:     { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
        !           393:     { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
        !           394:     { ngx_null_string, 0 }
        !           395: };
        !           396: 
        !           397: 
        !           398: ngx_int_t
        !           399: ngx_http_upstream_create(ngx_http_request_t *r)
        !           400: {
        !           401:     ngx_http_upstream_t  *u;
        !           402: 
        !           403:     u = r->upstream;
        !           404: 
        !           405:     if (u && u->cleanup) {
        !           406:         r->main->count++;
        !           407:         ngx_http_upstream_cleanup(r);
        !           408:     }
        !           409: 
        !           410:     u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
        !           411:     if (u == NULL) {
        !           412:         return NGX_ERROR;
        !           413:     }
        !           414: 
        !           415:     r->upstream = u;
        !           416: 
        !           417:     u->peer.log = r->connection->log;
        !           418:     u->peer.log_error = NGX_ERROR_ERR;
        !           419: #if (NGX_THREADS)
        !           420:     u->peer.lock = &r->connection->lock;
        !           421: #endif
        !           422: 
        !           423: #if (NGX_HTTP_CACHE)
        !           424:     r->cache = NULL;
        !           425: #endif
        !           426: 
        !           427:     u->headers_in.content_length_n = -1;
        !           428: 
        !           429:     return NGX_OK;
        !           430: }
        !           431: 
        !           432: 
        !           433: void
        !           434: ngx_http_upstream_init(ngx_http_request_t *r)
        !           435: {
        !           436:     ngx_connection_t     *c;
        !           437: 
        !           438:     c = r->connection;
        !           439: 
        !           440:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !           441:                    "http init upstream, client timer: %d", c->read->timer_set);
        !           442: 
        !           443: #if (NGX_HTTP_SPDY)
        !           444:     if (r->spdy_stream) {
        !           445:         ngx_http_upstream_init_request(r);
        !           446:         return;
        !           447:     }
        !           448: #endif
        !           449: 
        !           450:     if (c->read->timer_set) {
        !           451:         ngx_del_timer(c->read);
        !           452:     }
        !           453: 
        !           454:     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
        !           455: 
        !           456:         if (!c->write->active) {
        !           457:             if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT)
        !           458:                 == NGX_ERROR)
        !           459:             {
        !           460:                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           461:                 return;
        !           462:             }
        !           463:         }
        !           464:     }
        !           465: 
        !           466:     ngx_http_upstream_init_request(r);
        !           467: }
        !           468: 
        !           469: 
        !           470: static void
        !           471: ngx_http_upstream_init_request(ngx_http_request_t *r)
        !           472: {
        !           473:     ngx_str_t                      *host;
        !           474:     ngx_uint_t                      i;
        !           475:     ngx_resolver_ctx_t             *ctx, temp;
        !           476:     ngx_http_cleanup_t             *cln;
        !           477:     ngx_http_upstream_t            *u;
        !           478:     ngx_http_core_loc_conf_t       *clcf;
        !           479:     ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
        !           480:     ngx_http_upstream_main_conf_t  *umcf;
        !           481: 
        !           482:     if (r->aio) {
        !           483:         return;
        !           484:     }
        !           485: 
        !           486:     u = r->upstream;
        !           487: 
        !           488: #if (NGX_HTTP_CACHE)
        !           489: 
        !           490:     if (u->conf->cache) {
        !           491:         ngx_int_t  rc;
        !           492: 
        !           493:         rc = ngx_http_upstream_cache(r, u);
        !           494: 
        !           495:         if (rc == NGX_BUSY) {
        !           496:             r->write_event_handler = ngx_http_upstream_init_request;
        !           497:             return;
        !           498:         }
        !           499: 
        !           500:         r->write_event_handler = ngx_http_request_empty_handler;
        !           501: 
        !           502:         if (rc == NGX_DONE) {
        !           503:             return;
        !           504:         }
        !           505: 
        !           506:         if (rc != NGX_DECLINED) {
        !           507:             ngx_http_finalize_request(r, rc);
        !           508:             return;
        !           509:         }
        !           510:     }
        !           511: 
        !           512: #endif
        !           513: 
        !           514:     u->store = (u->conf->store || u->conf->store_lengths);
        !           515: 
        !           516:     if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
        !           517:         r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
        !           518:         r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
        !           519:     }
        !           520: 
        !           521:     if (r->request_body) {
        !           522:         u->request_bufs = r->request_body->bufs;
        !           523:     }
        !           524: 
        !           525:     if (u->create_request(r) != NGX_OK) {
        !           526:         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           527:         return;
        !           528:     }
        !           529: 
        !           530:     u->peer.local = ngx_http_upstream_get_local(r, u->conf->local);
        !           531: 
        !           532:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !           533: 
        !           534:     u->output.alignment = clcf->directio_alignment;
        !           535:     u->output.pool = r->pool;
        !           536:     u->output.bufs.num = 1;
        !           537:     u->output.bufs.size = clcf->client_body_buffer_size;
        !           538:     u->output.output_filter = ngx_chain_writer;
        !           539:     u->output.filter_ctx = &u->writer;
        !           540: 
        !           541:     u->writer.pool = r->pool;
        !           542: 
        !           543:     if (r->upstream_states == NULL) {
        !           544: 
        !           545:         r->upstream_states = ngx_array_create(r->pool, 1,
        !           546:                                             sizeof(ngx_http_upstream_state_t));
        !           547:         if (r->upstream_states == NULL) {
        !           548:             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           549:             return;
        !           550:         }
        !           551: 
        !           552:     } else {
        !           553: 
        !           554:         u->state = ngx_array_push(r->upstream_states);
        !           555:         if (u->state == NULL) {
        !           556:             ngx_http_upstream_finalize_request(r, u,
        !           557:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           558:             return;
        !           559:         }
        !           560: 
        !           561:         ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
        !           562:     }
        !           563: 
        !           564:     cln = ngx_http_cleanup_add(r, 0);
        !           565:     if (cln == NULL) {
        !           566:         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           567:         return;
        !           568:     }
        !           569: 
        !           570:     cln->handler = ngx_http_upstream_cleanup;
        !           571:     cln->data = r;
        !           572:     u->cleanup = &cln->handler;
        !           573: 
        !           574:     if (u->resolved == NULL) {
        !           575: 
        !           576:         uscf = u->conf->upstream;
        !           577: 
        !           578:     } else {
        !           579: 
        !           580:         if (u->resolved->sockaddr) {
        !           581: 
        !           582:             if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
        !           583:                 != NGX_OK)
        !           584:             {
        !           585:                 ngx_http_upstream_finalize_request(r, u,
        !           586:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           587:                 return;
        !           588:             }
        !           589: 
        !           590:             ngx_http_upstream_connect(r, u);
        !           591: 
        !           592:             return;
        !           593:         }
        !           594: 
        !           595:         host = &u->resolved->host;
        !           596: 
        !           597:         umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
        !           598: 
        !           599:         uscfp = umcf->upstreams.elts;
        !           600: 
        !           601:         for (i = 0; i < umcf->upstreams.nelts; i++) {
        !           602: 
        !           603:             uscf = uscfp[i];
        !           604: 
        !           605:             if (uscf->host.len == host->len
        !           606:                 && ((uscf->port == 0 && u->resolved->no_port)
        !           607:                      || uscf->port == u->resolved->port)
        !           608:                 && ngx_memcmp(uscf->host.data, host->data, host->len) == 0)
        !           609:             {
        !           610:                 goto found;
        !           611:             }
        !           612:         }
        !           613: 
        !           614:         if (u->resolved->port == 0) {
        !           615:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           616:                           "no port in upstream \"%V\"", host);
        !           617:             ngx_http_upstream_finalize_request(r, u,
        !           618:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           619:             return;
        !           620:         }
        !           621: 
        !           622:         temp.name = *host;
        !           623: 
        !           624:         ctx = ngx_resolve_start(clcf->resolver, &temp);
        !           625:         if (ctx == NULL) {
        !           626:             ngx_http_upstream_finalize_request(r, u,
        !           627:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           628:             return;
        !           629:         }
        !           630: 
        !           631:         if (ctx == NGX_NO_RESOLVER) {
        !           632:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           633:                           "no resolver defined to resolve %V", host);
        !           634: 
        !           635:             ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
        !           636:             return;
        !           637:         }
        !           638: 
        !           639:         ctx->name = *host;
        !           640:         ctx->type = NGX_RESOLVE_A;
        !           641:         ctx->handler = ngx_http_upstream_resolve_handler;
        !           642:         ctx->data = r;
        !           643:         ctx->timeout = clcf->resolver_timeout;
        !           644: 
        !           645:         u->resolved->ctx = ctx;
        !           646: 
        !           647:         if (ngx_resolve_name(ctx) != NGX_OK) {
        !           648:             u->resolved->ctx = NULL;
        !           649:             ngx_http_upstream_finalize_request(r, u,
        !           650:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           651:             return;
        !           652:         }
        !           653: 
        !           654:         return;
        !           655:     }
        !           656: 
        !           657: found:
        !           658: 
        !           659:     if (uscf == NULL) {
        !           660:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
        !           661:                       "no upstream configuration");
        !           662:         ngx_http_upstream_finalize_request(r, u,
        !           663:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           664:         return;
        !           665:     }
        !           666: 
        !           667:     if (uscf->peer.init(r, uscf) != NGX_OK) {
        !           668:         ngx_http_upstream_finalize_request(r, u,
        !           669:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           670:         return;
        !           671:     }
        !           672: 
        !           673:     ngx_http_upstream_connect(r, u);
        !           674: }
        !           675: 
        !           676: 
        !           677: #if (NGX_HTTP_CACHE)
        !           678: 
        !           679: static ngx_int_t
        !           680: ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !           681: {
        !           682:     ngx_int_t          rc;
        !           683:     ngx_http_cache_t  *c;
        !           684: 
        !           685:     c = r->cache;
        !           686: 
        !           687:     if (c == NULL) {
        !           688: 
        !           689:         if (!(r->method & u->conf->cache_methods)) {
        !           690:             return NGX_DECLINED;
        !           691:         }
        !           692: 
        !           693:         if (r->method & NGX_HTTP_HEAD) {
        !           694:             u->method = ngx_http_core_get_method;
        !           695:         }
        !           696: 
        !           697:         if (ngx_http_file_cache_new(r) != NGX_OK) {
        !           698:             return NGX_ERROR;
        !           699:         }
        !           700: 
        !           701:         if (u->create_key(r) != NGX_OK) {
        !           702:             return NGX_ERROR;
        !           703:         }
        !           704: 
        !           705:         /* TODO: add keys */
        !           706: 
        !           707:         ngx_http_file_cache_create_key(r);
        !           708: 
        !           709:         if (r->cache->header_start + 256 >= u->conf->buffer_size) {
        !           710:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           711:                           "%V_buffer_size %uz is not enough for cache key, "
        !           712:                           "it should increased at least to %uz",
        !           713:                           &u->conf->module, u->conf->buffer_size,
        !           714:                           ngx_align(r->cache->header_start + 256, 1024));
        !           715: 
        !           716:             r->cache = NULL;
        !           717:             return NGX_DECLINED;
        !           718:         }
        !           719: 
        !           720:         u->cacheable = 1;
        !           721: 
        !           722:         switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
        !           723: 
        !           724:         case NGX_ERROR:
        !           725:             return NGX_ERROR;
        !           726: 
        !           727:         case NGX_DECLINED:
        !           728:             u->cache_status = NGX_HTTP_CACHE_BYPASS;
        !           729:             return NGX_DECLINED;
        !           730: 
        !           731:         default: /* NGX_OK */
        !           732:             break;
        !           733:         }
        !           734: 
        !           735:         c = r->cache;
        !           736: 
        !           737:         c->min_uses = u->conf->cache_min_uses;
        !           738:         c->body_start = u->conf->buffer_size;
        !           739:         c->file_cache = u->conf->cache->data;
        !           740: 
        !           741:         c->lock = u->conf->cache_lock;
        !           742:         c->lock_timeout = u->conf->cache_lock_timeout;
        !           743: 
        !           744:         u->cache_status = NGX_HTTP_CACHE_MISS;
        !           745:     }
        !           746: 
        !           747:     rc = ngx_http_file_cache_open(r);
        !           748: 
        !           749:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           750:                    "http upstream cache: %i", rc);
        !           751: 
        !           752:     switch (rc) {
        !           753: 
        !           754:     case NGX_HTTP_CACHE_UPDATING:
        !           755: 
        !           756:         if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) {
        !           757:             u->cache_status = rc;
        !           758:             rc = NGX_OK;
        !           759: 
        !           760:         } else {
        !           761:             rc = NGX_HTTP_CACHE_STALE;
        !           762:         }
        !           763: 
        !           764:         break;
        !           765: 
        !           766:     case NGX_OK:
        !           767:         u->cache_status = NGX_HTTP_CACHE_HIT;
        !           768:     }
        !           769: 
        !           770:     switch (rc) {
        !           771: 
        !           772:     case NGX_OK:
        !           773: 
        !           774:         rc = ngx_http_upstream_cache_send(r, u);
        !           775: 
        !           776:         if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) {
        !           777:             return rc;
        !           778:         }
        !           779: 
        !           780:         break;
        !           781: 
        !           782:     case NGX_HTTP_CACHE_STALE:
        !           783: 
        !           784:         c->valid_sec = 0;
        !           785:         u->buffer.start = NULL;
        !           786:         u->cache_status = NGX_HTTP_CACHE_EXPIRED;
        !           787: 
        !           788:         break;
        !           789: 
        !           790:     case NGX_DECLINED:
        !           791: 
        !           792:         if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
        !           793:             u->buffer.start = NULL;
        !           794: 
        !           795:         } else {
        !           796:             u->buffer.pos = u->buffer.start + c->header_start;
        !           797:             u->buffer.last = u->buffer.pos;
        !           798:         }
        !           799: 
        !           800:         break;
        !           801: 
        !           802:     case NGX_HTTP_CACHE_SCARCE:
        !           803: 
        !           804:         u->cacheable = 0;
        !           805: 
        !           806:         break;
        !           807: 
        !           808:     case NGX_AGAIN:
        !           809: 
        !           810:         return NGX_BUSY;
        !           811: 
        !           812:     case NGX_ERROR:
        !           813: 
        !           814:         return NGX_ERROR;
        !           815: 
        !           816:     default:
        !           817: 
        !           818:         /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
        !           819: 
        !           820:         u->cache_status = NGX_HTTP_CACHE_HIT;
        !           821: 
        !           822:         return rc;
        !           823:     }
        !           824: 
        !           825:     r->cached = 0;
        !           826: 
        !           827:     return NGX_DECLINED;
        !           828: }
        !           829: 
        !           830: 
        !           831: static ngx_int_t
        !           832: ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !           833: {
        !           834:     ngx_int_t          rc;
        !           835:     ngx_http_cache_t  *c;
        !           836: 
        !           837:     r->cached = 1;
        !           838:     c = r->cache;
        !           839: 
        !           840:     if (c->header_start == c->body_start) {
        !           841:         r->http_version = NGX_HTTP_VERSION_9;
        !           842:         return ngx_http_cache_send(r);
        !           843:     }
        !           844: 
        !           845:     /* TODO: cache stack */
        !           846: 
        !           847:     u->buffer = *c->buf;
        !           848:     u->buffer.pos += c->header_start;
        !           849: 
        !           850:     ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
        !           851:     u->headers_in.content_length_n = -1;
        !           852: 
        !           853:     if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
        !           854:                       sizeof(ngx_table_elt_t))
        !           855:         != NGX_OK)
        !           856:     {
        !           857:         return NGX_ERROR;
        !           858:     }
        !           859: 
        !           860:     rc = u->process_header(r);
        !           861: 
        !           862:     if (rc == NGX_OK) {
        !           863: 
        !           864:         if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
        !           865:             return NGX_DONE;
        !           866:         }
        !           867: 
        !           868:         return ngx_http_cache_send(r);
        !           869:     }
        !           870: 
        !           871:     if (rc == NGX_ERROR) {
        !           872:         return NGX_ERROR;
        !           873:     }
        !           874: 
        !           875:     /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
        !           876: 
        !           877:     /* TODO: delete file */
        !           878: 
        !           879:     return rc;
        !           880: }
        !           881: 
        !           882: #endif
        !           883: 
        !           884: 
        !           885: static void
        !           886: ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
        !           887: {
        !           888:     ngx_connection_t              *c;
        !           889:     ngx_http_request_t            *r;
        !           890:     ngx_http_upstream_t           *u;
        !           891:     ngx_http_upstream_resolved_t  *ur;
        !           892: 
        !           893:     r = ctx->data;
        !           894:     c = r->connection;
        !           895: 
        !           896:     u = r->upstream;
        !           897:     ur = u->resolved;
        !           898: 
        !           899:     if (ctx->state) {
        !           900:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           901:                       "%V could not be resolved (%i: %s)",
        !           902:                       &ctx->name, ctx->state,
        !           903:                       ngx_resolver_strerror(ctx->state));
        !           904: 
        !           905:         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
        !           906:         goto failed;
        !           907:     }
        !           908: 
        !           909:     ur->naddrs = ctx->naddrs;
        !           910:     ur->addrs = ctx->addrs;
        !           911: 
        !           912: #if (NGX_DEBUG)
        !           913:     {
        !           914:     in_addr_t   addr;
        !           915:     ngx_uint_t  i;
        !           916: 
        !           917:     for (i = 0; i < ctx->naddrs; i++) {
        !           918:         addr = ntohl(ur->addrs[i]);
        !           919: 
        !           920:         ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           921:                        "name was resolved to %ud.%ud.%ud.%ud",
        !           922:                        (addr >> 24) & 0xff, (addr >> 16) & 0xff,
        !           923:                        (addr >> 8) & 0xff, addr & 0xff);
        !           924:     }
        !           925:     }
        !           926: #endif
        !           927: 
        !           928:     if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) {
        !           929:         ngx_http_upstream_finalize_request(r, u,
        !           930:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !           931:         goto failed;
        !           932:     }
        !           933: 
        !           934:     ngx_resolve_name_done(ctx);
        !           935:     ur->ctx = NULL;
        !           936: 
        !           937:     ngx_http_upstream_connect(r, u);
        !           938: 
        !           939: failed:
        !           940: 
        !           941:     ngx_http_run_posted_requests(c);
        !           942: }
        !           943: 
        !           944: 
        !           945: static void
        !           946: ngx_http_upstream_handler(ngx_event_t *ev)
        !           947: {
        !           948:     ngx_connection_t     *c;
        !           949:     ngx_http_request_t   *r;
        !           950:     ngx_http_log_ctx_t   *ctx;
        !           951:     ngx_http_upstream_t  *u;
        !           952: 
        !           953:     c = ev->data;
        !           954:     r = c->data;
        !           955: 
        !           956:     u = r->upstream;
        !           957:     c = r->connection;
        !           958: 
        !           959:     ctx = c->log->data;
        !           960:     ctx->current_request = r;
        !           961: 
        !           962:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !           963:                    "http upstream request: \"%V?%V\"", &r->uri, &r->args);
        !           964: 
        !           965:     if (ev->write) {
        !           966:         u->write_event_handler(r, u);
        !           967: 
        !           968:     } else {
        !           969:         u->read_event_handler(r, u);
        !           970:     }
        !           971: 
        !           972:     ngx_http_run_posted_requests(c);
        !           973: }
        !           974: 
        !           975: 
        !           976: static void
        !           977: ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
        !           978: {
        !           979:     ngx_http_upstream_check_broken_connection(r, r->connection->read);
        !           980: }
        !           981: 
        !           982: 
        !           983: static void
        !           984: ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r)
        !           985: {
        !           986:     ngx_http_upstream_check_broken_connection(r, r->connection->write);
        !           987: }
        !           988: 
        !           989: 
        !           990: static void
        !           991: ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
        !           992:     ngx_event_t *ev)
        !           993: {
        !           994:     int                  n;
        !           995:     char                 buf[1];
        !           996:     ngx_err_t            err;
        !           997:     ngx_int_t            event;
        !           998:     ngx_connection_t     *c;
        !           999:     ngx_http_upstream_t  *u;
        !          1000: 
        !          1001:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
        !          1002:                    "http upstream check client, write event:%d, \"%V\"",
        !          1003:                    ev->write, &r->uri);
        !          1004: 
        !          1005:     c = r->connection;
        !          1006:     u = r->upstream;
        !          1007: 
        !          1008:     if (c->error) {
        !          1009:         if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
        !          1010: 
        !          1011:             event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
        !          1012: 
        !          1013:             if (ngx_del_event(ev, event, 0) != NGX_OK) {
        !          1014:                 ngx_http_upstream_finalize_request(r, u,
        !          1015:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1016:                 return;
        !          1017:             }
        !          1018:         }
        !          1019: 
        !          1020:         if (!u->cacheable) {
        !          1021:             ngx_http_upstream_finalize_request(r, u,
        !          1022:                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
        !          1023:         }
        !          1024: 
        !          1025:         return;
        !          1026:     }
        !          1027: 
        !          1028: #if (NGX_HTTP_SPDY)
        !          1029:     if (r->spdy_stream) {
        !          1030:         return;
        !          1031:     }
        !          1032: #endif
        !          1033: 
        !          1034: #if (NGX_HAVE_KQUEUE)
        !          1035: 
        !          1036:     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
        !          1037: 
        !          1038:         if (!ev->pending_eof) {
        !          1039:             return;
        !          1040:         }
        !          1041: 
        !          1042:         ev->eof = 1;
        !          1043:         c->error = 1;
        !          1044: 
        !          1045:         if (ev->kq_errno) {
        !          1046:             ev->error = 1;
        !          1047:         }
        !          1048: 
        !          1049:         if (!u->cacheable && u->peer.connection) {
        !          1050:             ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
        !          1051:                           "kevent() reported that client prematurely closed "
        !          1052:                           "connection, so upstream connection is closed too");
        !          1053:             ngx_http_upstream_finalize_request(r, u,
        !          1054:                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
        !          1055:             return;
        !          1056:         }
        !          1057: 
        !          1058:         ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
        !          1059:                       "kevent() reported that client prematurely closed "
        !          1060:                       "connection");
        !          1061: 
        !          1062:         if (u->peer.connection == NULL) {
        !          1063:             ngx_http_upstream_finalize_request(r, u,
        !          1064:                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
        !          1065:         }
        !          1066: 
        !          1067:         return;
        !          1068:     }
        !          1069: 
        !          1070: #endif
        !          1071: 
        !          1072:     n = recv(c->fd, buf, 1, MSG_PEEK);
        !          1073: 
        !          1074:     err = ngx_socket_errno;
        !          1075: 
        !          1076:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, err,
        !          1077:                    "http upstream recv(): %d", n);
        !          1078: 
        !          1079:     if (ev->write && (n >= 0 || err == NGX_EAGAIN)) {
        !          1080:         return;
        !          1081:     }
        !          1082: 
        !          1083:     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
        !          1084: 
        !          1085:         event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
        !          1086: 
        !          1087:         if (ngx_del_event(ev, event, 0) != NGX_OK) {
        !          1088:             ngx_http_upstream_finalize_request(r, u,
        !          1089:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1090:             return;
        !          1091:         }
        !          1092:     }
        !          1093: 
        !          1094:     if (n > 0) {
        !          1095:         return;
        !          1096:     }
        !          1097: 
        !          1098:     if (n == -1) {
        !          1099:         if (err == NGX_EAGAIN) {
        !          1100:             return;
        !          1101:         }
        !          1102: 
        !          1103:         ev->error = 1;
        !          1104: 
        !          1105:     } else { /* n == 0 */
        !          1106:         err = 0;
        !          1107:     }
        !          1108: 
        !          1109:     ev->eof = 1;
        !          1110:     c->error = 1;
        !          1111: 
        !          1112:     if (!u->cacheable && u->peer.connection) {
        !          1113:         ngx_log_error(NGX_LOG_INFO, ev->log, err,
        !          1114:                       "client prematurely closed connection, "
        !          1115:                       "so upstream connection is closed too");
        !          1116:         ngx_http_upstream_finalize_request(r, u,
        !          1117:                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
        !          1118:         return;
        !          1119:     }
        !          1120: 
        !          1121:     ngx_log_error(NGX_LOG_INFO, ev->log, err,
        !          1122:                   "client prematurely closed connection");
        !          1123: 
        !          1124:     if (u->peer.connection == NULL) {
        !          1125:         ngx_http_upstream_finalize_request(r, u,
        !          1126:                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
        !          1127:     }
        !          1128: }
        !          1129: 
        !          1130: 
        !          1131: static void
        !          1132: ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          1133: {
        !          1134:     ngx_int_t          rc;
        !          1135:     ngx_time_t        *tp;
        !          1136:     ngx_connection_t  *c;
        !          1137: 
        !          1138:     r->connection->log->action = "connecting to upstream";
        !          1139: 
        !          1140:     if (u->state && u->state->response_sec) {
        !          1141:         tp = ngx_timeofday();
        !          1142:         u->state->response_sec = tp->sec - u->state->response_sec;
        !          1143:         u->state->response_msec = tp->msec - u->state->response_msec;
        !          1144:     }
        !          1145: 
        !          1146:     u->state = ngx_array_push(r->upstream_states);
        !          1147:     if (u->state == NULL) {
        !          1148:         ngx_http_upstream_finalize_request(r, u,
        !          1149:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1150:         return;
        !          1151:     }
        !          1152: 
        !          1153:     ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
        !          1154: 
        !          1155:     tp = ngx_timeofday();
        !          1156:     u->state->response_sec = tp->sec;
        !          1157:     u->state->response_msec = tp->msec;
        !          1158: 
        !          1159:     rc = ngx_event_connect_peer(&u->peer);
        !          1160: 
        !          1161:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          1162:                    "http upstream connect: %i", rc);
        !          1163: 
        !          1164:     if (rc == NGX_ERROR) {
        !          1165:         ngx_http_upstream_finalize_request(r, u,
        !          1166:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1167:         return;
        !          1168:     }
        !          1169: 
        !          1170:     u->state->peer = u->peer.name;
        !          1171: 
        !          1172:     if (rc == NGX_BUSY) {
        !          1173:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
        !          1174:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
        !          1175:         return;
        !          1176:     }
        !          1177: 
        !          1178:     if (rc == NGX_DECLINED) {
        !          1179:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        !          1180:         return;
        !          1181:     }
        !          1182: 
        !          1183:     /* rc == NGX_OK || rc == NGX_AGAIN */
        !          1184: 
        !          1185:     c = u->peer.connection;
        !          1186: 
        !          1187:     c->data = r;
        !          1188: 
        !          1189:     c->write->handler = ngx_http_upstream_handler;
        !          1190:     c->read->handler = ngx_http_upstream_handler;
        !          1191: 
        !          1192:     u->write_event_handler = ngx_http_upstream_send_request_handler;
        !          1193:     u->read_event_handler = ngx_http_upstream_process_header;
        !          1194: 
        !          1195:     c->sendfile &= r->connection->sendfile;
        !          1196:     u->output.sendfile = c->sendfile;
        !          1197: 
        !          1198:     if (c->pool == NULL) {
        !          1199: 
        !          1200:         /* we need separate pool here to be able to cache SSL connections */
        !          1201: 
        !          1202:         c->pool = ngx_create_pool(128, r->connection->log);
        !          1203:         if (c->pool == NULL) {
        !          1204:             ngx_http_upstream_finalize_request(r, u,
        !          1205:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1206:             return;
        !          1207:         }
        !          1208:     }
        !          1209: 
        !          1210:     c->log = r->connection->log;
        !          1211:     c->pool->log = c->log;
        !          1212:     c->read->log = c->log;
        !          1213:     c->write->log = c->log;
        !          1214: 
        !          1215:     /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
        !          1216: 
        !          1217:     u->writer.out = NULL;
        !          1218:     u->writer.last = &u->writer.out;
        !          1219:     u->writer.connection = c;
        !          1220:     u->writer.limit = 0;
        !          1221: 
        !          1222:     if (u->request_sent) {
        !          1223:         if (ngx_http_upstream_reinit(r, u) != NGX_OK) {
        !          1224:             ngx_http_upstream_finalize_request(r, u,
        !          1225:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1226:             return;
        !          1227:         }
        !          1228:     }
        !          1229: 
        !          1230:     if (r->request_body
        !          1231:         && r->request_body->buf
        !          1232:         && r->request_body->temp_file
        !          1233:         && r == r->main)
        !          1234:     {
        !          1235:         /*
        !          1236:          * the r->request_body->buf can be reused for one request only,
        !          1237:          * the subrequests should allocate their own temporary bufs
        !          1238:          */
        !          1239: 
        !          1240:         u->output.free = ngx_alloc_chain_link(r->pool);
        !          1241:         if (u->output.free == NULL) {
        !          1242:             ngx_http_upstream_finalize_request(r, u,
        !          1243:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1244:             return;
        !          1245:         }
        !          1246: 
        !          1247:         u->output.free->buf = r->request_body->buf;
        !          1248:         u->output.free->next = NULL;
        !          1249:         u->output.allocated = 1;
        !          1250: 
        !          1251:         r->request_body->buf->pos = r->request_body->buf->start;
        !          1252:         r->request_body->buf->last = r->request_body->buf->start;
        !          1253:         r->request_body->buf->tag = u->output.tag;
        !          1254:     }
        !          1255: 
        !          1256:     u->request_sent = 0;
        !          1257: 
        !          1258:     if (rc == NGX_AGAIN) {
        !          1259:         ngx_add_timer(c->write, u->conf->connect_timeout);
        !          1260:         return;
        !          1261:     }
        !          1262: 
        !          1263: #if (NGX_HTTP_SSL)
        !          1264: 
        !          1265:     if (u->ssl && c->ssl == NULL) {
        !          1266:         ngx_http_upstream_ssl_init_connection(r, u, c);
        !          1267:         return;
        !          1268:     }
        !          1269: 
        !          1270: #endif
        !          1271: 
        !          1272:     ngx_http_upstream_send_request(r, u);
        !          1273: }
        !          1274: 
        !          1275: 
        !          1276: #if (NGX_HTTP_SSL)
        !          1277: 
        !          1278: static void
        !          1279: ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
        !          1280:     ngx_http_upstream_t *u, ngx_connection_t *c)
        !          1281: {
        !          1282:     ngx_int_t   rc;
        !          1283: 
        !          1284:     if (ngx_ssl_create_connection(u->conf->ssl, c,
        !          1285:                                   NGX_SSL_BUFFER|NGX_SSL_CLIENT)
        !          1286:         != NGX_OK)
        !          1287:     {
        !          1288:         ngx_http_upstream_finalize_request(r, u,
        !          1289:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1290:         return;
        !          1291:     }
        !          1292: 
        !          1293:     c->sendfile = 0;
        !          1294:     u->output.sendfile = 0;
        !          1295: 
        !          1296:     if (u->conf->ssl_session_reuse) {
        !          1297:         if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
        !          1298:             ngx_http_upstream_finalize_request(r, u,
        !          1299:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1300:             return;
        !          1301:         }
        !          1302:     }
        !          1303: 
        !          1304:     r->connection->log->action = "SSL handshaking to upstream";
        !          1305: 
        !          1306:     rc = ngx_ssl_handshake(c);
        !          1307: 
        !          1308:     if (rc == NGX_AGAIN) {
        !          1309:         c->ssl->handler = ngx_http_upstream_ssl_handshake;
        !          1310:         return;
        !          1311:     }
        !          1312: 
        !          1313:     ngx_http_upstream_ssl_handshake(c);
        !          1314: }
        !          1315: 
        !          1316: 
        !          1317: static void
        !          1318: ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
        !          1319: {
        !          1320:     ngx_http_request_t   *r;
        !          1321:     ngx_http_upstream_t  *u;
        !          1322: 
        !          1323:     r = c->data;
        !          1324:     u = r->upstream;
        !          1325: 
        !          1326:     if (c->ssl->handshaked) {
        !          1327: 
        !          1328:         if (u->conf->ssl_session_reuse) {
        !          1329:             u->peer.save_session(&u->peer, u->peer.data);
        !          1330:         }
        !          1331: 
        !          1332:         c->write->handler = ngx_http_upstream_handler;
        !          1333:         c->read->handler = ngx_http_upstream_handler;
        !          1334: 
        !          1335:         ngx_http_upstream_send_request(r, u);
        !          1336: 
        !          1337:         return;
        !          1338:     }
        !          1339: 
        !          1340:     ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        !          1341: 
        !          1342: }
        !          1343: 
        !          1344: #endif
        !          1345: 
        !          1346: 
        !          1347: static ngx_int_t
        !          1348: ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          1349: {
        !          1350:     ngx_chain_t  *cl;
        !          1351: 
        !          1352:     if (u->reinit_request(r) != NGX_OK) {
        !          1353:         return NGX_ERROR;
        !          1354:     }
        !          1355: 
        !          1356:     u->keepalive = 0;
        !          1357:     u->upgrade = 0;
        !          1358: 
        !          1359:     ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
        !          1360:     u->headers_in.content_length_n = -1;
        !          1361: 
        !          1362:     if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
        !          1363:                       sizeof(ngx_table_elt_t))
        !          1364:         != NGX_OK)
        !          1365:     {
        !          1366:         return NGX_ERROR;
        !          1367:     }
        !          1368: 
        !          1369:     /* reinit the request chain */
        !          1370: 
        !          1371:     for (cl = u->request_bufs; cl; cl = cl->next) {
        !          1372:         cl->buf->pos = cl->buf->start;
        !          1373:         cl->buf->file_pos = 0;
        !          1374:     }
        !          1375: 
        !          1376:     /* reinit the subrequest's ngx_output_chain() context */
        !          1377: 
        !          1378:     if (r->request_body && r->request_body->temp_file
        !          1379:         && r != r->main && u->output.buf)
        !          1380:     {
        !          1381:         u->output.free = ngx_alloc_chain_link(r->pool);
        !          1382:         if (u->output.free == NULL) {
        !          1383:             return NGX_ERROR;
        !          1384:         }
        !          1385: 
        !          1386:         u->output.free->buf = u->output.buf;
        !          1387:         u->output.free->next = NULL;
        !          1388: 
        !          1389:         u->output.buf->pos = u->output.buf->start;
        !          1390:         u->output.buf->last = u->output.buf->start;
        !          1391:     }
        !          1392: 
        !          1393:     u->output.buf = NULL;
        !          1394:     u->output.in = NULL;
        !          1395:     u->output.busy = NULL;
        !          1396: 
        !          1397:     /* reinit u->buffer */
        !          1398: 
        !          1399:     u->buffer.pos = u->buffer.start;
        !          1400: 
        !          1401: #if (NGX_HTTP_CACHE)
        !          1402: 
        !          1403:     if (r->cache) {
        !          1404:         u->buffer.pos += r->cache->header_start;
        !          1405:     }
        !          1406: 
        !          1407: #endif
        !          1408: 
        !          1409:     u->buffer.last = u->buffer.pos;
        !          1410: 
        !          1411:     return NGX_OK;
        !          1412: }
        !          1413: 
        !          1414: 
        !          1415: static void
        !          1416: ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          1417: {
        !          1418:     ngx_int_t          rc;
        !          1419:     ngx_connection_t  *c;
        !          1420: 
        !          1421:     c = u->peer.connection;
        !          1422: 
        !          1423:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          1424:                    "http upstream send request");
        !          1425: 
        !          1426:     if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
        !          1427:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        !          1428:         return;
        !          1429:     }
        !          1430: 
        !          1431:     c->log->action = "sending request to upstream";
        !          1432: 
        !          1433:     rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs);
        !          1434: 
        !          1435:     u->request_sent = 1;
        !          1436: 
        !          1437:     if (rc == NGX_ERROR) {
        !          1438:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        !          1439:         return;
        !          1440:     }
        !          1441: 
        !          1442:     if (c->write->timer_set) {
        !          1443:         ngx_del_timer(c->write);
        !          1444:     }
        !          1445: 
        !          1446:     if (rc == NGX_AGAIN) {
        !          1447:         ngx_add_timer(c->write, u->conf->send_timeout);
        !          1448: 
        !          1449:         if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
        !          1450:             ngx_http_upstream_finalize_request(r, u,
        !          1451:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1452:             return;
        !          1453:         }
        !          1454: 
        !          1455:         return;
        !          1456:     }
        !          1457: 
        !          1458:     /* rc == NGX_OK */
        !          1459: 
        !          1460:     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
        !          1461:         if (ngx_tcp_push(c->fd) == NGX_ERROR) {
        !          1462:             ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
        !          1463:                           ngx_tcp_push_n " failed");
        !          1464:             ngx_http_upstream_finalize_request(r, u,
        !          1465:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1466:             return;
        !          1467:         }
        !          1468: 
        !          1469:         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
        !          1470:     }
        !          1471: 
        !          1472:     ngx_add_timer(c->read, u->conf->read_timeout);
        !          1473: 
        !          1474: #if 1
        !          1475:     if (c->read->ready) {
        !          1476: 
        !          1477:         /* post aio operation */
        !          1478: 
        !          1479:         /*
        !          1480:          * TODO comment
        !          1481:          * although we can post aio operation just in the end
        !          1482:          * of ngx_http_upstream_connect() CHECK IT !!!
        !          1483:          * it's better to do here because we postpone header buffer allocation
        !          1484:          */
        !          1485: 
        !          1486:         ngx_http_upstream_process_header(r, u);
        !          1487:         return;
        !          1488:     }
        !          1489: #endif
        !          1490: 
        !          1491:     u->write_event_handler = ngx_http_upstream_dummy_handler;
        !          1492: 
        !          1493:     if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
        !          1494:         ngx_http_upstream_finalize_request(r, u,
        !          1495:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1496:         return;
        !          1497:     }
        !          1498: }
        !          1499: 
        !          1500: 
        !          1501: static void
        !          1502: ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
        !          1503:     ngx_http_upstream_t *u)
        !          1504: {
        !          1505:     ngx_connection_t  *c;
        !          1506: 
        !          1507:     c = u->peer.connection;
        !          1508: 
        !          1509:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          1510:                    "http upstream send request handler");
        !          1511: 
        !          1512:     if (c->write->timedout) {
        !          1513:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
        !          1514:         return;
        !          1515:     }
        !          1516: 
        !          1517: #if (NGX_HTTP_SSL)
        !          1518: 
        !          1519:     if (u->ssl && c->ssl == NULL) {
        !          1520:         ngx_http_upstream_ssl_init_connection(r, u, c);
        !          1521:         return;
        !          1522:     }
        !          1523: 
        !          1524: #endif
        !          1525: 
        !          1526:     if (u->header_sent) {
        !          1527:         u->write_event_handler = ngx_http_upstream_dummy_handler;
        !          1528: 
        !          1529:         (void) ngx_handle_write_event(c->write, 0);
        !          1530: 
        !          1531:         return;
        !          1532:     }
        !          1533: 
        !          1534:     ngx_http_upstream_send_request(r, u);
        !          1535: }
        !          1536: 
        !          1537: 
        !          1538: static void
        !          1539: ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          1540: {
        !          1541:     ssize_t            n;
        !          1542:     ngx_int_t          rc;
        !          1543:     ngx_connection_t  *c;
        !          1544: 
        !          1545:     c = u->peer.connection;
        !          1546: 
        !          1547:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          1548:                    "http upstream process header");
        !          1549: 
        !          1550:     c->log->action = "reading response header from upstream";
        !          1551: 
        !          1552:     if (c->read->timedout) {
        !          1553:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
        !          1554:         return;
        !          1555:     }
        !          1556: 
        !          1557:     if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
        !          1558:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        !          1559:         return;
        !          1560:     }
        !          1561: 
        !          1562:     if (u->buffer.start == NULL) {
        !          1563:         u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size);
        !          1564:         if (u->buffer.start == NULL) {
        !          1565:             ngx_http_upstream_finalize_request(r, u,
        !          1566:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1567:             return;
        !          1568:         }
        !          1569: 
        !          1570:         u->buffer.pos = u->buffer.start;
        !          1571:         u->buffer.last = u->buffer.start;
        !          1572:         u->buffer.end = u->buffer.start + u->conf->buffer_size;
        !          1573:         u->buffer.temporary = 1;
        !          1574: 
        !          1575:         u->buffer.tag = u->output.tag;
        !          1576: 
        !          1577:         if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
        !          1578:                           sizeof(ngx_table_elt_t))
        !          1579:             != NGX_OK)
        !          1580:         {
        !          1581:             ngx_http_upstream_finalize_request(r, u,
        !          1582:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1583:             return;
        !          1584:         }
        !          1585: 
        !          1586: #if (NGX_HTTP_CACHE)
        !          1587: 
        !          1588:         if (r->cache) {
        !          1589:             u->buffer.pos += r->cache->header_start;
        !          1590:             u->buffer.last = u->buffer.pos;
        !          1591:         }
        !          1592: #endif
        !          1593:     }
        !          1594: 
        !          1595:     for ( ;; ) {
        !          1596: 
        !          1597:         n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
        !          1598: 
        !          1599:         if (n == NGX_AGAIN) {
        !          1600: #if 0
        !          1601:             ngx_add_timer(rev, u->read_timeout);
        !          1602: #endif
        !          1603: 
        !          1604:             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
        !          1605:                 ngx_http_upstream_finalize_request(r, u,
        !          1606:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1607:                 return;
        !          1608:             }
        !          1609: 
        !          1610:             return;
        !          1611:         }
        !          1612: 
        !          1613:         if (n == 0) {
        !          1614:             ngx_log_error(NGX_LOG_ERR, c->log, 0,
        !          1615:                           "upstream prematurely closed connection");
        !          1616:         }
        !          1617: 
        !          1618:         if (n == NGX_ERROR || n == 0) {
        !          1619:             ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        !          1620:             return;
        !          1621:         }
        !          1622: 
        !          1623:         u->buffer.last += n;
        !          1624: 
        !          1625: #if 0
        !          1626:         u->valid_header_in = 0;
        !          1627: 
        !          1628:         u->peer.cached = 0;
        !          1629: #endif
        !          1630: 
        !          1631:         rc = u->process_header(r);
        !          1632: 
        !          1633:         if (rc == NGX_AGAIN) {
        !          1634: 
        !          1635:             if (u->buffer.last == u->buffer.end) {
        !          1636:                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
        !          1637:                               "upstream sent too big header");
        !          1638: 
        !          1639:                 ngx_http_upstream_next(r, u,
        !          1640:                                        NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
        !          1641:                 return;
        !          1642:             }
        !          1643: 
        !          1644:             continue;
        !          1645:         }
        !          1646: 
        !          1647:         break;
        !          1648:     }
        !          1649: 
        !          1650:     if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
        !          1651:         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
        !          1652:         return;
        !          1653:     }
        !          1654: 
        !          1655:     if (rc == NGX_ERROR) {
        !          1656:         ngx_http_upstream_finalize_request(r, u,
        !          1657:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1658:         return;
        !          1659:     }
        !          1660: 
        !          1661:     /* rc == NGX_OK */
        !          1662: 
        !          1663:     if (u->headers_in.status_n > NGX_HTTP_SPECIAL_RESPONSE) {
        !          1664: 
        !          1665:         if (r->subrequest_in_memory) {
        !          1666:             u->buffer.last = u->buffer.pos;
        !          1667:         }
        !          1668: 
        !          1669:         if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
        !          1670:             return;
        !          1671:         }
        !          1672: 
        !          1673:         if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) {
        !          1674:             return;
        !          1675:         }
        !          1676:     }
        !          1677: 
        !          1678:     if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
        !          1679:         return;
        !          1680:     }
        !          1681: 
        !          1682:     if (!r->subrequest_in_memory) {
        !          1683:         ngx_http_upstream_send_response(r, u);
        !          1684:         return;
        !          1685:     }
        !          1686: 
        !          1687:     /* subrequest content in memory */
        !          1688: 
        !          1689:     if (u->input_filter == NULL) {
        !          1690:         u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
        !          1691:         u->input_filter = ngx_http_upstream_non_buffered_filter;
        !          1692:         u->input_filter_ctx = r;
        !          1693:     }
        !          1694: 
        !          1695:     if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
        !          1696:         ngx_http_upstream_finalize_request(r, u,
        !          1697:                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1698:         return;
        !          1699:     }
        !          1700: 
        !          1701:     n = u->buffer.last - u->buffer.pos;
        !          1702: 
        !          1703:     if (n) {
        !          1704:         u->buffer.last -= n;
        !          1705: 
        !          1706:         u->state->response_length += n;
        !          1707: 
        !          1708:         if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
        !          1709:             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
        !          1710:             return;
        !          1711:         }
        !          1712: 
        !          1713:         if (u->length == 0) {
        !          1714:             ngx_http_upstream_finalize_request(r, u, 0);
        !          1715:             return;
        !          1716:         }
        !          1717:     }
        !          1718: 
        !          1719:     u->read_event_handler = ngx_http_upstream_process_body_in_memory;
        !          1720: 
        !          1721:     ngx_http_upstream_process_body_in_memory(r, u);
        !          1722: }
        !          1723: 
        !          1724: 
        !          1725: static ngx_int_t
        !          1726: ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          1727: {
        !          1728:     ngx_uint_t                 status;
        !          1729:     ngx_http_upstream_next_t  *un;
        !          1730: 
        !          1731:     status = u->headers_in.status_n;
        !          1732: 
        !          1733:     for (un = ngx_http_upstream_next_errors; un->status; un++) {
        !          1734: 
        !          1735:         if (status != un->status) {
        !          1736:             continue;
        !          1737:         }
        !          1738: 
        !          1739:         if (u->peer.tries > 1 && (u->conf->next_upstream & un->mask)) {
        !          1740:             ngx_http_upstream_next(r, u, un->mask);
        !          1741:             return NGX_OK;
        !          1742:         }
        !          1743: 
        !          1744: #if (NGX_HTTP_CACHE)
        !          1745: 
        !          1746:         if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
        !          1747:             && (u->conf->cache_use_stale & un->mask))
        !          1748:         {
        !          1749:             ngx_int_t  rc;
        !          1750: 
        !          1751:             rc = u->reinit_request(r);
        !          1752: 
        !          1753:             if (rc == NGX_OK) {
        !          1754:                 u->cache_status = NGX_HTTP_CACHE_STALE;
        !          1755:                 rc = ngx_http_upstream_cache_send(r, u);
        !          1756:             }
        !          1757: 
        !          1758:             ngx_http_upstream_finalize_request(r, u, rc);
        !          1759:             return NGX_OK;
        !          1760:         }
        !          1761: 
        !          1762: #endif
        !          1763:     }
        !          1764: 
        !          1765:     return NGX_DECLINED;
        !          1766: }
        !          1767: 
        !          1768: 
        !          1769: static ngx_int_t
        !          1770: ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
        !          1771:     ngx_http_upstream_t *u)
        !          1772: {
        !          1773:     ngx_int_t                  status;
        !          1774:     ngx_uint_t                 i;
        !          1775:     ngx_table_elt_t           *h;
        !          1776:     ngx_http_err_page_t       *err_page;
        !          1777:     ngx_http_core_loc_conf_t  *clcf;
        !          1778: 
        !          1779:     status = u->headers_in.status_n;
        !          1780: 
        !          1781:     if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) {
        !          1782:         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
        !          1783:         return NGX_OK;
        !          1784:     }
        !          1785: 
        !          1786:     if (!u->conf->intercept_errors) {
        !          1787:         return NGX_DECLINED;
        !          1788:     }
        !          1789: 
        !          1790:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          1791: 
        !          1792:     if (clcf->error_pages == NULL) {
        !          1793:         return NGX_DECLINED;
        !          1794:     }
        !          1795: 
        !          1796:     err_page = clcf->error_pages->elts;
        !          1797:     for (i = 0; i < clcf->error_pages->nelts; i++) {
        !          1798: 
        !          1799:         if (err_page[i].status == status) {
        !          1800: 
        !          1801:             if (status == NGX_HTTP_UNAUTHORIZED
        !          1802:                 && u->headers_in.www_authenticate)
        !          1803:             {
        !          1804:                 h = ngx_list_push(&r->headers_out.headers);
        !          1805: 
        !          1806:                 if (h == NULL) {
        !          1807:                     ngx_http_upstream_finalize_request(r, u,
        !          1808:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1809:                     return NGX_OK;
        !          1810:                 }
        !          1811: 
        !          1812:                 *h = *u->headers_in.www_authenticate;
        !          1813: 
        !          1814:                 r->headers_out.www_authenticate = h;
        !          1815:             }
        !          1816: 
        !          1817: #if (NGX_HTTP_CACHE)
        !          1818: 
        !          1819:             if (r->cache) {
        !          1820:                 time_t  valid;
        !          1821: 
        !          1822:                 valid = ngx_http_file_cache_valid(u->conf->cache_valid, status);
        !          1823: 
        !          1824:                 if (valid) {
        !          1825:                     r->cache->valid_sec = ngx_time() + valid;
        !          1826:                     r->cache->error = status;
        !          1827:                 }
        !          1828: 
        !          1829:                 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
        !          1830:             }
        !          1831: #endif
        !          1832:             ngx_http_upstream_finalize_request(r, u, status);
        !          1833: 
        !          1834:             return NGX_OK;
        !          1835:         }
        !          1836:     }
        !          1837: 
        !          1838:     return NGX_DECLINED;
        !          1839: }
        !          1840: 
        !          1841: 
        !          1842: static ngx_int_t
        !          1843: ngx_http_upstream_test_connect(ngx_connection_t *c)
        !          1844: {
        !          1845:     int        err;
        !          1846:     socklen_t  len;
        !          1847: 
        !          1848: #if (NGX_HAVE_KQUEUE)
        !          1849: 
        !          1850:     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT)  {
        !          1851:         if (c->write->pending_eof || c->read->pending_eof) {
        !          1852:             if (c->write->pending_eof) {
        !          1853:                 err = c->write->kq_errno;
        !          1854: 
        !          1855:             } else {
        !          1856:                 err = c->read->kq_errno;
        !          1857:             }
        !          1858: 
        !          1859:             c->log->action = "connecting to upstream";
        !          1860:             (void) ngx_connection_error(c, err,
        !          1861:                                     "kevent() reported that connect() failed");
        !          1862:             return NGX_ERROR;
        !          1863:         }
        !          1864: 
        !          1865:     } else
        !          1866: #endif
        !          1867:     {
        !          1868:         err = 0;
        !          1869:         len = sizeof(int);
        !          1870: 
        !          1871:         /*
        !          1872:          * BSDs and Linux return 0 and set a pending error in err
        !          1873:          * Solaris returns -1 and sets errno
        !          1874:          */
        !          1875: 
        !          1876:         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
        !          1877:             == -1)
        !          1878:         {
        !          1879:             err = ngx_errno;
        !          1880:         }
        !          1881: 
        !          1882:         if (err) {
        !          1883:             c->log->action = "connecting to upstream";
        !          1884:             (void) ngx_connection_error(c, err, "connect() failed");
        !          1885:             return NGX_ERROR;
        !          1886:         }
        !          1887:     }
        !          1888: 
        !          1889:     return NGX_OK;
        !          1890: }
        !          1891: 
        !          1892: 
        !          1893: static ngx_int_t
        !          1894: ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          1895: {
        !          1896:     ngx_str_t                      *uri, args;
        !          1897:     ngx_uint_t                      i, flags;
        !          1898:     ngx_list_part_t                *part;
        !          1899:     ngx_table_elt_t                *h;
        !          1900:     ngx_http_upstream_header_t     *hh;
        !          1901:     ngx_http_upstream_main_conf_t  *umcf;
        !          1902: 
        !          1903:     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
        !          1904: 
        !          1905:     if (u->headers_in.x_accel_redirect
        !          1906:         && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT))
        !          1907:     {
        !          1908:         ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
        !          1909: 
        !          1910:         part = &u->headers_in.headers.part;
        !          1911:         h = part->elts;
        !          1912: 
        !          1913:         for (i = 0; /* void */; i++) {
        !          1914: 
        !          1915:             if (i >= part->nelts) {
        !          1916:                 if (part->next == NULL) {
        !          1917:                     break;
        !          1918:                 }
        !          1919: 
        !          1920:                 part = part->next;
        !          1921:                 h = part->elts;
        !          1922:                 i = 0;
        !          1923:             }
        !          1924: 
        !          1925:             hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
        !          1926:                                h[i].lowcase_key, h[i].key.len);
        !          1927: 
        !          1928:             if (hh && hh->redirect) {
        !          1929:                 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
        !          1930:                     ngx_http_finalize_request(r,
        !          1931:                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1932:                     return NGX_DONE;
        !          1933:                 }
        !          1934:             }
        !          1935:         }
        !          1936: 
        !          1937:         uri = &u->headers_in.x_accel_redirect->value;
        !          1938:         ngx_str_null(&args);
        !          1939:         flags = NGX_HTTP_LOG_UNSAFE;
        !          1940: 
        !          1941:         if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
        !          1942:             ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
        !          1943:             return NGX_DONE;
        !          1944:         }
        !          1945: 
        !          1946:         if (r->method != NGX_HTTP_HEAD) {
        !          1947:             r->method = NGX_HTTP_GET;
        !          1948:         }
        !          1949: 
        !          1950:         ngx_http_internal_redirect(r, uri, &args);
        !          1951:         ngx_http_finalize_request(r, NGX_DONE);
        !          1952:         return NGX_DONE;
        !          1953:     }
        !          1954: 
        !          1955:     part = &u->headers_in.headers.part;
        !          1956:     h = part->elts;
        !          1957: 
        !          1958:     for (i = 0; /* void */; i++) {
        !          1959: 
        !          1960:         if (i >= part->nelts) {
        !          1961:             if (part->next == NULL) {
        !          1962:                 break;
        !          1963:             }
        !          1964: 
        !          1965:             part = part->next;
        !          1966:             h = part->elts;
        !          1967:             i = 0;
        !          1968:         }
        !          1969: 
        !          1970:         if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
        !          1971:                           h[i].lowcase_key, h[i].key.len))
        !          1972:         {
        !          1973:             continue;
        !          1974:         }
        !          1975: 
        !          1976:         hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
        !          1977:                            h[i].lowcase_key, h[i].key.len);
        !          1978: 
        !          1979:         if (hh) {
        !          1980:             if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
        !          1981:                 ngx_http_upstream_finalize_request(r, u,
        !          1982:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1983:                 return NGX_DONE;
        !          1984:             }
        !          1985: 
        !          1986:             continue;
        !          1987:         }
        !          1988: 
        !          1989:         if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
        !          1990:             ngx_http_upstream_finalize_request(r, u,
        !          1991:                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
        !          1992:             return NGX_DONE;
        !          1993:         }
        !          1994:     }
        !          1995: 
        !          1996:     if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
        !          1997:         r->headers_out.server->hash = 0;
        !          1998:     }
        !          1999: 
        !          2000:     if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
        !          2001:         r->headers_out.date->hash = 0;
        !          2002:     }
        !          2003: 
        !          2004:     r->headers_out.status = u->headers_in.status_n;
        !          2005:     r->headers_out.status_line = u->headers_in.status_line;
        !          2006: 
        !          2007:     r->headers_out.content_length_n = u->headers_in.content_length_n;
        !          2008: 
        !          2009:     u->length = u->headers_in.content_length_n;
        !          2010: 
        !          2011:     return NGX_OK;
        !          2012: }
        !          2013: 
        !          2014: 
        !          2015: static void
        !          2016: ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
        !          2017:     ngx_http_upstream_t *u)
        !          2018: {
        !          2019:     size_t             size;
        !          2020:     ssize_t            n;
        !          2021:     ngx_buf_t         *b;
        !          2022:     ngx_event_t       *rev;
        !          2023:     ngx_connection_t  *c;
        !          2024: 
        !          2025:     c = u->peer.connection;
        !          2026:     rev = c->read;
        !          2027: 
        !          2028:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2029:                    "http upstream process body on memory");
        !          2030: 
        !          2031:     if (rev->timedout) {
        !          2032:         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
        !          2033:         ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT);
        !          2034:         return;
        !          2035:     }
        !          2036: 
        !          2037:     b = &u->buffer;
        !          2038: 
        !          2039:     for ( ;; ) {
        !          2040: 
        !          2041:         size = b->end - b->last;
        !          2042: 
        !          2043:         if (size == 0) {
        !          2044:             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
        !          2045:                           "upstream buffer is too small to read response");
        !          2046:             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
        !          2047:             return;
        !          2048:         }
        !          2049: 
        !          2050:         n = c->recv(c, b->last, size);
        !          2051: 
        !          2052:         if (n == NGX_AGAIN) {
        !          2053:             break;
        !          2054:         }
        !          2055: 
        !          2056:         if (n == 0 || n == NGX_ERROR) {
        !          2057:             ngx_http_upstream_finalize_request(r, u, n);
        !          2058:             return;
        !          2059:         }
        !          2060: 
        !          2061:         u->state->response_length += n;
        !          2062: 
        !          2063:         if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
        !          2064:             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
        !          2065:             return;
        !          2066:         }
        !          2067: 
        !          2068:         if (!rev->ready) {
        !          2069:             break;
        !          2070:         }
        !          2071:     }
        !          2072: 
        !          2073:     if (u->length == 0) {
        !          2074:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2075:         return;
        !          2076:     }
        !          2077: 
        !          2078:     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
        !          2079:         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
        !          2080:         return;
        !          2081:     }
        !          2082: 
        !          2083:     if (rev->active) {
        !          2084:         ngx_add_timer(rev, u->conf->read_timeout);
        !          2085: 
        !          2086:     } else if (rev->timer_set) {
        !          2087:         ngx_del_timer(rev);
        !          2088:     }
        !          2089: }
        !          2090: 
        !          2091: 
        !          2092: static void
        !          2093: ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          2094: {
        !          2095:     int                        tcp_nodelay;
        !          2096:     ssize_t                    n;
        !          2097:     ngx_int_t                  rc;
        !          2098:     ngx_event_pipe_t          *p;
        !          2099:     ngx_connection_t          *c;
        !          2100:     ngx_http_core_loc_conf_t  *clcf;
        !          2101: 
        !          2102:     rc = ngx_http_send_header(r);
        !          2103: 
        !          2104:     if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
        !          2105:         ngx_http_upstream_finalize_request(r, u, rc);
        !          2106:         return;
        !          2107:     }
        !          2108: 
        !          2109:     if (u->upgrade) {
        !          2110:         ngx_http_upstream_upgrade(r, u);
        !          2111:         return;
        !          2112:     }
        !          2113: 
        !          2114:     c = r->connection;
        !          2115: 
        !          2116:     if (r->header_only) {
        !          2117: 
        !          2118:         if (u->cacheable || u->store) {
        !          2119: 
        !          2120:             if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
        !          2121:                 ngx_connection_error(c, ngx_socket_errno,
        !          2122:                                      ngx_shutdown_socket_n " failed");
        !          2123:             }
        !          2124: 
        !          2125:             r->read_event_handler = ngx_http_request_empty_handler;
        !          2126:             r->write_event_handler = ngx_http_request_empty_handler;
        !          2127:             c->error = 1;
        !          2128: 
        !          2129:         } else {
        !          2130:             ngx_http_upstream_finalize_request(r, u, rc);
        !          2131:             return;
        !          2132:         }
        !          2133:     }
        !          2134: 
        !          2135:     u->header_sent = 1;
        !          2136: 
        !          2137:     if (r->request_body && r->request_body->temp_file) {
        !          2138:         ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
        !          2139:         r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
        !          2140:     }
        !          2141: 
        !          2142:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          2143: 
        !          2144:     if (!u->buffering) {
        !          2145: 
        !          2146:         if (u->input_filter == NULL) {
        !          2147:             u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
        !          2148:             u->input_filter = ngx_http_upstream_non_buffered_filter;
        !          2149:             u->input_filter_ctx = r;
        !          2150:         }
        !          2151: 
        !          2152:         u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
        !          2153:         r->write_event_handler =
        !          2154:                              ngx_http_upstream_process_non_buffered_downstream;
        !          2155: 
        !          2156:         r->limit_rate = 0;
        !          2157: 
        !          2158:         if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
        !          2159:             ngx_http_upstream_finalize_request(r, u, 0);
        !          2160:             return;
        !          2161:         }
        !          2162: 
        !          2163:         if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
        !          2164:             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
        !          2165: 
        !          2166:             tcp_nodelay = 1;
        !          2167: 
        !          2168:             if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
        !          2169:                                (const void *) &tcp_nodelay, sizeof(int)) == -1)
        !          2170:             {
        !          2171:                 ngx_connection_error(c, ngx_socket_errno,
        !          2172:                                      "setsockopt(TCP_NODELAY) failed");
        !          2173:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2174:                 return;
        !          2175:             }
        !          2176: 
        !          2177:             c->tcp_nodelay = NGX_TCP_NODELAY_SET;
        !          2178:         }
        !          2179: 
        !          2180:         n = u->buffer.last - u->buffer.pos;
        !          2181: 
        !          2182:         if (n) {
        !          2183:             u->buffer.last = u->buffer.pos;
        !          2184: 
        !          2185:             u->state->response_length += n;
        !          2186: 
        !          2187:             if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
        !          2188:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2189:                 return;
        !          2190:             }
        !          2191: 
        !          2192:             ngx_http_upstream_process_non_buffered_downstream(r);
        !          2193: 
        !          2194:         } else {
        !          2195:             u->buffer.pos = u->buffer.start;
        !          2196:             u->buffer.last = u->buffer.start;
        !          2197: 
        !          2198:             if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
        !          2199:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2200:                 return;
        !          2201:             }
        !          2202: 
        !          2203:             if (u->peer.connection->read->ready || u->length == 0) {
        !          2204:                 ngx_http_upstream_process_non_buffered_upstream(r, u);
        !          2205:             }
        !          2206:         }
        !          2207: 
        !          2208:         return;
        !          2209:     }
        !          2210: 
        !          2211:     /* TODO: preallocate event_pipe bufs, look "Content-Length" */
        !          2212: 
        !          2213: #if (NGX_HTTP_CACHE)
        !          2214: 
        !          2215:     if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
        !          2216:         ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
        !          2217:         r->cache->file.fd = NGX_INVALID_FILE;
        !          2218:     }
        !          2219: 
        !          2220:     switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
        !          2221: 
        !          2222:     case NGX_ERROR:
        !          2223:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2224:         return;
        !          2225: 
        !          2226:     case NGX_DECLINED:
        !          2227:         u->cacheable = 0;
        !          2228:         break;
        !          2229: 
        !          2230:     default: /* NGX_OK */
        !          2231: 
        !          2232:         if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
        !          2233: 
        !          2234:             r->cache->min_uses = u->conf->cache_min_uses;
        !          2235:             r->cache->body_start = u->conf->buffer_size;
        !          2236:             r->cache->file_cache = u->conf->cache->data;
        !          2237: 
        !          2238:             if (ngx_http_file_cache_create(r) != NGX_OK) {
        !          2239:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2240:                 return;
        !          2241:             }
        !          2242:         }
        !          2243: 
        !          2244:         break;
        !          2245:     }
        !          2246: 
        !          2247:     if (u->cacheable) {
        !          2248:         time_t  now, valid;
        !          2249: 
        !          2250:         now = ngx_time();
        !          2251: 
        !          2252:         valid = r->cache->valid_sec;
        !          2253: 
        !          2254:         if (valid == 0) {
        !          2255:             valid = ngx_http_file_cache_valid(u->conf->cache_valid,
        !          2256:                                               u->headers_in.status_n);
        !          2257:             if (valid) {
        !          2258:                 r->cache->valid_sec = now + valid;
        !          2259:             }
        !          2260:         }
        !          2261: 
        !          2262:         if (valid) {
        !          2263:             r->cache->last_modified = r->headers_out.last_modified_time;
        !          2264:             r->cache->date = now;
        !          2265:             r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
        !          2266: 
        !          2267:             ngx_http_file_cache_set_header(r, u->buffer.start);
        !          2268: 
        !          2269:         } else {
        !          2270:             u->cacheable = 0;
        !          2271:             r->headers_out.last_modified_time = -1;
        !          2272:         }
        !          2273:     }
        !          2274: 
        !          2275:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2276:                    "http cacheable: %d", u->cacheable);
        !          2277: 
        !          2278:     if (u->cacheable == 0 && r->cache) {
        !          2279:         ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
        !          2280:     }
        !          2281: 
        !          2282: #endif
        !          2283: 
        !          2284:     p = u->pipe;
        !          2285: 
        !          2286:     p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter;
        !          2287:     p->output_ctx = r;
        !          2288:     p->tag = u->output.tag;
        !          2289:     p->bufs = u->conf->bufs;
        !          2290:     p->busy_size = u->conf->busy_buffers_size;
        !          2291:     p->upstream = u->peer.connection;
        !          2292:     p->downstream = c;
        !          2293:     p->pool = r->pool;
        !          2294:     p->log = c->log;
        !          2295: 
        !          2296:     p->cacheable = u->cacheable || u->store;
        !          2297: 
        !          2298:     p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
        !          2299:     if (p->temp_file == NULL) {
        !          2300:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2301:         return;
        !          2302:     }
        !          2303: 
        !          2304:     p->temp_file->file.fd = NGX_INVALID_FILE;
        !          2305:     p->temp_file->file.log = c->log;
        !          2306:     p->temp_file->path = u->conf->temp_path;
        !          2307:     p->temp_file->pool = r->pool;
        !          2308: 
        !          2309:     if (p->cacheable) {
        !          2310:         p->temp_file->persistent = 1;
        !          2311: 
        !          2312:     } else {
        !          2313:         p->temp_file->log_level = NGX_LOG_WARN;
        !          2314:         p->temp_file->warn = "an upstream response is buffered "
        !          2315:                              "to a temporary file";
        !          2316:     }
        !          2317: 
        !          2318:     p->max_temp_file_size = u->conf->max_temp_file_size;
        !          2319:     p->temp_file_write_size = u->conf->temp_file_write_size;
        !          2320: 
        !          2321:     p->preread_bufs = ngx_alloc_chain_link(r->pool);
        !          2322:     if (p->preread_bufs == NULL) {
        !          2323:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2324:         return;
        !          2325:     }
        !          2326: 
        !          2327:     p->preread_bufs->buf = &u->buffer;
        !          2328:     p->preread_bufs->next = NULL;
        !          2329:     u->buffer.recycled = 1;
        !          2330: 
        !          2331:     p->preread_size = u->buffer.last - u->buffer.pos;
        !          2332: 
        !          2333:     if (u->cacheable) {
        !          2334: 
        !          2335:         p->buf_to_file = ngx_calloc_buf(r->pool);
        !          2336:         if (p->buf_to_file == NULL) {
        !          2337:             ngx_http_upstream_finalize_request(r, u, 0);
        !          2338:             return;
        !          2339:         }
        !          2340: 
        !          2341:         p->buf_to_file->start = u->buffer.start;
        !          2342:         p->buf_to_file->pos = u->buffer.start;
        !          2343:         p->buf_to_file->last = u->buffer.pos;
        !          2344:         p->buf_to_file->temporary = 1;
        !          2345:     }
        !          2346: 
        !          2347:     if (ngx_event_flags & NGX_USE_AIO_EVENT) {
        !          2348:         /* the posted aio operation may corrupt a shadow buffer */
        !          2349:         p->single_buf = 1;
        !          2350:     }
        !          2351: 
        !          2352:     /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
        !          2353:     p->free_bufs = 1;
        !          2354: 
        !          2355:     /*
        !          2356:      * event_pipe would do u->buffer.last += p->preread_size
        !          2357:      * as though these bytes were read
        !          2358:      */
        !          2359:     u->buffer.last = u->buffer.pos;
        !          2360: 
        !          2361:     if (u->conf->cyclic_temp_file) {
        !          2362: 
        !          2363:         /*
        !          2364:          * we need to disable the use of sendfile() if we use cyclic temp file
        !          2365:          * because the writing a new data may interfere with sendfile()
        !          2366:          * that uses the same kernel file pages (at least on FreeBSD)
        !          2367:          */
        !          2368: 
        !          2369:         p->cyclic_temp_file = 1;
        !          2370:         c->sendfile = 0;
        !          2371: 
        !          2372:     } else {
        !          2373:         p->cyclic_temp_file = 0;
        !          2374:     }
        !          2375: 
        !          2376:     p->read_timeout = u->conf->read_timeout;
        !          2377:     p->send_timeout = clcf->send_timeout;
        !          2378:     p->send_lowat = clcf->send_lowat;
        !          2379: 
        !          2380:     p->length = -1;
        !          2381: 
        !          2382:     if (u->input_filter_init
        !          2383:         && u->input_filter_init(p->input_ctx) != NGX_OK)
        !          2384:     {
        !          2385:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2386:         return;
        !          2387:     }
        !          2388: 
        !          2389:     u->read_event_handler = ngx_http_upstream_process_upstream;
        !          2390:     r->write_event_handler = ngx_http_upstream_process_downstream;
        !          2391: 
        !          2392:     ngx_http_upstream_process_upstream(r, u);
        !          2393: }
        !          2394: 
        !          2395: 
        !          2396: static void
        !          2397: ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          2398: {
        !          2399:     int                        tcp_nodelay;
        !          2400:     ngx_connection_t          *c;
        !          2401:     ngx_http_core_loc_conf_t  *clcf;
        !          2402: 
        !          2403:     c = r->connection;
        !          2404:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          2405: 
        !          2406:     /* TODO: prevent upgrade if not requested or not possible */
        !          2407: 
        !          2408:     r->keepalive = 0;
        !          2409:     c->log->action = "proxying upgraded connection";
        !          2410: 
        !          2411:     u->read_event_handler = ngx_http_upstream_upgraded_read_upstream;
        !          2412:     u->write_event_handler = ngx_http_upstream_upgraded_write_upstream;
        !          2413:     r->read_event_handler = ngx_http_upstream_upgraded_read_downstream;
        !          2414:     r->write_event_handler = ngx_http_upstream_upgraded_write_downstream;
        !          2415: 
        !          2416:     if (clcf->tcp_nodelay) {
        !          2417:         tcp_nodelay = 1;
        !          2418: 
        !          2419:         if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
        !          2420:             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
        !          2421: 
        !          2422:             if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
        !          2423:                            (const void *) &tcp_nodelay, sizeof(int)) == -1)
        !          2424:             {
        !          2425:                 ngx_connection_error(c, ngx_socket_errno,
        !          2426:                                      "setsockopt(TCP_NODELAY) failed");
        !          2427:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2428:                 return;
        !          2429:             }
        !          2430: 
        !          2431:             c->tcp_nodelay = NGX_TCP_NODELAY_SET;
        !          2432:         }
        !          2433: 
        !          2434:         if (u->peer.connection->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
        !          2435:             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, u->peer.connection->log, 0,
        !          2436:                            "tcp_nodelay");
        !          2437: 
        !          2438:             if (setsockopt(u->peer.connection->fd, IPPROTO_TCP, TCP_NODELAY,
        !          2439:                            (const void *) &tcp_nodelay, sizeof(int)) == -1)
        !          2440:             {
        !          2441:                 ngx_connection_error(u->peer.connection, ngx_socket_errno,
        !          2442:                                      "setsockopt(TCP_NODELAY) failed");
        !          2443:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2444:                 return;
        !          2445:             }
        !          2446: 
        !          2447:             u->peer.connection->tcp_nodelay = NGX_TCP_NODELAY_SET;
        !          2448:         }
        !          2449:     }
        !          2450: 
        !          2451:     if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
        !          2452:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2453:         return;
        !          2454:     }
        !          2455: 
        !          2456:     if (u->peer.connection->read->ready
        !          2457:         || u->buffer.pos != u->buffer.last)
        !          2458:     {
        !          2459:         ngx_http_upstream_process_upgraded(r, 1, 1);
        !          2460:     }
        !          2461: 
        !          2462:     if (c->read->ready
        !          2463:         || r->header_in->pos != r->header_in->last)
        !          2464:     {
        !          2465:         ngx_http_upstream_process_upgraded(r, 0, 1);
        !          2466:     }
        !          2467: }
        !          2468: 
        !          2469: 
        !          2470: static void
        !          2471: ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r)
        !          2472: {
        !          2473:     ngx_http_upstream_process_upgraded(r, 0, 0);
        !          2474: }
        !          2475: 
        !          2476: 
        !          2477: static void
        !          2478: ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r)
        !          2479: {
        !          2480:     ngx_http_upstream_process_upgraded(r, 1, 1);
        !          2481: }
        !          2482: 
        !          2483: 
        !          2484: static void
        !          2485: ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
        !          2486:     ngx_http_upstream_t *u)
        !          2487: {
        !          2488:     ngx_http_upstream_process_upgraded(r, 1, 0);
        !          2489: }
        !          2490: 
        !          2491: 
        !          2492: static void
        !          2493: ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
        !          2494:     ngx_http_upstream_t *u)
        !          2495: {
        !          2496:     ngx_http_upstream_process_upgraded(r, 0, 1);
        !          2497: }
        !          2498: 
        !          2499: 
        !          2500: static void
        !          2501: ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
        !          2502:     ngx_uint_t from_upstream, ngx_uint_t do_write)
        !          2503: {
        !          2504:     size_t                     size;
        !          2505:     ssize_t                    n;
        !          2506:     ngx_buf_t                 *b;
        !          2507:     ngx_connection_t          *c, *downstream, *upstream, *dst, *src;
        !          2508:     ngx_http_upstream_t       *u;
        !          2509:     ngx_http_core_loc_conf_t  *clcf;
        !          2510: 
        !          2511:     c = r->connection;
        !          2512:     u = r->upstream;
        !          2513: 
        !          2514:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2515:                    "http upstream process upgraded, fu:%ui", from_upstream);
        !          2516: 
        !          2517:     downstream = c;
        !          2518:     upstream = u->peer.connection;
        !          2519: 
        !          2520:     if (downstream->write->timedout) {
        !          2521:         c->timedout = 1;
        !          2522:         ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
        !          2523:         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
        !          2524:         return;
        !          2525:     }
        !          2526: 
        !          2527:     if (upstream->read->timedout || upstream->write->timedout) {
        !          2528:         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
        !          2529:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2530:         return;
        !          2531:     }
        !          2532: 
        !          2533:     if (from_upstream) {
        !          2534:         src = upstream;
        !          2535:         dst = downstream;
        !          2536:         b = &u->buffer;
        !          2537: 
        !          2538:     } else {
        !          2539:         src = downstream;
        !          2540:         dst = upstream;
        !          2541:         b = &u->from_client;
        !          2542: 
        !          2543:         if (r->header_in->last > r->header_in->pos) {
        !          2544:             b = r->header_in;
        !          2545:             b->end = b->last;
        !          2546:             do_write = 1;
        !          2547:         }
        !          2548: 
        !          2549:         if (b->start == NULL) {
        !          2550:             b->start = ngx_palloc(r->pool, u->conf->buffer_size);
        !          2551:             if (b->start == NULL) {
        !          2552:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2553:                 return;
        !          2554:             }
        !          2555: 
        !          2556:             b->pos = b->start;
        !          2557:             b->last = b->start;
        !          2558:             b->end = b->start + u->conf->buffer_size;
        !          2559:             b->temporary = 1;
        !          2560:             b->tag = u->output.tag;
        !          2561:         }
        !          2562:     }
        !          2563: 
        !          2564:     for ( ;; ) {
        !          2565: 
        !          2566:         if (do_write) {
        !          2567: 
        !          2568:             size = b->last - b->pos;
        !          2569: 
        !          2570:             if (size && dst->write->ready) {
        !          2571: 
        !          2572:                 n = dst->send(dst, b->pos, size);
        !          2573: 
        !          2574:                 if (n == NGX_ERROR) {
        !          2575:                     ngx_http_upstream_finalize_request(r, u, 0);
        !          2576:                     return;
        !          2577:                 }
        !          2578: 
        !          2579:                 if (n > 0) {
        !          2580:                     b->pos += n;
        !          2581: 
        !          2582:                     if (b->pos == b->last) {
        !          2583:                         b->pos = b->start;
        !          2584:                         b->last = b->start;
        !          2585:                     }
        !          2586:                 }
        !          2587:             }
        !          2588:         }
        !          2589: 
        !          2590:         size = b->end - b->last;
        !          2591: 
        !          2592:         if (size && src->read->ready) {
        !          2593: 
        !          2594:             n = src->recv(src, b->last, size);
        !          2595: 
        !          2596:             if (n == NGX_AGAIN || n == 0) {
        !          2597:                 break;
        !          2598:             }
        !          2599: 
        !          2600:             if (n > 0) {
        !          2601:                 do_write = 1;
        !          2602:                 b->last += n;
        !          2603: 
        !          2604:                 continue;
        !          2605:             }
        !          2606: 
        !          2607:             if (n == NGX_ERROR) {
        !          2608:                 src->read->eof = 1;
        !          2609:             }
        !          2610:         }
        !          2611: 
        !          2612:         break;
        !          2613:     }
        !          2614: 
        !          2615:     if ((upstream->read->eof && u->buffer.pos == u->buffer.last)
        !          2616:         || (downstream->read->eof && u->from_client.pos == u->from_client.last)
        !          2617:         || (downstream->read->eof && upstream->read->eof))
        !          2618:     {
        !          2619:         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2620:                        "http upstream upgraded done");
        !          2621:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2622:         return;
        !          2623:     }
        !          2624: 
        !          2625:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          2626: 
        !          2627:     if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
        !          2628:         != NGX_OK)
        !          2629:     {
        !          2630:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2631:         return;
        !          2632:     }
        !          2633: 
        !          2634:     if (upstream->write->active && !upstream->write->ready) {
        !          2635:         ngx_add_timer(upstream->write, u->conf->send_timeout);
        !          2636: 
        !          2637:     } else if (upstream->write->timer_set) {
        !          2638:         ngx_del_timer(upstream->write);
        !          2639:     }
        !          2640: 
        !          2641:     if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
        !          2642:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2643:         return;
        !          2644:     }
        !          2645: 
        !          2646:     if (upstream->read->active && !upstream->read->ready) {
        !          2647:         ngx_add_timer(upstream->read, u->conf->read_timeout);
        !          2648: 
        !          2649:     } else if (upstream->read->timer_set) {
        !          2650:         ngx_del_timer(upstream->read);
        !          2651:     }
        !          2652: 
        !          2653:     if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
        !          2654:         != NGX_OK)
        !          2655:     {
        !          2656:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2657:         return;
        !          2658:     }
        !          2659: 
        !          2660:     if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) {
        !          2661:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2662:         return;
        !          2663:     }
        !          2664: 
        !          2665:     if (downstream->write->active && !downstream->write->ready) {
        !          2666:         ngx_add_timer(downstream->write, clcf->send_timeout);
        !          2667: 
        !          2668:     } else if (downstream->write->timer_set) {
        !          2669:         ngx_del_timer(downstream->write);
        !          2670:     }
        !          2671: }
        !          2672: 
        !          2673: 
        !          2674: static void
        !          2675: ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
        !          2676: {
        !          2677:     ngx_event_t          *wev;
        !          2678:     ngx_connection_t     *c;
        !          2679:     ngx_http_upstream_t  *u;
        !          2680: 
        !          2681:     c = r->connection;
        !          2682:     u = r->upstream;
        !          2683:     wev = c->write;
        !          2684: 
        !          2685:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2686:                    "http upstream process non buffered downstream");
        !          2687: 
        !          2688:     c->log->action = "sending to client";
        !          2689: 
        !          2690:     if (wev->timedout) {
        !          2691:         c->timedout = 1;
        !          2692:         ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
        !          2693:         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
        !          2694:         return;
        !          2695:     }
        !          2696: 
        !          2697:     ngx_http_upstream_process_non_buffered_request(r, 1);
        !          2698: }
        !          2699: 
        !          2700: 
        !          2701: static void
        !          2702: ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
        !          2703:     ngx_http_upstream_t *u)
        !          2704: {
        !          2705:     ngx_connection_t  *c;
        !          2706: 
        !          2707:     c = u->peer.connection;
        !          2708: 
        !          2709:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2710:                    "http upstream process non buffered upstream");
        !          2711: 
        !          2712:     c->log->action = "reading upstream";
        !          2713: 
        !          2714:     if (c->read->timedout) {
        !          2715:         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
        !          2716:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2717:         return;
        !          2718:     }
        !          2719: 
        !          2720:     ngx_http_upstream_process_non_buffered_request(r, 0);
        !          2721: }
        !          2722: 
        !          2723: 
        !          2724: static void
        !          2725: ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
        !          2726:     ngx_uint_t do_write)
        !          2727: {
        !          2728:     size_t                     size;
        !          2729:     ssize_t                    n;
        !          2730:     ngx_buf_t                 *b;
        !          2731:     ngx_int_t                  rc;
        !          2732:     ngx_connection_t          *downstream, *upstream;
        !          2733:     ngx_http_upstream_t       *u;
        !          2734:     ngx_http_core_loc_conf_t  *clcf;
        !          2735: 
        !          2736:     u = r->upstream;
        !          2737:     downstream = r->connection;
        !          2738:     upstream = u->peer.connection;
        !          2739: 
        !          2740:     b = &u->buffer;
        !          2741: 
        !          2742:     do_write = do_write || u->length == 0;
        !          2743: 
        !          2744:     for ( ;; ) {
        !          2745: 
        !          2746:         if (do_write) {
        !          2747: 
        !          2748:             if (u->out_bufs || u->busy_bufs) {
        !          2749:                 rc = ngx_http_output_filter(r, u->out_bufs);
        !          2750: 
        !          2751:                 if (rc == NGX_ERROR) {
        !          2752:                     ngx_http_upstream_finalize_request(r, u, 0);
        !          2753:                     return;
        !          2754:                 }
        !          2755: 
        !          2756:                 ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
        !          2757:                                         &u->out_bufs, u->output.tag);
        !          2758:             }
        !          2759: 
        !          2760:             if (u->busy_bufs == NULL) {
        !          2761: 
        !          2762:                 if (u->length == 0
        !          2763:                     || upstream->read->eof
        !          2764:                     || upstream->read->error)
        !          2765:                 {
        !          2766:                     ngx_http_upstream_finalize_request(r, u, 0);
        !          2767:                     return;
        !          2768:                 }
        !          2769: 
        !          2770:                 b->pos = b->start;
        !          2771:                 b->last = b->start;
        !          2772:             }
        !          2773:         }
        !          2774: 
        !          2775:         size = b->end - b->last;
        !          2776: 
        !          2777:         if (size && upstream->read->ready) {
        !          2778: 
        !          2779:             n = upstream->recv(upstream, b->last, size);
        !          2780: 
        !          2781:             if (n == NGX_AGAIN) {
        !          2782:                 break;
        !          2783:             }
        !          2784: 
        !          2785:             if (n > 0) {
        !          2786:                 u->state->response_length += n;
        !          2787: 
        !          2788:                 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
        !          2789:                     ngx_http_upstream_finalize_request(r, u, 0);
        !          2790:                     return;
        !          2791:                 }
        !          2792:             }
        !          2793: 
        !          2794:             do_write = 1;
        !          2795: 
        !          2796:             continue;
        !          2797:         }
        !          2798: 
        !          2799:         break;
        !          2800:     }
        !          2801: 
        !          2802:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          2803: 
        !          2804:     if (downstream->data == r) {
        !          2805:         if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
        !          2806:             != NGX_OK)
        !          2807:         {
        !          2808:             ngx_http_upstream_finalize_request(r, u, 0);
        !          2809:             return;
        !          2810:         }
        !          2811:     }
        !          2812: 
        !          2813:     if (downstream->write->active && !downstream->write->ready) {
        !          2814:         ngx_add_timer(downstream->write, clcf->send_timeout);
        !          2815: 
        !          2816:     } else if (downstream->write->timer_set) {
        !          2817:         ngx_del_timer(downstream->write);
        !          2818:     }
        !          2819: 
        !          2820:     if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
        !          2821:         ngx_http_upstream_finalize_request(r, u, 0);
        !          2822:         return;
        !          2823:     }
        !          2824: 
        !          2825:     if (upstream->read->active && !upstream->read->ready) {
        !          2826:         ngx_add_timer(upstream->read, u->conf->read_timeout);
        !          2827: 
        !          2828:     } else if (upstream->read->timer_set) {
        !          2829:         ngx_del_timer(upstream->read);
        !          2830:     }
        !          2831: }
        !          2832: 
        !          2833: 
        !          2834: static ngx_int_t
        !          2835: ngx_http_upstream_non_buffered_filter_init(void *data)
        !          2836: {
        !          2837:     return NGX_OK;
        !          2838: }
        !          2839: 
        !          2840: 
        !          2841: static ngx_int_t
        !          2842: ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
        !          2843: {
        !          2844:     ngx_http_request_t  *r = data;
        !          2845: 
        !          2846:     ngx_buf_t            *b;
        !          2847:     ngx_chain_t          *cl, **ll;
        !          2848:     ngx_http_upstream_t  *u;
        !          2849: 
        !          2850:     u = r->upstream;
        !          2851: 
        !          2852:     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
        !          2853:         ll = &cl->next;
        !          2854:     }
        !          2855: 
        !          2856:     cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
        !          2857:     if (cl == NULL) {
        !          2858:         return NGX_ERROR;
        !          2859:     }
        !          2860: 
        !          2861:     *ll = cl;
        !          2862: 
        !          2863:     cl->buf->flush = 1;
        !          2864:     cl->buf->memory = 1;
        !          2865: 
        !          2866:     b = &u->buffer;
        !          2867: 
        !          2868:     cl->buf->pos = b->last;
        !          2869:     b->last += bytes;
        !          2870:     cl->buf->last = b->last;
        !          2871:     cl->buf->tag = u->output.tag;
        !          2872: 
        !          2873:     if (u->length == -1) {
        !          2874:         return NGX_OK;
        !          2875:     }
        !          2876: 
        !          2877:     u->length -= bytes;
        !          2878: 
        !          2879:     return NGX_OK;
        !          2880: }
        !          2881: 
        !          2882: 
        !          2883: static void
        !          2884: ngx_http_upstream_process_downstream(ngx_http_request_t *r)
        !          2885: {
        !          2886:     ngx_event_t          *wev;
        !          2887:     ngx_connection_t     *c;
        !          2888:     ngx_event_pipe_t     *p;
        !          2889:     ngx_http_upstream_t  *u;
        !          2890: 
        !          2891:     c = r->connection;
        !          2892:     u = r->upstream;
        !          2893:     p = u->pipe;
        !          2894:     wev = c->write;
        !          2895: 
        !          2896:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2897:                    "http upstream process downstream");
        !          2898: 
        !          2899:     c->log->action = "sending to client";
        !          2900: 
        !          2901:     if (wev->timedout) {
        !          2902: 
        !          2903:         if (wev->delayed) {
        !          2904: 
        !          2905:             wev->timedout = 0;
        !          2906:             wev->delayed = 0;
        !          2907: 
        !          2908:             if (!wev->ready) {
        !          2909:                 ngx_add_timer(wev, p->send_timeout);
        !          2910: 
        !          2911:                 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
        !          2912:                     ngx_http_upstream_finalize_request(r, u, 0);
        !          2913:                 }
        !          2914: 
        !          2915:                 return;
        !          2916:             }
        !          2917: 
        !          2918:             if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
        !          2919:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2920:                 return;
        !          2921:             }
        !          2922: 
        !          2923:         } else {
        !          2924:             p->downstream_error = 1;
        !          2925:             c->timedout = 1;
        !          2926:             ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
        !          2927:         }
        !          2928: 
        !          2929:     } else {
        !          2930: 
        !          2931:         if (wev->delayed) {
        !          2932: 
        !          2933:             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2934:                            "http downstream delayed");
        !          2935: 
        !          2936:             if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
        !          2937:                 ngx_http_upstream_finalize_request(r, u, 0);
        !          2938:             }
        !          2939: 
        !          2940:             return;
        !          2941:         }
        !          2942: 
        !          2943:         if (ngx_event_pipe(p, 1) == NGX_ABORT) {
        !          2944:             ngx_http_upstream_finalize_request(r, u, 0);
        !          2945:             return;
        !          2946:         }
        !          2947:     }
        !          2948: 
        !          2949:     ngx_http_upstream_process_request(r);
        !          2950: }
        !          2951: 
        !          2952: 
        !          2953: static void
        !          2954: ngx_http_upstream_process_upstream(ngx_http_request_t *r,
        !          2955:     ngx_http_upstream_t *u)
        !          2956: {
        !          2957:     ngx_connection_t  *c;
        !          2958: 
        !          2959:     c = u->peer.connection;
        !          2960: 
        !          2961:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
        !          2962:                    "http upstream process upstream");
        !          2963: 
        !          2964:     c->log->action = "reading upstream";
        !          2965: 
        !          2966:     if (c->read->timedout) {
        !          2967:         u->pipe->upstream_error = 1;
        !          2968:         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
        !          2969: 
        !          2970:     } else {
        !          2971:         if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
        !          2972:             ngx_http_upstream_finalize_request(r, u, 0);
        !          2973:             return;
        !          2974:         }
        !          2975:     }
        !          2976: 
        !          2977:     ngx_http_upstream_process_request(r);
        !          2978: }
        !          2979: 
        !          2980: 
        !          2981: static void
        !          2982: ngx_http_upstream_process_request(ngx_http_request_t *r)
        !          2983: {
        !          2984:     ngx_temp_file_t      *tf;
        !          2985:     ngx_event_pipe_t     *p;
        !          2986:     ngx_http_upstream_t  *u;
        !          2987: 
        !          2988:     u = r->upstream;
        !          2989:     p = u->pipe;
        !          2990: 
        !          2991:     if (u->peer.connection) {
        !          2992: 
        !          2993:         if (u->store) {
        !          2994: 
        !          2995:             if (p->upstream_eof || p->upstream_done) {
        !          2996: 
        !          2997:                 tf = u->pipe->temp_file;
        !          2998: 
        !          2999:                 if (u->headers_in.status_n == NGX_HTTP_OK
        !          3000:                     && (u->headers_in.content_length_n == -1
        !          3001:                         || (u->headers_in.content_length_n == tf->offset)))
        !          3002:                 {
        !          3003:                     ngx_http_upstream_store(r, u);
        !          3004:                     u->store = 0;
        !          3005:                 }
        !          3006:             }
        !          3007:         }
        !          3008: 
        !          3009: #if (NGX_HTTP_CACHE)
        !          3010: 
        !          3011:         if (u->cacheable) {
        !          3012: 
        !          3013:             if (p->upstream_done) {
        !          3014:                 ngx_http_file_cache_update(r, u->pipe->temp_file);
        !          3015: 
        !          3016:             } else if (p->upstream_eof) {
        !          3017: 
        !          3018:                 tf = u->pipe->temp_file;
        !          3019: 
        !          3020:                 if (u->headers_in.content_length_n == -1
        !          3021:                     || u->headers_in.content_length_n
        !          3022:                        == tf->offset - (off_t) r->cache->body_start)
        !          3023:                 {
        !          3024:                     ngx_http_file_cache_update(r, tf);
        !          3025: 
        !          3026:                 } else {
        !          3027:                     ngx_http_file_cache_free(r->cache, tf);
        !          3028:                 }
        !          3029: 
        !          3030:             } else if (p->upstream_error) {
        !          3031:                 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
        !          3032:             }
        !          3033:         }
        !          3034: 
        !          3035: #endif
        !          3036: 
        !          3037:         if (p->upstream_done || p->upstream_eof || p->upstream_error) {
        !          3038:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3039:                            "http upstream exit: %p", p->out);
        !          3040: #if 0
        !          3041:             ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
        !          3042: #endif
        !          3043:             ngx_http_upstream_finalize_request(r, u, 0);
        !          3044:             return;
        !          3045:         }
        !          3046:     }
        !          3047: 
        !          3048:     if (p->downstream_error) {
        !          3049:         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3050:                        "http upstream downstream error");
        !          3051: 
        !          3052:         if (!u->cacheable && !u->store && u->peer.connection) {
        !          3053:             ngx_http_upstream_finalize_request(r, u, 0);
        !          3054:         }
        !          3055:     }
        !          3056: }
        !          3057: 
        !          3058: 
        !          3059: static void
        !          3060: ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          3061: {
        !          3062:     size_t                  root;
        !          3063:     time_t                  lm;
        !          3064:     ngx_str_t               path;
        !          3065:     ngx_temp_file_t        *tf;
        !          3066:     ngx_ext_rename_file_t   ext;
        !          3067: 
        !          3068:     tf = u->pipe->temp_file;
        !          3069: 
        !          3070:     if (tf->file.fd == NGX_INVALID_FILE) {
        !          3071: 
        !          3072:         /* create file for empty 200 response */
        !          3073: 
        !          3074:         tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
        !          3075:         if (tf == NULL) {
        !          3076:             return;
        !          3077:         }
        !          3078: 
        !          3079:         tf->file.fd = NGX_INVALID_FILE;
        !          3080:         tf->file.log = r->connection->log;
        !          3081:         tf->path = u->conf->temp_path;
        !          3082:         tf->pool = r->pool;
        !          3083:         tf->persistent = 1;
        !          3084: 
        !          3085:         if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
        !          3086:                                  tf->persistent, tf->clean, tf->access)
        !          3087:             != NGX_OK)
        !          3088:         {
        !          3089:             return;
        !          3090:         }
        !          3091: 
        !          3092:         u->pipe->temp_file = tf;
        !          3093:     }
        !          3094: 
        !          3095:     ext.access = u->conf->store_access;
        !          3096:     ext.path_access = u->conf->store_access;
        !          3097:     ext.time = -1;
        !          3098:     ext.create_path = 1;
        !          3099:     ext.delete_file = 1;
        !          3100:     ext.log = r->connection->log;
        !          3101: 
        !          3102:     if (u->headers_in.last_modified) {
        !          3103: 
        !          3104:         lm = ngx_http_parse_time(u->headers_in.last_modified->value.data,
        !          3105:                                  u->headers_in.last_modified->value.len);
        !          3106: 
        !          3107:         if (lm != NGX_ERROR) {
        !          3108:             ext.time = lm;
        !          3109:             ext.fd = tf->file.fd;
        !          3110:         }
        !          3111:     }
        !          3112: 
        !          3113:     if (u->conf->store_lengths == NULL) {
        !          3114: 
        !          3115:         ngx_http_map_uri_to_path(r, &path, &root, 0);
        !          3116: 
        !          3117:     } else {
        !          3118:         if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0,
        !          3119:                                 u->conf->store_values->elts)
        !          3120:             == NULL)
        !          3121:         {
        !          3122:             return;
        !          3123:         }
        !          3124:     }
        !          3125: 
        !          3126:     path.len--;
        !          3127: 
        !          3128:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3129:                    "upstream stores \"%s\" to \"%s\"",
        !          3130:                    tf->file.name.data, path.data);
        !          3131: 
        !          3132:     (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);
        !          3133: }
        !          3134: 
        !          3135: 
        !          3136: static void
        !          3137: ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
        !          3138: {
        !          3139:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3140:                    "http upstream dummy handler");
        !          3141: }
        !          3142: 
        !          3143: 
        !          3144: static void
        !          3145: ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
        !          3146:     ngx_uint_t ft_type)
        !          3147: {
        !          3148:     ngx_uint_t  status, state;
        !          3149: 
        !          3150:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3151:                    "http next upstream, %xi", ft_type);
        !          3152: 
        !          3153: #if 0
        !          3154:     ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
        !          3155: #endif
        !          3156: 
        !          3157:     if (u->peer.sockaddr) {
        !          3158: 
        !          3159:         if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
        !          3160:             state = NGX_PEER_NEXT;
        !          3161:         } else {
        !          3162:             state = NGX_PEER_FAILED;
        !          3163:         }
        !          3164: 
        !          3165:         u->peer.free(&u->peer, u->peer.data, state);
        !          3166:         u->peer.sockaddr = NULL;
        !          3167:     }
        !          3168: 
        !          3169:     if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
        !          3170:         ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT,
        !          3171:                       "upstream timed out");
        !          3172:     }
        !          3173: 
        !          3174:     if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
        !          3175:         status = 0;
        !          3176: 
        !          3177:         /* TODO: inform balancer instead */
        !          3178: 
        !          3179:         u->peer.tries++;
        !          3180: 
        !          3181:     } else {
        !          3182:         switch(ft_type) {
        !          3183: 
        !          3184:         case NGX_HTTP_UPSTREAM_FT_TIMEOUT:
        !          3185:             status = NGX_HTTP_GATEWAY_TIME_OUT;
        !          3186:             break;
        !          3187: 
        !          3188:         case NGX_HTTP_UPSTREAM_FT_HTTP_500:
        !          3189:             status = NGX_HTTP_INTERNAL_SERVER_ERROR;
        !          3190:             break;
        !          3191: 
        !          3192:         case NGX_HTTP_UPSTREAM_FT_HTTP_404:
        !          3193:             status = NGX_HTTP_NOT_FOUND;
        !          3194:             break;
        !          3195: 
        !          3196:         /*
        !          3197:          * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
        !          3198:          * never reach here
        !          3199:          */
        !          3200: 
        !          3201:         default:
        !          3202:             status = NGX_HTTP_BAD_GATEWAY;
        !          3203:         }
        !          3204:     }
        !          3205: 
        !          3206:     if (r->connection->error) {
        !          3207:         ngx_http_upstream_finalize_request(r, u,
        !          3208:                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
        !          3209:         return;
        !          3210:     }
        !          3211: 
        !          3212:     if (status) {
        !          3213:         u->state->status = status;
        !          3214: 
        !          3215:         if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
        !          3216: 
        !          3217: #if (NGX_HTTP_CACHE)
        !          3218: 
        !          3219:             if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
        !          3220:                 && (u->conf->cache_use_stale & ft_type))
        !          3221:             {
        !          3222:                 ngx_int_t  rc;
        !          3223: 
        !          3224:                 rc = u->reinit_request(r);
        !          3225: 
        !          3226:                 if (rc == NGX_OK) {
        !          3227:                     u->cache_status = NGX_HTTP_CACHE_STALE;
        !          3228:                     rc = ngx_http_upstream_cache_send(r, u);
        !          3229:                 }
        !          3230: 
        !          3231:                 ngx_http_upstream_finalize_request(r, u, rc);
        !          3232:                 return;
        !          3233:             }
        !          3234: #endif
        !          3235: 
        !          3236:             ngx_http_upstream_finalize_request(r, u, status);
        !          3237:             return;
        !          3238:         }
        !          3239:     }
        !          3240: 
        !          3241:     if (u->peer.connection) {
        !          3242:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3243:                        "close http upstream connection: %d",
        !          3244:                        u->peer.connection->fd);
        !          3245: #if (NGX_HTTP_SSL)
        !          3246: 
        !          3247:         if (u->peer.connection->ssl) {
        !          3248:             u->peer.connection->ssl->no_wait_shutdown = 1;
        !          3249:             u->peer.connection->ssl->no_send_shutdown = 1;
        !          3250: 
        !          3251:             (void) ngx_ssl_shutdown(u->peer.connection);
        !          3252:         }
        !          3253: #endif
        !          3254: 
        !          3255:         if (u->peer.connection->pool) {
        !          3256:             ngx_destroy_pool(u->peer.connection->pool);
        !          3257:         }
        !          3258: 
        !          3259:         ngx_close_connection(u->peer.connection);
        !          3260:         u->peer.connection = NULL;
        !          3261:     }
        !          3262: 
        !          3263: #if 0
        !          3264:     if (u->conf->busy_lock && !u->busy_locked) {
        !          3265:         ngx_http_upstream_busy_lock(p);
        !          3266:         return;
        !          3267:     }
        !          3268: #endif
        !          3269: 
        !          3270:     ngx_http_upstream_connect(r, u);
        !          3271: }
        !          3272: 
        !          3273: 
        !          3274: static void
        !          3275: ngx_http_upstream_cleanup(void *data)
        !          3276: {
        !          3277:     ngx_http_request_t *r = data;
        !          3278: 
        !          3279:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3280:                    "cleanup http upstream request: \"%V\"", &r->uri);
        !          3281: 
        !          3282:     ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE);
        !          3283: }
        !          3284: 
        !          3285: 
        !          3286: static void
        !          3287: ngx_http_upstream_finalize_request(ngx_http_request_t *r,
        !          3288:     ngx_http_upstream_t *u, ngx_int_t rc)
        !          3289: {
        !          3290:     ngx_time_t  *tp;
        !          3291: 
        !          3292:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3293:                    "finalize http upstream request: %i", rc);
        !          3294: 
        !          3295:     if (u->cleanup) {
        !          3296:         *u->cleanup = NULL;
        !          3297:         u->cleanup = NULL;
        !          3298:     }
        !          3299: 
        !          3300:     if (u->resolved && u->resolved->ctx) {
        !          3301:         ngx_resolve_name_done(u->resolved->ctx);
        !          3302:         u->resolved->ctx = NULL;
        !          3303:     }
        !          3304: 
        !          3305:     if (u->state && u->state->response_sec) {
        !          3306:         tp = ngx_timeofday();
        !          3307:         u->state->response_sec = tp->sec - u->state->response_sec;
        !          3308:         u->state->response_msec = tp->msec - u->state->response_msec;
        !          3309: 
        !          3310:         if (u->pipe && u->pipe->read_length) {
        !          3311:             u->state->response_length = u->pipe->read_length;
        !          3312:         }
        !          3313:     }
        !          3314: 
        !          3315:     u->finalize_request(r, rc);
        !          3316: 
        !          3317:     if (u->peer.free && u->peer.sockaddr) {
        !          3318:         u->peer.free(&u->peer, u->peer.data, 0);
        !          3319:         u->peer.sockaddr = NULL;
        !          3320:     }
        !          3321: 
        !          3322:     if (u->peer.connection) {
        !          3323: 
        !          3324: #if (NGX_HTTP_SSL)
        !          3325: 
        !          3326:         /* TODO: do not shutdown persistent connection */
        !          3327: 
        !          3328:         if (u->peer.connection->ssl) {
        !          3329: 
        !          3330:             /*
        !          3331:              * We send the "close notify" shutdown alert to the upstream only
        !          3332:              * and do not wait its "close notify" shutdown alert.
        !          3333:              * It is acceptable according to the TLS standard.
        !          3334:              */
        !          3335: 
        !          3336:             u->peer.connection->ssl->no_wait_shutdown = 1;
        !          3337: 
        !          3338:             (void) ngx_ssl_shutdown(u->peer.connection);
        !          3339:         }
        !          3340: #endif
        !          3341: 
        !          3342:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3343:                        "close http upstream connection: %d",
        !          3344:                        u->peer.connection->fd);
        !          3345: 
        !          3346:         if (u->peer.connection->pool) {
        !          3347:             ngx_destroy_pool(u->peer.connection->pool);
        !          3348:         }
        !          3349: 
        !          3350:         ngx_close_connection(u->peer.connection);
        !          3351:     }
        !          3352: 
        !          3353:     u->peer.connection = NULL;
        !          3354: 
        !          3355:     if (u->pipe && u->pipe->temp_file) {
        !          3356:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3357:                        "http upstream temp fd: %d",
        !          3358:                        u->pipe->temp_file->file.fd);
        !          3359:     }
        !          3360: 
        !          3361:     if (u->store && u->pipe && u->pipe->temp_file
        !          3362:         && u->pipe->temp_file->file.fd != NGX_INVALID_FILE)
        !          3363:     {
        !          3364:         if (ngx_delete_file(u->pipe->temp_file->file.name.data)
        !          3365:             == NGX_FILE_ERROR)
        !          3366:         {
        !          3367:             ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
        !          3368:                           ngx_delete_file_n " \"%s\" failed",
        !          3369:                           u->pipe->temp_file->file.name.data);
        !          3370:         }
        !          3371:     }
        !          3372: 
        !          3373: #if (NGX_HTTP_CACHE)
        !          3374: 
        !          3375:     if (r->cache) {
        !          3376: 
        !          3377:         if (u->cacheable) {
        !          3378: 
        !          3379:             if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
        !          3380:                 time_t  valid;
        !          3381: 
        !          3382:                 valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
        !          3383: 
        !          3384:                 if (valid) {
        !          3385:                     r->cache->valid_sec = ngx_time() + valid;
        !          3386:                     r->cache->error = rc;
        !          3387:                 }
        !          3388:             }
        !          3389:         }
        !          3390: 
        !          3391:         ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
        !          3392:     }
        !          3393: 
        !          3394: #endif
        !          3395: 
        !          3396:     if (u->header_sent
        !          3397:         && rc != NGX_HTTP_REQUEST_TIME_OUT
        !          3398:         && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
        !          3399:     {
        !          3400:         rc = 0;
        !          3401:     }
        !          3402: 
        !          3403:     if (rc == NGX_DECLINED) {
        !          3404:         return;
        !          3405:     }
        !          3406: 
        !          3407:     r->connection->log->action = "sending to client";
        !          3408: 
        !          3409:     if (rc == 0
        !          3410:         && !r->header_only
        !          3411: #if (NGX_HTTP_CACHE)
        !          3412:         && !r->cached
        !          3413: #endif
        !          3414:        )
        !          3415:     {
        !          3416:         rc = ngx_http_send_special(r, NGX_HTTP_LAST);
        !          3417:     }
        !          3418: 
        !          3419:     ngx_http_finalize_request(r, rc);
        !          3420: }
        !          3421: 
        !          3422: 
        !          3423: static ngx_int_t
        !          3424: ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3425:     ngx_uint_t offset)
        !          3426: {
        !          3427:     ngx_table_elt_t  **ph;
        !          3428: 
        !          3429:     ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
        !          3430: 
        !          3431:     if (*ph == NULL) {
        !          3432:         *ph = h;
        !          3433:     }
        !          3434: 
        !          3435:     return NGX_OK;
        !          3436: }
        !          3437: 
        !          3438: 
        !          3439: static ngx_int_t
        !          3440: ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3441:     ngx_uint_t offset)
        !          3442: {
        !          3443:     return NGX_OK;
        !          3444: }
        !          3445: 
        !          3446: 
        !          3447: static ngx_int_t
        !          3448: ngx_http_upstream_process_content_length(ngx_http_request_t *r,
        !          3449:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          3450: {
        !          3451:     ngx_http_upstream_t  *u;
        !          3452: 
        !          3453:     u = r->upstream;
        !          3454: 
        !          3455:     u->headers_in.content_length = h;
        !          3456:     u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);
        !          3457: 
        !          3458:     return NGX_OK;
        !          3459: }
        !          3460: 
        !          3461: 
        !          3462: static ngx_int_t
        !          3463: ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3464:     ngx_uint_t offset)
        !          3465: {
        !          3466: #if (NGX_HTTP_CACHE)
        !          3467:     ngx_http_upstream_t  *u;
        !          3468: 
        !          3469:     u = r->upstream;
        !          3470: 
        !          3471:     if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
        !          3472:         u->cacheable = 0;
        !          3473:     }
        !          3474: #endif
        !          3475: 
        !          3476:     return NGX_OK;
        !          3477: }
        !          3478: 
        !          3479: 
        !          3480: static ngx_int_t
        !          3481: ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
        !          3482:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          3483: {
        !          3484:     ngx_array_t          *pa;
        !          3485:     ngx_table_elt_t     **ph;
        !          3486:     ngx_http_upstream_t  *u;
        !          3487: 
        !          3488:     u = r->upstream;
        !          3489:     pa = &u->headers_in.cache_control;
        !          3490: 
        !          3491:     if (pa->elts == NULL) {
        !          3492:        if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
        !          3493:        {
        !          3494:            return NGX_ERROR;
        !          3495:        }
        !          3496:     }
        !          3497: 
        !          3498:     ph = ngx_array_push(pa);
        !          3499:     if (ph == NULL) {
        !          3500:         return NGX_ERROR;
        !          3501:     }
        !          3502: 
        !          3503:     *ph = h;
        !          3504: 
        !          3505: #if (NGX_HTTP_CACHE)
        !          3506:     {
        !          3507:     u_char     *p, *last;
        !          3508:     ngx_int_t   n;
        !          3509: 
        !          3510:     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) {
        !          3511:         return NGX_OK;
        !          3512:     }
        !          3513: 
        !          3514:     if (r->cache == NULL) {
        !          3515:         return NGX_OK;
        !          3516:     }
        !          3517: 
        !          3518:     if (r->cache->valid_sec != 0) {
        !          3519:         return NGX_OK;
        !          3520:     }
        !          3521: 
        !          3522:     p = h->value.data;
        !          3523:     last = p + h->value.len;
        !          3524: 
        !          3525:     if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
        !          3526:         || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
        !          3527:         || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
        !          3528:     {
        !          3529:         u->cacheable = 0;
        !          3530:         return NGX_OK;
        !          3531:     }
        !          3532: 
        !          3533:     p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
        !          3534: 
        !          3535:     if (p == NULL) {
        !          3536:         return NGX_OK;
        !          3537:     }
        !          3538: 
        !          3539:     n = 0;
        !          3540: 
        !          3541:     for (p += 8; p < last; p++) {
        !          3542:         if (*p == ',' || *p == ';' || *p == ' ') {
        !          3543:             break;
        !          3544:         }
        !          3545: 
        !          3546:         if (*p >= '0' && *p <= '9') {
        !          3547:             n = n * 10 + *p - '0';
        !          3548:             continue;
        !          3549:         }
        !          3550: 
        !          3551:         u->cacheable = 0;
        !          3552:         return NGX_OK;
        !          3553:     }
        !          3554: 
        !          3555:     if (n == 0) {
        !          3556:         u->cacheable = 0;
        !          3557:         return NGX_OK;
        !          3558:     }
        !          3559: 
        !          3560:     r->cache->valid_sec = ngx_time() + n;
        !          3561:     }
        !          3562: #endif
        !          3563: 
        !          3564:     return NGX_OK;
        !          3565: }
        !          3566: 
        !          3567: 
        !          3568: static ngx_int_t
        !          3569: ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3570:     ngx_uint_t offset)
        !          3571: {
        !          3572:     ngx_http_upstream_t  *u;
        !          3573: 
        !          3574:     u = r->upstream;
        !          3575:     u->headers_in.expires = h;
        !          3576: 
        !          3577: #if (NGX_HTTP_CACHE)
        !          3578:     {
        !          3579:     time_t  expires;
        !          3580: 
        !          3581:     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES) {
        !          3582:         return NGX_OK;
        !          3583:     }
        !          3584: 
        !          3585:     if (r->cache == NULL) {
        !          3586:         return NGX_OK;
        !          3587:     }
        !          3588: 
        !          3589:     if (r->cache->valid_sec != 0) {
        !          3590:         return NGX_OK;
        !          3591:     }
        !          3592: 
        !          3593:     expires = ngx_http_parse_time(h->value.data, h->value.len);
        !          3594: 
        !          3595:     if (expires == NGX_ERROR || expires < ngx_time()) {
        !          3596:         u->cacheable = 0;
        !          3597:         return NGX_OK;
        !          3598:     }
        !          3599: 
        !          3600:     r->cache->valid_sec = expires;
        !          3601:     }
        !          3602: #endif
        !          3603: 
        !          3604:     return NGX_OK;
        !          3605: }
        !          3606: 
        !          3607: 
        !          3608: static ngx_int_t
        !          3609: ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
        !          3610:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          3611: {
        !          3612:     ngx_http_upstream_t  *u;
        !          3613: 
        !          3614:     u = r->upstream;
        !          3615:     u->headers_in.x_accel_expires = h;
        !          3616: 
        !          3617: #if (NGX_HTTP_CACHE)
        !          3618:     {
        !          3619:     u_char     *p;
        !          3620:     size_t      len;
        !          3621:     ngx_int_t   n;
        !          3622: 
        !          3623:     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES) {
        !          3624:         return NGX_OK;
        !          3625:     }
        !          3626: 
        !          3627:     if (r->cache == NULL) {
        !          3628:         return NGX_OK;
        !          3629:     }
        !          3630: 
        !          3631:     len = h->value.len;
        !          3632:     p = h->value.data;
        !          3633: 
        !          3634:     if (p[0] != '@') {
        !          3635:         n = ngx_atoi(p, len);
        !          3636: 
        !          3637:         switch (n) {
        !          3638:         case 0:
        !          3639:             u->cacheable = 0;
        !          3640:             /* fall through */
        !          3641: 
        !          3642:         case NGX_ERROR:
        !          3643:             return NGX_OK;
        !          3644: 
        !          3645:         default:
        !          3646:             r->cache->valid_sec = ngx_time() + n;
        !          3647:             return NGX_OK;
        !          3648:         }
        !          3649:     }
        !          3650: 
        !          3651:     p++;
        !          3652:     len--;
        !          3653: 
        !          3654:     n = ngx_atoi(p, len);
        !          3655: 
        !          3656:     if (n != NGX_ERROR) {
        !          3657:         r->cache->valid_sec = n;
        !          3658:     }
        !          3659:     }
        !          3660: #endif
        !          3661: 
        !          3662:     return NGX_OK;
        !          3663: }
        !          3664: 
        !          3665: 
        !          3666: static ngx_int_t
        !          3667: ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3668:     ngx_uint_t offset)
        !          3669: {
        !          3670:     ngx_int_t             n;
        !          3671:     ngx_http_upstream_t  *u;
        !          3672: 
        !          3673:     u = r->upstream;
        !          3674:     u->headers_in.x_accel_limit_rate = h;
        !          3675: 
        !          3676:     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) {
        !          3677:         return NGX_OK;
        !          3678:     }
        !          3679: 
        !          3680:     n = ngx_atoi(h->value.data, h->value.len);
        !          3681: 
        !          3682:     if (n != NGX_ERROR) {
        !          3683:         r->limit_rate = (size_t) n;
        !          3684:     }
        !          3685: 
        !          3686:     return NGX_OK;
        !          3687: }
        !          3688: 
        !          3689: 
        !          3690: static ngx_int_t
        !          3691: ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3692:     ngx_uint_t offset)
        !          3693: {
        !          3694:     u_char                c0, c1, c2;
        !          3695:     ngx_http_upstream_t  *u;
        !          3696: 
        !          3697:     u = r->upstream;
        !          3698: 
        !          3699:     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING) {
        !          3700:         return NGX_OK;
        !          3701:     }
        !          3702: 
        !          3703:     if (u->conf->change_buffering) {
        !          3704: 
        !          3705:         if (h->value.len == 2) {
        !          3706:             c0 = ngx_tolower(h->value.data[0]);
        !          3707:             c1 = ngx_tolower(h->value.data[1]);
        !          3708: 
        !          3709:             if (c0 == 'n' && c1 == 'o') {
        !          3710:                 u->buffering = 0;
        !          3711:             }
        !          3712: 
        !          3713:         } else if (h->value.len == 3) {
        !          3714:             c0 = ngx_tolower(h->value.data[0]);
        !          3715:             c1 = ngx_tolower(h->value.data[1]);
        !          3716:             c2 = ngx_tolower(h->value.data[2]);
        !          3717: 
        !          3718:             if (c0 == 'y' && c1 == 'e' && c2 == 's') {
        !          3719:                 u->buffering = 1;
        !          3720:             }
        !          3721:         }
        !          3722:     }
        !          3723: 
        !          3724:     return NGX_OK;
        !          3725: }
        !          3726: 
        !          3727: 
        !          3728: static ngx_int_t
        !          3729: ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3730:     ngx_uint_t offset)
        !          3731: {
        !          3732:     if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) {
        !          3733:         return NGX_OK;
        !          3734:     }
        !          3735: 
        !          3736:     r->headers_out.override_charset = &h->value;
        !          3737: 
        !          3738:     return NGX_OK;
        !          3739: }
        !          3740: 
        !          3741: 
        !          3742: static ngx_int_t
        !          3743: ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3744:     ngx_uint_t offset)
        !          3745: {
        !          3746:     r->upstream->headers_in.connection = h;
        !          3747: 
        !          3748:     if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
        !          3749:                          (u_char *) "close", 5 - 1)
        !          3750:         != NULL)
        !          3751:     {
        !          3752:         r->upstream->headers_in.connection_close = 1;
        !          3753:     }
        !          3754: 
        !          3755:     return NGX_OK;
        !          3756: }
        !          3757: 
        !          3758: 
        !          3759: static ngx_int_t
        !          3760: ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
        !          3761:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          3762: {
        !          3763:     r->upstream->headers_in.transfer_encoding = h;
        !          3764: 
        !          3765:     if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
        !          3766:                          (u_char *) "chunked", 7 - 1)
        !          3767:         != NULL)
        !          3768:     {
        !          3769:         r->upstream->headers_in.chunked = 1;
        !          3770:     }
        !          3771: 
        !          3772:     return NGX_OK;
        !          3773: }
        !          3774: 
        !          3775: 
        !          3776: static ngx_int_t
        !          3777: ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3778:     ngx_uint_t offset)
        !          3779: {
        !          3780:     ngx_table_elt_t  *ho, **ph;
        !          3781: 
        !          3782:     ho = ngx_list_push(&r->headers_out.headers);
        !          3783:     if (ho == NULL) {
        !          3784:         return NGX_ERROR;
        !          3785:     }
        !          3786: 
        !          3787:     *ho = *h;
        !          3788: 
        !          3789:     if (offset) {
        !          3790:         ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
        !          3791:         *ph = ho;
        !          3792:     }
        !          3793: 
        !          3794:     return NGX_OK;
        !          3795: }
        !          3796: 
        !          3797: 
        !          3798: static ngx_int_t
        !          3799: ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
        !          3800:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          3801: {
        !          3802:     ngx_array_t      *pa;
        !          3803:     ngx_table_elt_t  *ho, **ph;
        !          3804: 
        !          3805:     pa = (ngx_array_t *) ((char *) &r->headers_out + offset);
        !          3806: 
        !          3807:     if (pa->elts == NULL) {
        !          3808:         if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
        !          3809:         {
        !          3810:             return NGX_ERROR;
        !          3811:         }
        !          3812:     }
        !          3813: 
        !          3814:     ph = ngx_array_push(pa);
        !          3815:     if (ph == NULL) {
        !          3816:         return NGX_ERROR;
        !          3817:     }
        !          3818: 
        !          3819:     ho = ngx_list_push(&r->headers_out.headers);
        !          3820:     if (ho == NULL) {
        !          3821:         return NGX_ERROR;
        !          3822:     }
        !          3823: 
        !          3824:     *ho = *h;
        !          3825:     *ph = ho;
        !          3826: 
        !          3827:     return NGX_OK;
        !          3828: }
        !          3829: 
        !          3830: 
        !          3831: static ngx_int_t
        !          3832: ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3833:     ngx_uint_t offset)
        !          3834: {
        !          3835:     u_char  *p, *last;
        !          3836: 
        !          3837:     r->headers_out.content_type_len = h->value.len;
        !          3838:     r->headers_out.content_type = h->value;
        !          3839:     r->headers_out.content_type_lowcase = NULL;
        !          3840: 
        !          3841:     for (p = h->value.data; *p; p++) {
        !          3842: 
        !          3843:         if (*p != ';') {
        !          3844:             continue;
        !          3845:         }
        !          3846: 
        !          3847:         last = p;
        !          3848: 
        !          3849:         while (*++p == ' ') { /* void */ }
        !          3850: 
        !          3851:         if (*p == '\0') {
        !          3852:             return NGX_OK;
        !          3853:         }
        !          3854: 
        !          3855:         if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
        !          3856:             continue;
        !          3857:         }
        !          3858: 
        !          3859:         p += 8;
        !          3860: 
        !          3861:         r->headers_out.content_type_len = last - h->value.data;
        !          3862: 
        !          3863:         if (*p == '"') {
        !          3864:             p++;
        !          3865:         }
        !          3866: 
        !          3867:         last = h->value.data + h->value.len;
        !          3868: 
        !          3869:         if (*(last - 1) == '"') {
        !          3870:             last--;
        !          3871:         }
        !          3872: 
        !          3873:         r->headers_out.charset.len = last - p;
        !          3874:         r->headers_out.charset.data = p;
        !          3875: 
        !          3876:         return NGX_OK;
        !          3877:     }
        !          3878: 
        !          3879:     return NGX_OK;
        !          3880: }
        !          3881: 
        !          3882: 
        !          3883: static ngx_int_t
        !          3884: ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3885:     ngx_uint_t offset)
        !          3886: {
        !          3887:     ngx_table_elt_t  *ho;
        !          3888: 
        !          3889:     ho = ngx_list_push(&r->headers_out.headers);
        !          3890:     if (ho == NULL) {
        !          3891:         return NGX_ERROR;
        !          3892:     }
        !          3893: 
        !          3894:     *ho = *h;
        !          3895: 
        !          3896:     r->headers_out.last_modified = ho;
        !          3897: 
        !          3898: #if (NGX_HTTP_CACHE)
        !          3899: 
        !          3900:     if (r->upstream->cacheable) {
        !          3901:         r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
        !          3902:                                                                 h->value.len);
        !          3903:     }
        !          3904: 
        !          3905: #endif
        !          3906: 
        !          3907:     return NGX_OK;
        !          3908: }
        !          3909: 
        !          3910: 
        !          3911: static ngx_int_t
        !          3912: ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3913:     ngx_uint_t offset)
        !          3914: {
        !          3915:     ngx_int_t         rc;
        !          3916:     ngx_table_elt_t  *ho;
        !          3917: 
        !          3918:     ho = ngx_list_push(&r->headers_out.headers);
        !          3919:     if (ho == NULL) {
        !          3920:         return NGX_ERROR;
        !          3921:     }
        !          3922: 
        !          3923:     *ho = *h;
        !          3924: 
        !          3925:     if (r->upstream->rewrite_redirect) {
        !          3926:         rc = r->upstream->rewrite_redirect(r, ho, 0);
        !          3927: 
        !          3928:         if (rc == NGX_DECLINED) {
        !          3929:             return NGX_OK;
        !          3930:         }
        !          3931: 
        !          3932:         if (rc == NGX_OK) {
        !          3933:             r->headers_out.location = ho;
        !          3934: 
        !          3935:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3936:                            "rewritten location: \"%V\"", &ho->value);
        !          3937:         }
        !          3938: 
        !          3939:         return rc;
        !          3940:     }
        !          3941: 
        !          3942:     if (ho->value.data[0] != '/') {
        !          3943:         r->headers_out.location = ho;
        !          3944:     }
        !          3945: 
        !          3946:     /*
        !          3947:      * we do not set r->headers_out.location here to avoid the handling
        !          3948:      * the local redirects without a host name by ngx_http_header_filter()
        !          3949:      */
        !          3950: 
        !          3951:     return NGX_OK;
        !          3952: }
        !          3953: 
        !          3954: 
        !          3955: static ngx_int_t
        !          3956: ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          3957:     ngx_uint_t offset)
        !          3958: {
        !          3959:     u_char           *p;
        !          3960:     ngx_int_t         rc;
        !          3961:     ngx_table_elt_t  *ho;
        !          3962: 
        !          3963:     ho = ngx_list_push(&r->headers_out.headers);
        !          3964:     if (ho == NULL) {
        !          3965:         return NGX_ERROR;
        !          3966:     }
        !          3967: 
        !          3968:     *ho = *h;
        !          3969: 
        !          3970:     if (r->upstream->rewrite_redirect) {
        !          3971: 
        !          3972:         p = ngx_strcasestrn(ho->value.data, "url=", 4 - 1);
        !          3973: 
        !          3974:         if (p) {
        !          3975:             rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data);
        !          3976: 
        !          3977:         } else {
        !          3978:             return NGX_OK;
        !          3979:         }
        !          3980: 
        !          3981:         if (rc == NGX_DECLINED) {
        !          3982:             return NGX_OK;
        !          3983:         }
        !          3984: 
        !          3985:         if (rc == NGX_OK) {
        !          3986:             r->headers_out.refresh = ho;
        !          3987: 
        !          3988:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          3989:                            "rewritten refresh: \"%V\"", &ho->value);
        !          3990:         }
        !          3991: 
        !          3992:         return rc;
        !          3993:     }
        !          3994: 
        !          3995:     r->headers_out.refresh = ho;
        !          3996: 
        !          3997:     return NGX_OK;
        !          3998: }
        !          3999: 
        !          4000: 
        !          4001: static ngx_int_t
        !          4002: ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
        !          4003:     ngx_uint_t offset)
        !          4004: {
        !          4005:     ngx_int_t         rc;
        !          4006:     ngx_table_elt_t  *ho;
        !          4007: 
        !          4008:     ho = ngx_list_push(&r->headers_out.headers);
        !          4009:     if (ho == NULL) {
        !          4010:         return NGX_ERROR;
        !          4011:     }
        !          4012: 
        !          4013:     *ho = *h;
        !          4014: 
        !          4015:     if (r->upstream->rewrite_cookie) {
        !          4016:         rc = r->upstream->rewrite_cookie(r, ho);
        !          4017: 
        !          4018:         if (rc == NGX_DECLINED) {
        !          4019:             return NGX_OK;
        !          4020:         }
        !          4021: 
        !          4022: #if (NGX_DEBUG)
        !          4023:         if (rc == NGX_OK) {
        !          4024:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          4025:                            "rewritten cookie: \"%V\"", &ho->value);
        !          4026:         }
        !          4027: #endif
        !          4028: 
        !          4029:         return rc;
        !          4030:     }
        !          4031: 
        !          4032:     return NGX_OK;
        !          4033: }
        !          4034: 
        !          4035: 
        !          4036: static ngx_int_t
        !          4037: ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
        !          4038:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          4039: {
        !          4040:     ngx_table_elt_t  *ho;
        !          4041: 
        !          4042: #if (NGX_HTTP_CACHE)
        !          4043: 
        !          4044:     if (r->cached) {
        !          4045:         r->allow_ranges = 1;
        !          4046:         return NGX_OK;
        !          4047: 
        !          4048:     }
        !          4049: 
        !          4050: #endif
        !          4051: 
        !          4052:     ho = ngx_list_push(&r->headers_out.headers);
        !          4053:     if (ho == NULL) {
        !          4054:         return NGX_ERROR;
        !          4055:     }
        !          4056: 
        !          4057:     *ho = *h;
        !          4058: 
        !          4059:     r->headers_out.accept_ranges = ho;
        !          4060: 
        !          4061:     return NGX_OK;
        !          4062: }
        !          4063: 
        !          4064: 
        !          4065: #if (NGX_HTTP_GZIP)
        !          4066: 
        !          4067: static ngx_int_t
        !          4068: ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
        !          4069:     ngx_table_elt_t *h, ngx_uint_t offset)
        !          4070: {
        !          4071:     ngx_table_elt_t  *ho;
        !          4072: 
        !          4073:     ho = ngx_list_push(&r->headers_out.headers);
        !          4074:     if (ho == NULL) {
        !          4075:         return NGX_ERROR;
        !          4076:     }
        !          4077: 
        !          4078:     *ho = *h;
        !          4079: 
        !          4080:     r->headers_out.content_encoding = ho;
        !          4081: 
        !          4082:     return NGX_OK;
        !          4083: }
        !          4084: 
        !          4085: #endif
        !          4086: 
        !          4087: 
        !          4088: static ngx_int_t
        !          4089: ngx_http_upstream_add_variables(ngx_conf_t *cf)
        !          4090: {
        !          4091:     ngx_http_variable_t  *var, *v;
        !          4092: 
        !          4093:     for (v = ngx_http_upstream_vars; v->name.len; v++) {
        !          4094:         var = ngx_http_add_variable(cf, &v->name, v->flags);
        !          4095:         if (var == NULL) {
        !          4096:             return NGX_ERROR;
        !          4097:         }
        !          4098: 
        !          4099:         var->get_handler = v->get_handler;
        !          4100:         var->data = v->data;
        !          4101:     }
        !          4102: 
        !          4103:     return NGX_OK;
        !          4104: }
        !          4105: 
        !          4106: 
        !          4107: static ngx_int_t
        !          4108: ngx_http_upstream_addr_variable(ngx_http_request_t *r,
        !          4109:     ngx_http_variable_value_t *v, uintptr_t data)
        !          4110: {
        !          4111:     u_char                     *p;
        !          4112:     size_t                      len;
        !          4113:     ngx_uint_t                  i;
        !          4114:     ngx_http_upstream_state_t  *state;
        !          4115: 
        !          4116:     v->valid = 1;
        !          4117:     v->no_cacheable = 0;
        !          4118:     v->not_found = 0;
        !          4119: 
        !          4120:     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
        !          4121:         v->not_found = 1;
        !          4122:         return NGX_OK;
        !          4123:     }
        !          4124: 
        !          4125:     len = 0;
        !          4126:     state = r->upstream_states->elts;
        !          4127: 
        !          4128:     for (i = 0; i < r->upstream_states->nelts; i++) {
        !          4129:         if (state[i].peer) {
        !          4130:             len += state[i].peer->len + 2;
        !          4131: 
        !          4132:         } else {
        !          4133:             len += 3;
        !          4134:         }
        !          4135:     }
        !          4136: 
        !          4137:     p = ngx_pnalloc(r->pool, len);
        !          4138:     if (p == NULL) {
        !          4139:         return NGX_ERROR;
        !          4140:     }
        !          4141: 
        !          4142:     v->data = p;
        !          4143: 
        !          4144:     i = 0;
        !          4145: 
        !          4146:     for ( ;; ) {
        !          4147:         if (state[i].peer) {
        !          4148:             p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len);
        !          4149:         }
        !          4150: 
        !          4151:         if (++i == r->upstream_states->nelts) {
        !          4152:             break;
        !          4153:         }
        !          4154: 
        !          4155:         if (state[i].peer) {
        !          4156:             *p++ = ',';
        !          4157:             *p++ = ' ';
        !          4158: 
        !          4159:         } else {
        !          4160:             *p++ = ' ';
        !          4161:             *p++ = ':';
        !          4162:             *p++ = ' ';
        !          4163: 
        !          4164:             if (++i == r->upstream_states->nelts) {
        !          4165:                 break;
        !          4166:             }
        !          4167: 
        !          4168:             continue;
        !          4169:         }
        !          4170:     }
        !          4171: 
        !          4172:     v->len = p - v->data;
        !          4173: 
        !          4174:     return NGX_OK;
        !          4175: }
        !          4176: 
        !          4177: 
        !          4178: static ngx_int_t
        !          4179: ngx_http_upstream_status_variable(ngx_http_request_t *r,
        !          4180:     ngx_http_variable_value_t *v, uintptr_t data)
        !          4181: {
        !          4182:     u_char                     *p;
        !          4183:     size_t                      len;
        !          4184:     ngx_uint_t                  i;
        !          4185:     ngx_http_upstream_state_t  *state;
        !          4186: 
        !          4187:     v->valid = 1;
        !          4188:     v->no_cacheable = 0;
        !          4189:     v->not_found = 0;
        !          4190: 
        !          4191:     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
        !          4192:         v->not_found = 1;
        !          4193:         return NGX_OK;
        !          4194:     }
        !          4195: 
        !          4196:     len = r->upstream_states->nelts * (3 + 2);
        !          4197: 
        !          4198:     p = ngx_pnalloc(r->pool, len);
        !          4199:     if (p == NULL) {
        !          4200:         return NGX_ERROR;
        !          4201:     }
        !          4202: 
        !          4203:     v->data = p;
        !          4204: 
        !          4205:     i = 0;
        !          4206:     state = r->upstream_states->elts;
        !          4207: 
        !          4208:     for ( ;; ) {
        !          4209:         if (state[i].status) {
        !          4210:             p = ngx_sprintf(p, "%ui", state[i].status);
        !          4211: 
        !          4212:         } else {
        !          4213:             *p++ = '-';
        !          4214:         }
        !          4215: 
        !          4216:         if (++i == r->upstream_states->nelts) {
        !          4217:             break;
        !          4218:         }
        !          4219: 
        !          4220:         if (state[i].peer) {
        !          4221:             *p++ = ',';
        !          4222:             *p++ = ' ';
        !          4223: 
        !          4224:         } else {
        !          4225:             *p++ = ' ';
        !          4226:             *p++ = ':';
        !          4227:             *p++ = ' ';
        !          4228: 
        !          4229:             if (++i == r->upstream_states->nelts) {
        !          4230:                 break;
        !          4231:             }
        !          4232: 
        !          4233:             continue;
        !          4234:         }
        !          4235:     }
        !          4236: 
        !          4237:     v->len = p - v->data;
        !          4238: 
        !          4239:     return NGX_OK;
        !          4240: }
        !          4241: 
        !          4242: 
        !          4243: static ngx_int_t
        !          4244: ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
        !          4245:     ngx_http_variable_value_t *v, uintptr_t data)
        !          4246: {
        !          4247:     u_char                     *p;
        !          4248:     size_t                      len;
        !          4249:     ngx_uint_t                  i;
        !          4250:     ngx_msec_int_t              ms;
        !          4251:     ngx_http_upstream_state_t  *state;
        !          4252: 
        !          4253:     v->valid = 1;
        !          4254:     v->no_cacheable = 0;
        !          4255:     v->not_found = 0;
        !          4256: 
        !          4257:     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
        !          4258:         v->not_found = 1;
        !          4259:         return NGX_OK;
        !          4260:     }
        !          4261: 
        !          4262:     len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2);
        !          4263: 
        !          4264:     p = ngx_pnalloc(r->pool, len);
        !          4265:     if (p == NULL) {
        !          4266:         return NGX_ERROR;
        !          4267:     }
        !          4268: 
        !          4269:     v->data = p;
        !          4270: 
        !          4271:     i = 0;
        !          4272:     state = r->upstream_states->elts;
        !          4273: 
        !          4274:     for ( ;; ) {
        !          4275:         if (state[i].status) {
        !          4276:             ms = (ngx_msec_int_t)
        !          4277:                      (state[i].response_sec * 1000 + state[i].response_msec);
        !          4278:             ms = ngx_max(ms, 0);
        !          4279:             p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
        !          4280: 
        !          4281:         } else {
        !          4282:             *p++ = '-';
        !          4283:         }
        !          4284: 
        !          4285:         if (++i == r->upstream_states->nelts) {
        !          4286:             break;
        !          4287:         }
        !          4288: 
        !          4289:         if (state[i].peer) {
        !          4290:             *p++ = ',';
        !          4291:             *p++ = ' ';
        !          4292: 
        !          4293:         } else {
        !          4294:             *p++ = ' ';
        !          4295:             *p++ = ':';
        !          4296:             *p++ = ' ';
        !          4297: 
        !          4298:             if (++i == r->upstream_states->nelts) {
        !          4299:                 break;
        !          4300:             }
        !          4301: 
        !          4302:             continue;
        !          4303:         }
        !          4304:     }
        !          4305: 
        !          4306:     v->len = p - v->data;
        !          4307: 
        !          4308:     return NGX_OK;
        !          4309: }
        !          4310: 
        !          4311: 
        !          4312: static ngx_int_t
        !          4313: ngx_http_upstream_response_length_variable(ngx_http_request_t *r,
        !          4314:     ngx_http_variable_value_t *v, uintptr_t data)
        !          4315: {
        !          4316:     u_char                     *p;
        !          4317:     size_t                      len;
        !          4318:     ngx_uint_t                  i;
        !          4319:     ngx_http_upstream_state_t  *state;
        !          4320: 
        !          4321:     v->valid = 1;
        !          4322:     v->no_cacheable = 0;
        !          4323:     v->not_found = 0;
        !          4324: 
        !          4325:     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
        !          4326:         v->not_found = 1;
        !          4327:         return NGX_OK;
        !          4328:     }
        !          4329: 
        !          4330:     len = r->upstream_states->nelts * (NGX_OFF_T_LEN + 2);
        !          4331: 
        !          4332:     p = ngx_pnalloc(r->pool, len);
        !          4333:     if (p == NULL) {
        !          4334:         return NGX_ERROR;
        !          4335:     }
        !          4336: 
        !          4337:     v->data = p;
        !          4338: 
        !          4339:     i = 0;
        !          4340:     state = r->upstream_states->elts;
        !          4341: 
        !          4342:     for ( ;; ) {
        !          4343:         p = ngx_sprintf(p, "%O", state[i].response_length);
        !          4344: 
        !          4345:         if (++i == r->upstream_states->nelts) {
        !          4346:             break;
        !          4347:         }
        !          4348: 
        !          4349:         if (state[i].peer) {
        !          4350:             *p++ = ',';
        !          4351:             *p++ = ' ';
        !          4352: 
        !          4353:         } else {
        !          4354:             *p++ = ' ';
        !          4355:             *p++ = ':';
        !          4356:             *p++ = ' ';
        !          4357: 
        !          4358:             if (++i == r->upstream_states->nelts) {
        !          4359:                 break;
        !          4360:             }
        !          4361: 
        !          4362:             continue;
        !          4363:         }
        !          4364:     }
        !          4365: 
        !          4366:     v->len = p - v->data;
        !          4367: 
        !          4368:     return NGX_OK;
        !          4369: }
        !          4370: 
        !          4371: 
        !          4372: ngx_int_t
        !          4373: ngx_http_upstream_header_variable(ngx_http_request_t *r,
        !          4374:     ngx_http_variable_value_t *v, uintptr_t data)
        !          4375: {
        !          4376:     if (r->upstream == NULL) {
        !          4377:         v->not_found = 1;
        !          4378:         return NGX_OK;
        !          4379:     }
        !          4380: 
        !          4381:     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
        !          4382:                                          &r->upstream->headers_in.headers.part,
        !          4383:                                          sizeof("upstream_http_") - 1);
        !          4384: }
        !          4385: 
        !          4386: 
        !          4387: #if (NGX_HTTP_CACHE)
        !          4388: 
        !          4389: ngx_int_t
        !          4390: ngx_http_upstream_cache_status(ngx_http_request_t *r,
        !          4391:     ngx_http_variable_value_t *v, uintptr_t data)
        !          4392: {
        !          4393:     ngx_uint_t  n;
        !          4394: 
        !          4395:     if (r->upstream == NULL || r->upstream->cache_status == 0) {
        !          4396:         v->not_found = 1;
        !          4397:         return NGX_OK;
        !          4398:     }
        !          4399: 
        !          4400:     n = r->upstream->cache_status - 1;
        !          4401: 
        !          4402:     v->valid = 1;
        !          4403:     v->no_cacheable = 0;
        !          4404:     v->not_found = 0;
        !          4405:     v->len = ngx_http_cache_status[n].len;
        !          4406:     v->data = ngx_http_cache_status[n].data;
        !          4407: 
        !          4408:     return NGX_OK;
        !          4409: }
        !          4410: 
        !          4411: #endif
        !          4412: 
        !          4413: 
        !          4414: static char *
        !          4415: ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
        !          4416: {
        !          4417:     char                          *rv;
        !          4418:     void                          *mconf;
        !          4419:     ngx_str_t                     *value;
        !          4420:     ngx_url_t                      u;
        !          4421:     ngx_uint_t                     m;
        !          4422:     ngx_conf_t                     pcf;
        !          4423:     ngx_http_module_t             *module;
        !          4424:     ngx_http_conf_ctx_t           *ctx, *http_ctx;
        !          4425:     ngx_http_upstream_srv_conf_t  *uscf;
        !          4426: 
        !          4427:     ngx_memzero(&u, sizeof(ngx_url_t));
        !          4428: 
        !          4429:     value = cf->args->elts;
        !          4430:     u.host = value[1];
        !          4431:     u.no_resolve = 1;
        !          4432:     u.no_port = 1;
        !          4433: 
        !          4434:     uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE
        !          4435:                                          |NGX_HTTP_UPSTREAM_WEIGHT
        !          4436:                                          |NGX_HTTP_UPSTREAM_MAX_FAILS
        !          4437:                                          |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
        !          4438:                                          |NGX_HTTP_UPSTREAM_DOWN
        !          4439:                                          |NGX_HTTP_UPSTREAM_BACKUP);
        !          4440:     if (uscf == NULL) {
        !          4441:         return NGX_CONF_ERROR;
        !          4442:     }
        !          4443: 
        !          4444: 
        !          4445:     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
        !          4446:     if (ctx == NULL) {
        !          4447:         return NGX_CONF_ERROR;
        !          4448:     }
        !          4449: 
        !          4450:     http_ctx = cf->ctx;
        !          4451:     ctx->main_conf = http_ctx->main_conf;
        !          4452: 
        !          4453:     /* the upstream{}'s srv_conf */
        !          4454: 
        !          4455:     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
        !          4456:     if (ctx->srv_conf == NULL) {
        !          4457:         return NGX_CONF_ERROR;
        !          4458:     }
        !          4459: 
        !          4460:     ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
        !          4461: 
        !          4462:     uscf->srv_conf = ctx->srv_conf;
        !          4463: 
        !          4464: 
        !          4465:     /* the upstream{}'s loc_conf */
        !          4466: 
        !          4467:     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
        !          4468:     if (ctx->loc_conf == NULL) {
        !          4469:         return NGX_CONF_ERROR;
        !          4470:     }
        !          4471: 
        !          4472:     for (m = 0; ngx_modules[m]; m++) {
        !          4473:         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
        !          4474:             continue;
        !          4475:         }
        !          4476: 
        !          4477:         module = ngx_modules[m]->ctx;
        !          4478: 
        !          4479:         if (module->create_srv_conf) {
        !          4480:             mconf = module->create_srv_conf(cf);
        !          4481:             if (mconf == NULL) {
        !          4482:                 return NGX_CONF_ERROR;
        !          4483:             }
        !          4484: 
        !          4485:             ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf;
        !          4486:         }
        !          4487: 
        !          4488:         if (module->create_loc_conf) {
        !          4489:             mconf = module->create_loc_conf(cf);
        !          4490:             if (mconf == NULL) {
        !          4491:                 return NGX_CONF_ERROR;
        !          4492:             }
        !          4493: 
        !          4494:             ctx->loc_conf[ngx_modules[m]->ctx_index] = mconf;
        !          4495:         }
        !          4496:     }
        !          4497: 
        !          4498: 
        !          4499:     /* parse inside upstream{} */
        !          4500: 
        !          4501:     pcf = *cf;
        !          4502:     cf->ctx = ctx;
        !          4503:     cf->cmd_type = NGX_HTTP_UPS_CONF;
        !          4504: 
        !          4505:     rv = ngx_conf_parse(cf, NULL);
        !          4506: 
        !          4507:     *cf = pcf;
        !          4508: 
        !          4509:     if (rv != NGX_CONF_OK) {
        !          4510:         return rv;
        !          4511:     }
        !          4512: 
        !          4513:     if (uscf->servers == NULL) {
        !          4514:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4515:                            "no servers are inside upstream");
        !          4516:         return NGX_CONF_ERROR;
        !          4517:     }
        !          4518: 
        !          4519:     return rv;
        !          4520: }
        !          4521: 
        !          4522: 
        !          4523: static char *
        !          4524: ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !          4525: {
        !          4526:     ngx_http_upstream_srv_conf_t  *uscf = conf;
        !          4527: 
        !          4528:     time_t                       fail_timeout;
        !          4529:     ngx_str_t                   *value, s;
        !          4530:     ngx_url_t                    u;
        !          4531:     ngx_int_t                    weight, max_fails;
        !          4532:     ngx_uint_t                   i;
        !          4533:     ngx_http_upstream_server_t  *us;
        !          4534: 
        !          4535:     if (uscf->servers == NULL) {
        !          4536:         uscf->servers = ngx_array_create(cf->pool, 4,
        !          4537:                                          sizeof(ngx_http_upstream_server_t));
        !          4538:         if (uscf->servers == NULL) {
        !          4539:             return NGX_CONF_ERROR;
        !          4540:         }
        !          4541:     }
        !          4542: 
        !          4543:     us = ngx_array_push(uscf->servers);
        !          4544:     if (us == NULL) {
        !          4545:         return NGX_CONF_ERROR;
        !          4546:     }
        !          4547: 
        !          4548:     ngx_memzero(us, sizeof(ngx_http_upstream_server_t));
        !          4549: 
        !          4550:     value = cf->args->elts;
        !          4551: 
        !          4552:     ngx_memzero(&u, sizeof(ngx_url_t));
        !          4553: 
        !          4554:     u.url = value[1];
        !          4555:     u.default_port = 80;
        !          4556: 
        !          4557:     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
        !          4558:         if (u.err) {
        !          4559:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4560:                                "%s in upstream \"%V\"", u.err, &u.url);
        !          4561:         }
        !          4562: 
        !          4563:         return NGX_CONF_ERROR;
        !          4564:     }
        !          4565: 
        !          4566:     weight = 1;
        !          4567:     max_fails = 1;
        !          4568:     fail_timeout = 10;
        !          4569: 
        !          4570:     for (i = 2; i < cf->args->nelts; i++) {
        !          4571: 
        !          4572:         if (ngx_strncmp(value[i].data, "weight=", 7) == 0) {
        !          4573: 
        !          4574:             if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) {
        !          4575:                 goto invalid;
        !          4576:             }
        !          4577: 
        !          4578:             weight = ngx_atoi(&value[i].data[7], value[i].len - 7);
        !          4579: 
        !          4580:             if (weight == NGX_ERROR || weight == 0) {
        !          4581:                 goto invalid;
        !          4582:             }
        !          4583: 
        !          4584:             continue;
        !          4585:         }
        !          4586: 
        !          4587:         if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
        !          4588: 
        !          4589:             if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) {
        !          4590:                 goto invalid;
        !          4591:             }
        !          4592: 
        !          4593:             max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
        !          4594: 
        !          4595:             if (max_fails == NGX_ERROR) {
        !          4596:                 goto invalid;
        !          4597:             }
        !          4598: 
        !          4599:             continue;
        !          4600:         }
        !          4601: 
        !          4602:         if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) {
        !          4603: 
        !          4604:             if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) {
        !          4605:                 goto invalid;
        !          4606:             }
        !          4607: 
        !          4608:             s.len = value[i].len - 13;
        !          4609:             s.data = &value[i].data[13];
        !          4610: 
        !          4611:             fail_timeout = ngx_parse_time(&s, 1);
        !          4612: 
        !          4613:             if (fail_timeout == (time_t) NGX_ERROR) {
        !          4614:                 goto invalid;
        !          4615:             }
        !          4616: 
        !          4617:             continue;
        !          4618:         }
        !          4619: 
        !          4620:         if (ngx_strncmp(value[i].data, "backup", 6) == 0) {
        !          4621: 
        !          4622:             if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) {
        !          4623:                 goto invalid;
        !          4624:             }
        !          4625: 
        !          4626:             us->backup = 1;
        !          4627: 
        !          4628:             continue;
        !          4629:         }
        !          4630: 
        !          4631:         if (ngx_strncmp(value[i].data, "down", 4) == 0) {
        !          4632: 
        !          4633:             if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
        !          4634:                 goto invalid;
        !          4635:             }
        !          4636: 
        !          4637:             us->down = 1;
        !          4638: 
        !          4639:             continue;
        !          4640:         }
        !          4641: 
        !          4642:         goto invalid;
        !          4643:     }
        !          4644: 
        !          4645:     us->addrs = u.addrs;
        !          4646:     us->naddrs = u.naddrs;
        !          4647:     us->weight = weight;
        !          4648:     us->max_fails = max_fails;
        !          4649:     us->fail_timeout = fail_timeout;
        !          4650: 
        !          4651:     return NGX_CONF_OK;
        !          4652: 
        !          4653: invalid:
        !          4654: 
        !          4655:     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4656:                        "invalid parameter \"%V\"", &value[i]);
        !          4657: 
        !          4658:     return NGX_CONF_ERROR;
        !          4659: }
        !          4660: 
        !          4661: 
        !          4662: ngx_http_upstream_srv_conf_t *
        !          4663: ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
        !          4664: {
        !          4665:     ngx_uint_t                      i;
        !          4666:     ngx_http_upstream_server_t     *us;
        !          4667:     ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
        !          4668:     ngx_http_upstream_main_conf_t  *umcf;
        !          4669: 
        !          4670:     if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) {
        !          4671: 
        !          4672:         if (ngx_parse_url(cf->pool, u) != NGX_OK) {
        !          4673:             if (u->err) {
        !          4674:                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4675:                                    "%s in upstream \"%V\"", u->err, &u->url);
        !          4676:             }
        !          4677: 
        !          4678:             return NULL;
        !          4679:         }
        !          4680:     }
        !          4681: 
        !          4682:     umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);
        !          4683: 
        !          4684:     uscfp = umcf->upstreams.elts;
        !          4685: 
        !          4686:     for (i = 0; i < umcf->upstreams.nelts; i++) {
        !          4687: 
        !          4688:         if (uscfp[i]->host.len != u->host.len
        !          4689:             || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
        !          4690:                != 0)
        !          4691:         {
        !          4692:             continue;
        !          4693:         }
        !          4694: 
        !          4695:         if ((flags & NGX_HTTP_UPSTREAM_CREATE)
        !          4696:              && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE))
        !          4697:         {
        !          4698:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4699:                                "duplicate upstream \"%V\"", &u->host);
        !          4700:             return NULL;
        !          4701:         }
        !          4702: 
        !          4703:         if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port) {
        !          4704:             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
        !          4705:                                "upstream \"%V\" may not have port %d",
        !          4706:                                &u->host, u->port);
        !          4707:             return NULL;
        !          4708:         }
        !          4709: 
        !          4710:         if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port) {
        !          4711:             ngx_log_error(NGX_LOG_WARN, cf->log, 0,
        !          4712:                           "upstream \"%V\" may not have port %d in %s:%ui",
        !          4713:                           &u->host, uscfp[i]->port,
        !          4714:                           uscfp[i]->file_name, uscfp[i]->line);
        !          4715:             return NULL;
        !          4716:         }
        !          4717: 
        !          4718:         if (uscfp[i]->port && u->port
        !          4719:             && uscfp[i]->port != u->port)
        !          4720:         {
        !          4721:             continue;
        !          4722:         }
        !          4723: 
        !          4724:         if (uscfp[i]->default_port && u->default_port
        !          4725:             && uscfp[i]->default_port != u->default_port)
        !          4726:         {
        !          4727:             continue;
        !          4728:         }
        !          4729: 
        !          4730:         if (flags & NGX_HTTP_UPSTREAM_CREATE) {
        !          4731:             uscfp[i]->flags = flags;
        !          4732:         }
        !          4733: 
        !          4734:         return uscfp[i];
        !          4735:     }
        !          4736: 
        !          4737:     uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
        !          4738:     if (uscf == NULL) {
        !          4739:         return NULL;
        !          4740:     }
        !          4741: 
        !          4742:     uscf->flags = flags;
        !          4743:     uscf->host = u->host;
        !          4744:     uscf->file_name = cf->conf_file->file.name.data;
        !          4745:     uscf->line = cf->conf_file->line;
        !          4746:     uscf->port = u->port;
        !          4747:     uscf->default_port = u->default_port;
        !          4748:     uscf->no_port = u->no_port;
        !          4749: 
        !          4750:     if (u->naddrs == 1) {
        !          4751:         uscf->servers = ngx_array_create(cf->pool, 1,
        !          4752:                                          sizeof(ngx_http_upstream_server_t));
        !          4753:         if (uscf->servers == NULL) {
        !          4754:             return NULL;
        !          4755:         }
        !          4756: 
        !          4757:         us = ngx_array_push(uscf->servers);
        !          4758:         if (us == NULL) {
        !          4759:             return NULL;
        !          4760:         }
        !          4761: 
        !          4762:         ngx_memzero(us, sizeof(ngx_http_upstream_server_t));
        !          4763: 
        !          4764:         us->addrs = u->addrs;
        !          4765:         us->naddrs = 1;
        !          4766:     }
        !          4767: 
        !          4768:     uscfp = ngx_array_push(&umcf->upstreams);
        !          4769:     if (uscfp == NULL) {
        !          4770:         return NULL;
        !          4771:     }
        !          4772: 
        !          4773:     *uscfp = uscf;
        !          4774: 
        !          4775:     return uscf;
        !          4776: }
        !          4777: 
        !          4778: 
        !          4779: char *
        !          4780: ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
        !          4781:     void *conf)
        !          4782: {
        !          4783:     char  *p = conf;
        !          4784: 
        !          4785:     ngx_int_t                           rc;
        !          4786:     ngx_str_t                          *value;
        !          4787:     ngx_http_complex_value_t            cv;
        !          4788:     ngx_http_upstream_local_t         **plocal, *local;
        !          4789:     ngx_http_compile_complex_value_t    ccv;
        !          4790: 
        !          4791:     plocal = (ngx_http_upstream_local_t **) (p + cmd->offset);
        !          4792: 
        !          4793:     if (*plocal != NGX_CONF_UNSET_PTR) {
        !          4794:         return "is duplicate";
        !          4795:     }
        !          4796: 
        !          4797:     value = cf->args->elts;
        !          4798: 
        !          4799:     if (ngx_strcmp(value[1].data, "off") == 0) {
        !          4800:         *plocal = NULL;
        !          4801:         return NGX_CONF_OK;
        !          4802:     }
        !          4803: 
        !          4804:     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
        !          4805: 
        !          4806:     ccv.cf = cf;
        !          4807:     ccv.value = &value[1];
        !          4808:     ccv.complex_value = &cv;
        !          4809: 
        !          4810:     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
        !          4811:         return NGX_CONF_ERROR;
        !          4812:     }
        !          4813: 
        !          4814:     local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t));
        !          4815:     if (local == NULL) {
        !          4816:         return NGX_CONF_ERROR;
        !          4817:     }
        !          4818: 
        !          4819:     *plocal = local;
        !          4820: 
        !          4821:     if (cv.lengths) {
        !          4822:         local->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
        !          4823:         if (local->value == NULL) {
        !          4824:             return NGX_CONF_ERROR;
        !          4825:         }
        !          4826: 
        !          4827:         *local->value = cv;
        !          4828: 
        !          4829:         return NGX_CONF_OK;
        !          4830:     }
        !          4831: 
        !          4832:     local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
        !          4833:     if (local->addr == NULL) {
        !          4834:         return NGX_CONF_ERROR;
        !          4835:     }
        !          4836: 
        !          4837:     rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len);
        !          4838: 
        !          4839:     switch (rc) {
        !          4840:     case NGX_OK:
        !          4841:         local->addr->name = value[1];
        !          4842:         return NGX_CONF_OK;
        !          4843: 
        !          4844:     case NGX_DECLINED:
        !          4845:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4846:                            "invalid address \"%V\"", &value[1]);
        !          4847:         /* fall through */
        !          4848: 
        !          4849:     default:
        !          4850:         return NGX_CONF_ERROR;
        !          4851:     }
        !          4852: }
        !          4853: 
        !          4854: 
        !          4855: static ngx_addr_t *
        !          4856: ngx_http_upstream_get_local(ngx_http_request_t *r,
        !          4857:     ngx_http_upstream_local_t *local)
        !          4858: {
        !          4859:     ngx_int_t    rc;
        !          4860:     ngx_str_t    val;
        !          4861:     ngx_addr_t  *addr;
        !          4862: 
        !          4863:     if (local == NULL) {
        !          4864:         return NULL;
        !          4865:     }
        !          4866: 
        !          4867:     if (local->value == NULL) {
        !          4868:         return local->addr;
        !          4869:     }
        !          4870: 
        !          4871:     if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {
        !          4872:         return NULL;
        !          4873:     }
        !          4874: 
        !          4875:     if (val.len == 0) {
        !          4876:         return NULL;
        !          4877:     }
        !          4878: 
        !          4879:     addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
        !          4880:     if (addr == NULL) {
        !          4881:         return NULL;
        !          4882:     }
        !          4883: 
        !          4884:     rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
        !          4885: 
        !          4886:     switch (rc) {
        !          4887:     case NGX_OK:
        !          4888:         addr->name = val;
        !          4889:         return addr;
        !          4890: 
        !          4891:     case NGX_DECLINED:
        !          4892:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !          4893:                       "invalid local address \"%V\"", &val);
        !          4894:         /* fall through */
        !          4895: 
        !          4896:     default:
        !          4897:         return NULL;
        !          4898:     }
        !          4899: }
        !          4900: 
        !          4901: 
        !          4902: char *
        !          4903: ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
        !          4904:     void *conf)
        !          4905: {
        !          4906:     char  *p = conf;
        !          4907: 
        !          4908:     ngx_str_t                   *value;
        !          4909:     ngx_array_t                **a;
        !          4910:     ngx_http_upstream_param_t   *param;
        !          4911: 
        !          4912:     a = (ngx_array_t **) (p + cmd->offset);
        !          4913: 
        !          4914:     if (*a == NULL) {
        !          4915:         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
        !          4916:         if (*a == NULL) {
        !          4917:             return NGX_CONF_ERROR;
        !          4918:         }
        !          4919:     }
        !          4920: 
        !          4921:     param = ngx_array_push(*a);
        !          4922:     if (param == NULL) {
        !          4923:         return NGX_CONF_ERROR;
        !          4924:     }
        !          4925: 
        !          4926:     value = cf->args->elts;
        !          4927: 
        !          4928:     param->key = value[1];
        !          4929:     param->value = value[2];
        !          4930:     param->skip_empty = 0;
        !          4931: 
        !          4932:     if (cf->args->nelts == 4) {
        !          4933:         if (ngx_strcmp(value[3].data, "if_not_empty") != 0) {
        !          4934:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          4935:                                "invalid parameter \"%V\"", &value[3]);
        !          4936:             return NGX_CONF_ERROR;
        !          4937:         }
        !          4938: 
        !          4939:         param->skip_empty = 1;
        !          4940:     }
        !          4941: 
        !          4942:     return NGX_CONF_OK;
        !          4943: }
        !          4944: 
        !          4945: 
        !          4946: ngx_int_t
        !          4947: ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
        !          4948:     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
        !          4949:     ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
        !          4950: {
        !          4951:     ngx_str_t       *h;
        !          4952:     ngx_uint_t       i, j;
        !          4953:     ngx_array_t      hide_headers;
        !          4954:     ngx_hash_key_t  *hk;
        !          4955: 
        !          4956:     if (conf->hide_headers == NGX_CONF_UNSET_PTR
        !          4957:         && conf->pass_headers == NGX_CONF_UNSET_PTR)
        !          4958:     {
        !          4959:         conf->hide_headers = prev->hide_headers;
        !          4960:         conf->pass_headers = prev->pass_headers;
        !          4961: 
        !          4962:         conf->hide_headers_hash = prev->hide_headers_hash;
        !          4963: 
        !          4964:         if (conf->hide_headers_hash.buckets
        !          4965: #if (NGX_HTTP_CACHE)
        !          4966:             && ((conf->cache == NULL) == (prev->cache == NULL))
        !          4967: #endif
        !          4968:            )
        !          4969:         {
        !          4970:             return NGX_OK;
        !          4971:         }
        !          4972: 
        !          4973:     } else {
        !          4974:         if (conf->hide_headers == NGX_CONF_UNSET_PTR) {
        !          4975:             conf->hide_headers = prev->hide_headers;
        !          4976:         }
        !          4977: 
        !          4978:         if (conf->pass_headers == NGX_CONF_UNSET_PTR) {
        !          4979:             conf->pass_headers = prev->pass_headers;
        !          4980:         }
        !          4981:     }
        !          4982: 
        !          4983:     if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
        !          4984:         != NGX_OK)
        !          4985:     {
        !          4986:         return NGX_ERROR;
        !          4987:     }
        !          4988: 
        !          4989:     for (h = default_hide_headers; h->len; h++) {
        !          4990:         hk = ngx_array_push(&hide_headers);
        !          4991:         if (hk == NULL) {
        !          4992:             return NGX_ERROR;
        !          4993:         }
        !          4994: 
        !          4995:         hk->key = *h;
        !          4996:         hk->key_hash = ngx_hash_key_lc(h->data, h->len);
        !          4997:         hk->value = (void *) 1;
        !          4998:     }
        !          4999: 
        !          5000:     if (conf->hide_headers != NGX_CONF_UNSET_PTR) {
        !          5001: 
        !          5002:         h = conf->hide_headers->elts;
        !          5003: 
        !          5004:         for (i = 0; i < conf->hide_headers->nelts; i++) {
        !          5005: 
        !          5006:             hk = hide_headers.elts;
        !          5007: 
        !          5008:             for (j = 0; j < hide_headers.nelts; j++) {
        !          5009:                 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
        !          5010:                     goto exist;
        !          5011:                 }
        !          5012:             }
        !          5013: 
        !          5014:             hk = ngx_array_push(&hide_headers);
        !          5015:             if (hk == NULL) {
        !          5016:                 return NGX_ERROR;
        !          5017:             }
        !          5018: 
        !          5019:             hk->key = h[i];
        !          5020:             hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
        !          5021:             hk->value = (void *) 1;
        !          5022: 
        !          5023:         exist:
        !          5024: 
        !          5025:             continue;
        !          5026:         }
        !          5027:     }
        !          5028: 
        !          5029:     if (conf->pass_headers != NGX_CONF_UNSET_PTR) {
        !          5030: 
        !          5031:         h = conf->pass_headers->elts;
        !          5032:         hk = hide_headers.elts;
        !          5033: 
        !          5034:         for (i = 0; i < conf->pass_headers->nelts; i++) {
        !          5035:             for (j = 0; j < hide_headers.nelts; j++) {
        !          5036: 
        !          5037:                 if (hk[j].key.data == NULL) {
        !          5038:                     continue;
        !          5039:                 }
        !          5040: 
        !          5041:                 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
        !          5042:                     hk[j].key.data = NULL;
        !          5043:                     break;
        !          5044:                 }
        !          5045:             }
        !          5046:         }
        !          5047:     }
        !          5048: 
        !          5049:     hash->hash = &conf->hide_headers_hash;
        !          5050:     hash->key = ngx_hash_key_lc;
        !          5051:     hash->pool = cf->pool;
        !          5052:     hash->temp_pool = NULL;
        !          5053: 
        !          5054:     return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts);
        !          5055: }
        !          5056: 
        !          5057: 
        !          5058: static void *
        !          5059: ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
        !          5060: {
        !          5061:     ngx_http_upstream_main_conf_t  *umcf;
        !          5062: 
        !          5063:     umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t));
        !          5064:     if (umcf == NULL) {
        !          5065:         return NULL;
        !          5066:     }
        !          5067: 
        !          5068:     if (ngx_array_init(&umcf->upstreams, cf->pool, 4,
        !          5069:                        sizeof(ngx_http_upstream_srv_conf_t *))
        !          5070:         != NGX_OK)
        !          5071:     {
        !          5072:         return NULL;
        !          5073:     }
        !          5074: 
        !          5075:     return umcf;
        !          5076: }
        !          5077: 
        !          5078: 
        !          5079: static char *
        !          5080: ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
        !          5081: {
        !          5082:     ngx_http_upstream_main_conf_t  *umcf = conf;
        !          5083: 
        !          5084:     ngx_uint_t                      i;
        !          5085:     ngx_array_t                     headers_in;
        !          5086:     ngx_hash_key_t                 *hk;
        !          5087:     ngx_hash_init_t                 hash;
        !          5088:     ngx_http_upstream_init_pt       init;
        !          5089:     ngx_http_upstream_header_t     *header;
        !          5090:     ngx_http_upstream_srv_conf_t  **uscfp;
        !          5091: 
        !          5092:     uscfp = umcf->upstreams.elts;
        !          5093: 
        !          5094:     for (i = 0; i < umcf->upstreams.nelts; i++) {
        !          5095: 
        !          5096:         init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
        !          5097:                                             ngx_http_upstream_init_round_robin;
        !          5098: 
        !          5099:         if (init(cf, uscfp[i]) != NGX_OK) {
        !          5100:             return NGX_CONF_ERROR;
        !          5101:         }
        !          5102:     }
        !          5103: 
        !          5104: 
        !          5105:     /* upstream_headers_in_hash */
        !          5106: 
        !          5107:     if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
        !          5108:         != NGX_OK)
        !          5109:     {
        !          5110:         return NGX_CONF_ERROR;
        !          5111:     }
        !          5112: 
        !          5113:     for (header = ngx_http_upstream_headers_in; header->name.len; header++) {
        !          5114:         hk = ngx_array_push(&headers_in);
        !          5115:         if (hk == NULL) {
        !          5116:             return NGX_CONF_ERROR;
        !          5117:         }
        !          5118: 
        !          5119:         hk->key = header->name;
        !          5120:         hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
        !          5121:         hk->value = header;
        !          5122:     }
        !          5123: 
        !          5124:     hash.hash = &umcf->headers_in_hash;
        !          5125:     hash.key = ngx_hash_key_lc;
        !          5126:     hash.max_size = 512;
        !          5127:     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
        !          5128:     hash.name = "upstream_headers_in_hash";
        !          5129:     hash.pool = cf->pool;
        !          5130:     hash.temp_pool = NULL;
        !          5131: 
        !          5132:     if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
        !          5133:         return NGX_CONF_ERROR;
        !          5134:     }
        !          5135: 
        !          5136:     return NGX_CONF_OK;
        !          5137: }

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