changeset 169:edf29bb717da

nginx-0.0.1-2003-10-31-19:05:33 import
author Igor Sysoev <igor@sysoev.ru>
date Fri, 31 Oct 2003 16:05:33 +0000
parents ba5dbb949603
children c42be4185301
files src/event/ngx_event_connect.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/ngx_http_headers.c src/http/ngx_http_request.c
diffstat 5 files changed, 129 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -223,7 +223,7 @@ ngx_log_debug(pc->log, "CONNECT: %s" _ p
          * aio allows to post operation on non-connected socket
          * at least in FreeBSD
          * 
-         * TODO: check in Win32, etc.
+         * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
          */
  
         rev->ready = 1;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -22,6 +22,7 @@ static void ngx_http_proxy_process_body(
 
 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type);
+static int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status);
 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
 static void ngx_http_proxy_close_connection(ngx_connection_t *c);
 
@@ -189,9 +190,9 @@ static ngx_http_header_t headers_in[] = 
 };
 
 
-static char http_version[] = " HTTP/1.0" CRLF;
-static char host_header[] = "Host: ";
-static char connection_close_header[] = "Connection: close" CRLF;
+static char  http_version[] = " HTTP/1.0" CRLF;
+static char  host_header[] = "Host: ";
+static char  connection_close_header[] = "Connection: close" CRLF;
 
 
 
