diff options
author | corvid <devnull@localhost> | 2014-07-17 03:24:01 +0000 |
---|---|---|
committer | corvid <devnull@localhost> | 2014-07-17 03:24:01 +0000 |
commit | e75e4a0217096ebd7f425278403ab687911b0bb6 (patch) | |
tree | db0a7f268471e8388e982a8fc363221b73802fa8 /src/IO/http.c | |
parent | f626a943944d0184491bab2c75a09788986b0d04 (diff) |
http persistent connections initial patch
Diffstat (limited to 'src/IO/http.c')
-rw-r--r-- | src/IO/http.c | 115 |
1 files changed, 100 insertions, 15 deletions
diff --git a/src/IO/http.c b/src/IO/http.c index 23101ba7..917cb95e 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -79,7 +79,8 @@ typedef struct { typedef struct { char *host; - int active_connections; + Dlist *active_fds; + int avail_fd; SocketQueue_t main_q, image_q; /* imgs have separate lower-priority queue */ } HostConnection_t; @@ -89,6 +90,7 @@ static SocketData_t* Http_socket_dequeue(HostConnection_t *hc); static HostConnection_t *Http_host_connection_get(const char *host); static void Http_host_connection_remove(HostConnection_t *hc); static int Http_connect_socket(ChainLink *Info); +static void Http_send_query(ChainLink *Info, SocketData_t *S); static void Http_socket_free(int SKey); /* @@ -160,8 +162,9 @@ static int Http_sock_new(void) static void Http_connect_queued_sockets(HostConnection_t *hc) { + bool_t all_is_well = TRUE; SocketData_t *sd; - while (hc->active_connections < prefs.http_max_conns && + while (dList_length(hc->active_fds) < prefs.http_max_conns && (sd = Http_socket_dequeue(hc))) { sd->flags &= ~HTTP_SOCKET_QUEUED; @@ -170,18 +173,30 @@ static void Http_connect_queued_sockets(HostConnection_t *hc) dFree(sd); } else if (a_Web_valid(sd->web)) { /* start connecting the socket */ - if (Http_connect_socket(sd->Info) < 0) { + if (hc->avail_fd != -1) { + sd->SockFD = hc->avail_fd; + hc->avail_fd = -1; + } else if (Http_connect_socket(sd->Info) < 0) { ChainLink *Info = sd->Info; + all_is_well = FALSE; MSG_BW(sd->web, 1, "ERROR: %s", dStrerror(sd->Err)); a_Chain_bfcb(OpAbort, Info, NULL, "Both"); Http_socket_free(VOIDP2INT(Info->LocalKey)); /* free sd */ dFree(Info); - } else { + } + if (all_is_well) { + a_Chain_bcb(OpSend, sd->Info, &sd->SockFD, "FD"); + a_Chain_fcb(OpSend, sd->Info, &sd->SockFD, "FD"); + Http_send_query(sd->Info, sd); sd->connected_to = hc->host; - hc->active_connections++; + dList_append(hc->active_fds, (void *)sd->SockFD); } } } + if (hc->avail_fd != -1) { + dClose(hc->avail_fd); + hc->avail_fd = -1; + } } /* @@ -199,9 +214,9 @@ static void Http_socket_free(int SKey) } else { if (S->connected_to) { HostConnection_t *hc = Http_host_connection_get(S->connected_to); - hc->active_connections--; + dList_remove_fast(hc->active_fds, (void *)S->SockFD); Http_connect_queued_sockets(hc); - if (hc->active_connections == 0) + if (dList_length(hc->active_fds) == 0) Http_host_connection_remove(hc); } dFree(S); @@ -275,6 +290,9 @@ Dstr *a_Http_make_query_str(const DilloUrl *url, const DilloUrl *requester, web_flags & WEB_Stylesheet ? "text/css,*/*;q=0.1" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; + const char *connection_hdr_val = + dStrAsciiCasecmp(URL_SCHEME(url), "http") == 0 ? "keep-alive" : "close"; + if (use_proxy) { dStr_sprintfa(request_uri, "%s%s", URL_STR(url), @@ -309,15 +327,15 @@ Dstr *a_Http_make_query_str(const DilloUrl *url, const DilloUrl *requester, "DNT: 1\r\n" "%s" /* proxy auth */ "%s" /* referer */ - "Connection: close\r\n" + "Connection: %s\r\n" "Content-Type: %s\r\n" "Content-Length: %ld\r\n" "%s" /* cookies */ "\r\n", request_uri->str, URL_AUTHORITY(url), prefs.http_user_agent, accept_hdr_value, HTTP_Language_hdr, auth ? auth : "", - proxy_auth->str, referer, content_type->str, (long)URL_DATA(url)->len, - cookies); + proxy_auth->str, referer, connection_hdr_val, content_type->str, + (long)URL_DATA(url)->len, cookies); dStr_append_l(query, URL_DATA(url)->str, URL_DATA(url)->len); dStr_free(content_type, TRUE); } else { @@ -333,13 +351,13 @@ Dstr *a_Http_make_query_str(const DilloUrl *url, const DilloUrl *requester, "DNT: 1\r\n" "%s" /* proxy auth */ "%s" /* referer */ - "Connection: close\r\n" + "Connection: %s\r\n" "%s" /* cache control */ "%s" /* cookies */ "\r\n", request_uri->str, URL_AUTHORITY(url), prefs.http_user_agent, accept_hdr_value, HTTP_Language_hdr, auth ? auth : "", - proxy_auth->str, referer, + proxy_auth->str, referer, connection_hdr_val, (URL_FLAGS(url) & URL_E2EQuery) ? "Pragma: no-cache\r\nCache-Control: no-cache\r\n" : "", cookies); @@ -447,9 +465,6 @@ static int Http_connect_socket(ChainLink *Info) dClose(S->SockFD); MSG("Http_connect_socket ERROR: %s\n", dStrerror(S->Err)); } else { - a_Chain_bcb(OpSend, Info, &S->SockFD, "FD"); - a_Chain_fcb(OpSend, Info, &S->SockFD, "FD"); - Http_send_query(S->Info, S); return 0; /* Success */ } } @@ -618,6 +633,28 @@ static int Http_get(ChainLink *Info, void *Data1) return 0; } +static void Http_make_fd_available(int fd) +{ + int i, j; + + for (i = 0; i < dList_length(host_connections); i++) { + HostConnection_t *hc = + (HostConnection_t*) dList_nth_data(host_connections, i); + + for (j = 0; j < dList_length(hc->active_fds); j++) { + void *data = dList_nth_data(hc->active_fds, j); + + if (fd == VOIDP2INT(data)) { + _MSG("host %s ", hc->host); + _MSG("Shift fd %d from active to avail\n", fd); + dList_remove_fast (hc->active_fds, data); + hc->avail_fd = fd; + return; + } + } + } +} + /* * CCC function for the HTTP module */ @@ -665,6 +702,51 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, break; } } + } else if (Branch == 2) { + if (Dir == FWD) { + /* Receiving from server */ + switch (Op) { + case OpSend: + /* Data1 = dbuf */ + a_Chain_fcb(OpSend, Info, Data1, "send_page_2eof"); + break; + case OpEnd: + a_Chain_fcb(OpEnd, Info, NULL, NULL); + dFree(Info); + break; + default: + MSG_WARN("Unused CCC\n"); + break; + } + } else { /* 2 BCK */ + switch (Op) { + case OpStart: + a_Chain_link_new(Info, a_Http_ccc, BCK, a_IO_ccc, 2, 2); + a_Chain_bcb(OpStart, Info, NULL, NULL); /* IORead */ + break; + case OpSend: + if (Data2) { + if (!strcmp(Data2, "FD")) { + Info->LocalKey = (void *)*(int*)Data1; + a_Chain_bcb(OpSend, Info, Data1, Data2); + } else if (!strcmp(Data2, "reply_complete")) { + int fd = VOIDP2INT(Info->LocalKey); + + Http_make_fd_available(fd); + a_Chain_bfcb(OpEnd, Info, NULL, NULL); + dFree(Info); + } + } + break; + case OpAbort: + a_Chain_bcb(OpAbort, Info, NULL, NULL); + dFree(Info); + break; + default: + MSG_WARN("Unused CCC\n"); + break; + } + } } } @@ -726,6 +808,8 @@ static HostConnection_t *Http_host_connection_get(const char *host) Http_socket_queue_init(&hc->main_q); Http_socket_queue_init(&hc->image_q); hc->host = dStrdup(host); + hc->active_fds = dList_new(prefs.http_max_conns); + hc->avail_fd = -1; dList_append(host_connections, hc); return hc; @@ -736,6 +820,7 @@ static void Http_host_connection_remove(HostConnection_t *hc) assert(hc->main_q.head == NULL && hc->image_q.head == NULL); dList_remove_fast(host_connections, hc); dFree(hc->host); + dList_free(hc->active_fds); dFree(hc); } |