@@ -207,6 +208,10 @@ static int ngx_http_proxy_handler(ngx_ht
     p->upstream.peers = p->lcf->peers;
     p->upstream.tries = p->lcf->peers->number;
 
+    ngx_init_array(p->states, r->pool, p->upstream.tries,
+                   sizeof(ngx_http_proxy_state_t),
+                   NGX_HTTP_INTERNAL_SERVER_ERROR);
+
     p->request = r;
     p->method = r->method;
 
@@ -471,21 +476,13 @@ static int ngx_http_proxy_connect(ngx_ht
         if (rc == NGX_CONNECT_ERROR) {
             ngx_event_connect_peer_failed(&p->upstream);
 
-#if 0
-            /* TODO: make separate func and call it from next_upstream */
-
-            if (!(state = ngx_push_array(p->states))) {
+            if (ngx_http_proxy_log_state(p, NGX_HTTP_BAD_GATEWAY) == NGX_ERROR)
+            {
                 ngx_http_proxy_finalize_request(p,
                                                 NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return NGX_DONE;
             }
 
-            state->status = NGX_HTTP_BAD_GATEWAY;
-            state->peer =
-                 p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text;
-
-#endif
-
             if (p->upstream.tries == 0) {
                 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
                 return NGX_DONE;
@@ -517,7 +514,7 @@ static int ngx_http_proxy_connect(ngx_ht
         p->timedout = 0;
 
         if (rc == NGX_OK) {
-            return ngx_http_proxy_send_request(p);
+            return ngx_http_proxy_send_request0(p);
         }
 
         /* rc == NGX_AGAIN */
@@ -528,6 +525,78 @@ static int ngx_http_proxy_connect(ngx_ht
     }
 }
 
+
+static int ngx_http_proxy_send_request0(ngx_http_proxy_ctx_t *p)
+{
+    ngx_connection_t        *c;
+    ngx_chain_writer_ctx_t  *wctx;
+
+    c = p->upstream.connection;
+
+    p->action = "sending request to upstream";
+    wctx = p->output_chain_ctx->output_ctx;
+    wctx->connection = c;
+    rc = ngx_output_chain(p->output_chain_ctx,
+                          !p->request_sent ? p->request->request_hunks:
+                                             NULL);
+    if (rc == NGX_ERROR) {
+        return ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
+    }
+
+    p->request_sent = 1;
+
+    if (c->write->timer_set) {
+        ngx_del_timer(c->write);
+    }
+
+    if (rc == NGX_AGAIN) {
+        ngx_add_timer(c->write, p->lcf->send_timeout);
+
+        if (ngx_handle_write_event(c->write, /* STUB: lowat */ 0) == NGX_ERROR)
+        {
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        return NGX_AGAIN;
+    }
+
+    /* rc == NGX_OK */
+
+    if (c->read->ready) {
+        /* post aio operation */
+        ngx_http_proxy_process_upstream_status_line(c->read);
+    }
+
+            if (ngx_handle_level_write_event(c->write) == NGX_ERROR) {
+                ngx_http_proxy_finalize_request(p,
+                                       NGX_HTTP_INTERNAL_SERVER_ERROR);
+                return;
+            }
+
+            if (c->tcp_nopush) {
+                if (ngx_tcp_push(c->fd) == NGX_ERROR) {
+                    ngx_log_error(NGX_LOG_CRIT, c->log,
+                                  ngx_socket_errno,
+                                  ngx_tcp_push_n " failed");
+                    ngx_http_proxy_finalize_request(p,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
+                    return; 
+                }
+
+                c->tcp_nopush = 0;
+            }
+        }
+
+        return;
+    }
+
+    ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
+
+    return NGX_OK;
+}
+
+
 #endif
 
 
@@ -1391,6 +1460,8 @@ static int ngx_http_proxy_parse_status_l
 
 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type)
 {
+    int  status;
+
     ngx_event_connect_peer_failed(&p->upstream);
 
     if (p->timedout) {
@@ -1403,10 +1474,20 @@ static void ngx_http_proxy_next_upstream
         p->upstream.connection = NULL;
     }
 
+    if (ft_type == NGX_HTTP_PROXY_FT_TIMEOUT) {
+        status = NGX_HTTP_GATEWAY_TIME_OUT;
+
+    } else {
+        status = NGX_HTTP_BAD_GATEWAY;
+    }
+
+    if (ngx_http_proxy_log_state(p, status) == NGX_ERROR) {
+        ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return;
+    }
+
     if (p->upstream.tries == 0 || !(p->lcf->next_upstream & ft_type)) {
-        ngx_http_proxy_finalize_request(p,
-                                        p->timedout ? NGX_HTTP_GATEWAY_TIME_OUT:
-                                                      NGX_HTTP_BAD_GATEWAY);
+        ngx_http_proxy_finalize_request(p, status);
         return;
     }
 
@@ -1420,6 +1501,23 @@ ngx_log_debug(p->request->connection->lo
     return;
 }
 
+
+static int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status)
+{
+    ngx_http_proxy_state_t  *state;
+
+    if (!(state = ngx_push_array(&p->states))) {
+        return NGX_ERROR;
+    }
+
+    state->status = status;
+    state->peer =
+                &p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text;
+
+    return NGX_OK;
+}
+
+
 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
 {
     ngx_log_debug(p->request->connection->log,
@@ -1447,7 +1545,6 @@ static void ngx_http_proxy_finalize_requ
 }
 
 
-
 static void ngx_http_proxy_close_connection(ngx_connection_t *c)
 {
     ngx_log_debug(c->log, "close connection: %d" _ c->fd);
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -44,6 +44,12 @@ typedef struct {
 
 
 typedef struct {
+    int         status;
+    ngx_str_t  *peer;
+} ngx_http_proxy_state_t;
+
+
+typedef struct {
     ngx_table_t      *headers;   /* it must be first field */
 
     ngx_table_elt_t  *date;
@@ -91,6 +97,8 @@ struct ngx_http_proxy_ctx_s {
     int                         status_count;
     int                         state;
 
+    ngx_array_t                 states;    /* of ngx_http_proxy_state_t */
+
     char                       *action;
     ngx_http_log_ctx_t         *saved_ctx;
     ngx_log_handler_pt          saved_handler;
--- a/src/http/ngx_http_headers.c
+++ b/src/http/ngx_http_headers.c
@@ -48,7 +48,7 @@ ngx_http_header_t  ngx_http_headers_out[
 ngx_table_elt_t *ngx_http_add_header(void *header,
                                      ngx_http_header_t *http_headers)
 {
-    int               i, j, nelts;
+    int               i, j;
     char             *prev;
     ngx_table_t      *headers;
     ngx_table_elt_t  *h, *new;
@@ -56,7 +56,6 @@ ngx_table_elt_t *ngx_http_add_header(voi
     headers = *(ngx_table_t **) header;
 
     prev = headers->elts;
-    nelts = headers->nelts;
 
     if (!(new = ngx_push_table(headers))) {
         return NULL;
@@ -74,10 +73,10 @@ ngx_table_elt_t *ngx_http_add_header(voi
      */
 
     ngx_log_error(NGX_LOG_ALERT, headers->pool->log, 0,
-                  "header table is small, %d elements", nelts);
+                  "header table is small, %d elements", headers->nelts - 1);
 
     h = headers->elts;
-    for (i = 0; i < nelts; i++) {
+    for (i = 0; i < headers->nelts - 1; i++) {
         if (h[i].key.len == 0) {
             continue;
         }
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -95,6 +95,8 @@ void ngx_http_init_connection(ngx_connec
     }
 
 #if 0
+    /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */
+
     c->write->ready = 0;
     c->write->event_handler = ngx_http_dummy;