diff options
Diffstat (limited to 'src/IO')
-rw-r--r-- | src/IO/IO.c | 13 | ||||
-rw-r--r-- | src/IO/about.c | 70 | ||||
-rw-r--r-- | src/IO/http.c | 270 |
3 files changed, 252 insertions, 101 deletions
diff --git a/src/IO/IO.c b/src/IO/IO.c index a0a8bba5..0addf486 100644 --- a/src/IO/IO.c +++ b/src/IO/IO.c @@ -298,6 +298,8 @@ static void IO_fd_write_cb(int fd, void *data) } else { if (IO_callback(io) == 0) a_IOwatch_remove_fd(fd, DIO_WRITE); + if (io->Status) + a_IO_ccc(OpAbort, 1, FWD, io->Info, NULL, NULL); } } @@ -350,6 +352,7 @@ void a_IO_ccc(int Op, int Branch, int Dir, ChainLink *Info, switch (Op) { case OpStart: io = IO_new(IOWrite); + io->Info = Info; Info->LocalKey = io; break; case OpSend: @@ -384,6 +387,13 @@ void a_IO_ccc(int Op, int Branch, int Dir, ChainLink *Info, } else { /* 1 FWD */ /* Write-data status */ switch (Op) { + case OpAbort: + io = Info->LocalKey; + IO_close_fd(io, IO_StopRdWr); + IO_free(io); + a_Chain_fcb(OpAbort, Info, NULL, NULL); + dFree(Info); + break; default: MSG_WARN("Unused CCC\n"); break; @@ -406,9 +416,10 @@ void a_IO_ccc(int Op, int Branch, int Dir, ChainLink *Info, IO_submit(io); } break; + case OpEnd: case OpAbort: io = Info->LocalKey; - IO_close_fd(io, IO_StopRdWr); + IO_close_fd(io, Op == OpEnd ? IO_StopRd : IO_StopRdWr); IO_free(io); dFree(Info); break; diff --git a/src/IO/about.c b/src/IO/about.c index 5ffe7dff..0cc3b427 100644 --- a/src/IO/about.c +++ b/src/IO/about.c @@ -229,29 +229,32 @@ const char *const AboutSplash= "<table border='0' cellpadding='5' cellspacing='1' width='100%'>\n" "<tr>\n" " <td bgcolor='#CCCCCC'>\n" -" <h4>Release overview</h4>\n" -" December 24, 2014\n" +" <h4>Notes</h4>\n" "<tr>\n" " <td bgcolor='#FFFFFF'>\n" " <table border='0' cellspacing='0' cellpadding='5'>\n" " <tr>\n" " <td>\n" -"<p>\n" -"The dillo-3.0.4.1 release brings you fixes:\n" "<ul>\n" -"<li> for linking with the recently-released fltk-1.3.3\n" -" (we don't use <tt>fl_oldfocus</tt> anymore).\n" -"<li> to make sure that windows are resizable with fltk-1.3.3.\n" -"<li> not to load background images, or follow redirections or meta refresh,\n" -" in <tt>--local</tt> mode (security).\n" -"<li> to permit linking on OS X (remove our <tt>Fl_Printer</tt> stub).\n" -"<li> for a crash when searching from the address bar and no search urls are\n" -" found in dillorc.\n" +" <li> There's a\n" +" <a href='http://www.dillo.org/dillorc'>dillorc</a>\n" +" (readable config) file inside the tarball. It is well-commented\n" +" and has plenty of options to customize dillo, so <STRONG>copy\n" +" it</STRONG> to your <STRONG>~/.dillo/</STRONG> directory, and\n" +" modify it to your taste.\n" +" <li> The right mouse button brings up a context-sensitive menu\n" +" (available on pages, links, images, forms, the Back and Forward buttons,\n" +" and the bug meter).\n" +" <li> Cookies are disabled by default for privacy. To log into certain\n" +" sites, you may need to <a href='http://www.dillo.org/Cookies.txt'>enable\n" +" cookies selectively</a>.\n" +" <li> Frames, Java and Javascript are not supported.\n" +" <li> This release is mainly intended for <strong>developers</strong>\n" +" and <strong>advanced users</strong>.\n" +" <li> Documentation for developers is in the <CODE>/doc</CODE>\n" +" dir inside the tarball; you can find directions on everything\n" +" else at the home page.\n" "</ul>\n" -"<p>\n" -"...that shouldn't have to wait until dillo-3.1 is ready with its floating\n" -"elements and assorted good things.\n" -"<p>\n" " </table>\n" "</table>\n" "</table>\n" @@ -262,32 +265,29 @@ const char *const AboutSplash= "<table border='0' cellpadding='5' cellspacing='1' width='100%'>\n" "<tr>\n" " <td bgcolor='#CCCCCC'>\n" -" <h4>Notes</h4>\n" +" <h4>Release overview</h4>\n" +" December 24, 2014\n" "<tr>\n" " <td bgcolor='#FFFFFF'>\n" " <table border='0' cellspacing='0' cellpadding='5'>\n" " <tr>\n" " <td>\n" +"<p>\n" +"The dillo-3.0.4.1 release brings you fixes:\n" "<ul>\n" -" <li> There's a\n" -" <a href='http://www.dillo.org/dillorc'>dillorc</a>\n" -" (readable config) file inside the tarball. It is well-commented\n" -" and has plenty of options to customize dillo, so <STRONG>copy\n" -" it</STRONG> to your <STRONG>~/.dillo/</STRONG> directory, and\n" -" modify it to your taste.\n" -" <li> Documentation for developers is in the <CODE>/doc</CODE>\n" -" dir inside the tarball; you can find directions on everything\n" -" else at the home page.\n" -" <li> The right mouse button brings up a context-sensitive menu\n" -" (available on pages, links, images, forms, the Back and Forward buttons,\n" -" and the bug meter).\n" -" <li> Dillo behaves very nicely when browsing local files, images, and HTML.\n" -" It's also very good for Internet searching.\n" -" <li> This release is mainly intended for <strong>developers</strong>\n" -" and <strong>advanced users</strong>.\n" -" <li> Frames, Java and Javascript are not supported.\n" +"<li> for linking with the recently-released fltk-1.3.3\n" +" (we don't use <tt>fl_oldfocus</tt> anymore).\n" +"<li> to make sure that windows are resizable with fltk-1.3.3.\n" +"<li> not to load background images, or follow redirections or meta refresh,\n" +" in <tt>--local</tt> mode (security).\n" +"<li> to permit linking on OS X (remove our <tt>Fl_Printer</tt> stub).\n" +"<li> for a crash when searching from the address bar and no search urls are\n" +" found in dillorc.\n" "</ul>\n" -"<br>\n" +"<p>\n" +"...that shouldn't have to wait until dillo-3.1 is ready with its floating\n" +"elements and assorted good things.\n" +"<p>\n" " </table>\n" "</table>\n" "</table>\n" diff --git a/src/IO/http.c b/src/IO/http.c index a0021a9e..49b3a3ac 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -48,6 +48,8 @@ D_STMT_START { \ #define _MSG_BW(web, root, ...) +static const int HTTP_PORT = 80; + static const int HTTP_SOCKET_USE_PROXY = 0x1; static const int HTTP_SOCKET_QUEUED = 0x4; static const int HTTP_SOCKET_TO_BE_FREED = 0x8; @@ -67,28 +69,23 @@ typedef struct { /* Data structures and functions to queue sockets that need to be * delayed due to the per host connection limit. */ -typedef struct SocketQueueEntry { - SocketData_t* sock; - struct SocketQueueEntry *next ; -} SocketQueueEntry_t; - -typedef struct { - SocketQueueEntry_t *head; - SocketQueueEntry_t *tail; -} SocketQueue_t; - typedef struct { char *host; - int active_connections; - SocketQueue_t queue; + int active_conns; + Dlist *queue; } HostConnection_t; -static void Http_socket_queue_init(SocketQueue_t *sq); -static void Http_socket_enqueue(SocketQueue_t *sq, SocketData_t* sock); -static SocketData_t* Http_socket_dequeue(SocketQueue_t *sq); +typedef struct { + int fd; + int skey; +} FdMapEntry_t; + +static void Http_socket_enqueue(HostConnection_t *hc, SocketData_t* sock); +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); /* @@ -101,6 +98,11 @@ static char *HTTP_Proxy_Auth_base64 = NULL; static char *HTTP_Language_hdr = NULL; static Dlist *host_connections; +/* TODO: If fd_map will stick around in its present form (FDs and SocketData_t) + * then consider whether having both this and ValidSocks is necessary. + */ +static Dlist *fd_map; + /* * Initialize proxy vars and Accept-Language header */ @@ -125,6 +127,7 @@ int a_Http_init(void) */ host_connections = dList_new(5); + fd_map = dList_new(20); return 0; } @@ -155,14 +158,39 @@ void a_Http_set_proxy_passwd(const char *str) static int Http_sock_new(void) { SocketData_t *S = dNew0(SocketData_t, 1); + S->SockFD = -1; return a_Klist_insert(&ValidSocks, S); } +/* + * Compare by FD. + */ +static int Http_fd_map_cmp(const void *v1, const void *v2) +{ + int fd = VOIDP2INT(v2); + const FdMapEntry_t *e = v1; + + return (fd == e->fd) ? 0 : 1; +} + +/* + * Remove and free entry from fd_map. + */ +static void Http_fd_map_remove_entry(int fd) +{ + void *data = dList_find_custom(fd_map, INT2VOIDP(fd), Http_fd_map_cmp); + + if (data) { + dList_remove_fast(fd_map, data); + dFree(data); + } +} + static void Http_connect_queued_sockets(HostConnection_t *hc) { SocketData_t *sd; - while (hc->active_connections < prefs.http_max_conns && - (sd = Http_socket_dequeue(&hc->queue))) { + while (hc->active_conns < prefs.http_max_conns && + (sd = Http_socket_dequeue(hc))) { sd->flags &= ~HTTP_SOCKET_QUEUED; @@ -177,8 +205,17 @@ static void Http_connect_queued_sockets(HostConnection_t *hc) Http_socket_free(VOIDP2INT(Info->LocalKey)); /* free sd */ dFree(Info); } else { + FdMapEntry_t *e = dNew0(FdMapEntry_t, 1); + + e->fd = sd->SockFD; + e->skey = VOIDP2INT(sd->Info->LocalKey); + dList_append(fd_map, e); + + hc->active_conns++; + 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++; } } } @@ -197,11 +234,13 @@ static void Http_socket_free(int SKey) if (S->flags & HTTP_SOCKET_QUEUED) { S->flags |= HTTP_SOCKET_TO_BE_FREED; } else { + if (S->SockFD != -1) + Http_fd_map_remove_entry(S->SockFD); if (S->connected_to) { HostConnection_t *hc = Http_host_connection_get(S->connected_to); - hc->active_connections--; + hc->active_conns--; Http_connect_queued_sockets(hc); - if (hc->active_connections == 0) + if (hc->active_conns == 0) Http_host_connection_remove(hc); } dFree(S); @@ -275,6 +314,10 @@ 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 = + (prefs.http_persistent_conns == TRUE && + !dStrAsciiCasecmp(URL_SCHEME(url), "http")) ? "keep-alive" : "close"; + if (use_proxy) { dStr_sprintfa(request_uri, "%s%s", URL_STR(url), @@ -309,15 +352,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 +376,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); @@ -416,7 +459,7 @@ static int Http_connect_socket(ChainLink *Info) struct sockaddr_in *sin = (struct sockaddr_in *)&name; socket_len = sizeof(struct sockaddr_in); sin->sin_family = dh->af; - sin->sin_port = S->port ? htons(S->port) : htons(DILLO_URL_HTTP_PORT); + sin->sin_port = S->port ? htons(S->port) : htons(HTTP_PORT); memcpy(&sin->sin_addr, dh->data, (size_t)dh->alen); if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl)) MSG("Connecting to %s\n", inet_ntoa(sin->sin_addr)); @@ -430,7 +473,7 @@ static int Http_connect_socket(ChainLink *Info) socket_len = sizeof(struct sockaddr_in6); sin6->sin6_family = dh->af; sin6->sin6_port = - S->port ? htons(S->port) : htons(DILLO_URL_HTTP_PORT); + S->port ? htons(S->port) : htons(HTTP_PORT); memcpy(&sin6->sin6_addr, dh->data, dh->alen); inet_ntop(dh->af, dh->data, buf, sizeof(buf)); if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl)) @@ -447,9 +490,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 */ } } @@ -491,7 +531,6 @@ static int Http_must_use_proxy(const DilloUrl *url) /* * Return a new string for the request used to tunnel HTTPS through a proxy. - * As of 2009, the best reference appears to be section 5 of RFC 2817. */ char *a_Http_make_connect_str(const DilloUrl *url) { @@ -565,11 +604,11 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data) hc = Http_host_connection_get(URL_HOST(HTTP_Proxy)); else hc = Http_host_connection_get(URL_HOST(S->web->url)); - Http_socket_enqueue(&hc->queue, S); + Http_socket_enqueue(hc, S); Http_connect_queued_sockets(hc); } else { /* DNS wasn't able to resolve the hostname */ - MSG_BW(S->web, 0, "ERROR: Dns can't resolve %s", + MSG_BW(S->web, 0, "ERROR: DNS can't resolve %s", (S->flags & HTTP_SOCKET_USE_PROXY) ? URL_HOST_(HTTP_Proxy) : URL_HOST_(S->web->url)); a_Chain_bfcb(OpAbort, S->Info, NULL, "Both"); @@ -620,6 +659,46 @@ static int Http_get(ChainLink *Info, void *Data1) } /* + * If any entry in the socket data queue can reuse our connection, set it up + * and send off a new query. + */ +static void Http_socket_reuse(int SKey) +{ + SocketData_t *new_sd, *old_sd = a_Klist_get_data(ValidSocks, SKey); + HostConnection_t *hc = Http_host_connection_get(old_sd->connected_to); + int i, n = dList_length(hc->queue); + + for (i = 0; i < n; i++) { + new_sd = dList_nth_data(hc->queue, i); + + if (a_Web_valid(new_sd->web) && old_sd->port == new_sd->port) { + new_sd->SockFD = old_sd->SockFD; + Http_fd_map_remove_entry(old_sd->SockFD); + a_Klist_remove(ValidSocks, SKey); + dFree(old_sd); + + dList_remove(hc->queue, new_sd); + new_sd->flags &= ~HTTP_SOCKET_QUEUED; + FdMapEntry_t *e = dNew0(FdMapEntry_t, 1); + e->fd = new_sd->SockFD; + e->skey = VOIDP2INT(new_sd->Info->LocalKey); + dList_append(fd_map, e); + + a_Chain_bcb(OpSend, new_sd->Info, &new_sd->SockFD, "FD"); + a_Chain_fcb(OpSend, new_sd->Info, &new_sd->SockFD, "FD"); + Http_send_query(new_sd->Info, new_sd); + new_sd->connected_to = hc->host; + return; + } + } + dClose(old_sd->SockFD); + Http_fd_map_remove_entry(old_sd->SockFD); + a_Klist_remove(ValidSocks, SKey); + hc->active_conns--; + dFree(old_sd); +} + +/* * CCC function for the HTTP module */ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, @@ -648,7 +727,6 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, case OpEnd: /* finished the HTTP query branch */ a_Chain_bcb(OpEnd, Info, NULL, NULL); - Http_socket_free(SKey); dFree(Info); break; case OpAbort: @@ -659,51 +737,97 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, break; } } else { /* 1 FWD */ + SocketData_t *sd; /* HTTP send-query status branch */ switch (Op) { + case OpAbort: + if ((sd = a_Klist_get_data(ValidSocks, SKey))) + MSG_BW(sd->web, 1, "Can't get %s", URL_STR(sd->web->url)); + a_Chain_fcb(OpAbort, Info, NULL, "Both"); + Http_socket_free(SKey); + dFree(Info); + break; default: MSG_WARN("Unused CCC\n"); 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); + Http_socket_free(SKey); + 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")) { + int fd = *(int*)Data1; + FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd), + Http_fd_map_cmp); + Info->LocalKey = INT2VOIDP(fme->skey); + a_Chain_bcb(OpSend, Info, Data1, Data2); + } else if (!strcmp(Data2, "reply_complete")) { + a_Chain_bfcb(OpEnd, Info, NULL, NULL); + Http_socket_reuse(SKey); + dFree(Info); + } + } + break; + case OpAbort: + a_Chain_bcb(OpAbort, Info, NULL, NULL); + dFree(Info); + break; + default: + MSG_WARN("Unused CCC\n"); + break; + } + } } } - -static void Http_socket_queue_init(SocketQueue_t *sq) -{ - sq->head = NULL; - sq->tail = NULL; -} - -static void Http_socket_enqueue(SocketQueue_t *sq, SocketData_t* sock) +/* + * Add socket data to the queue. Pages/stylesheets/etc. have higher priority + * than images. + */ +static void Http_socket_enqueue(HostConnection_t *hc, SocketData_t* sock) { - SocketQueueEntry_t *se = dNew(SocketQueueEntry_t, 1); + if ((sock->web->flags & WEB_Image) == 0) { + int i, n = dList_length(hc->queue); - se->sock = sock; - se->next = NULL; + for (i = 0; i < n; i++) { + SocketData_t *curr = dList_nth_data(hc->queue, i); - if (sq->tail) - sq->tail->next = se; - sq->tail = se; - - if (! sq->head) - sq->head = se; + if (a_Web_valid(curr->web) && (curr->web->flags & WEB_Image)) { + dList_insert_pos(hc->queue, sock, i); + return; + } + } + } + dList_append(hc->queue, sock); } -static SocketData_t* Http_socket_dequeue(SocketQueue_t *sq) +static SocketData_t* Http_socket_dequeue(HostConnection_t *hc) { - SocketQueueEntry_t *se = sq->head; - SocketData_t *sd = NULL; - - if (se) { - sq->head = se->next; - if (sq->tail == se) - sq->tail = NULL; - sd = se->sock; - dFree(se); - } + SocketData_t *sd = dList_nth_data(hc->queue, 0); + dList_remove(hc->queue, sd); return sd; } @@ -720,7 +844,7 @@ static HostConnection_t *Http_host_connection_get(const char *host) } hc = dNew0(HostConnection_t, 1); - Http_socket_queue_init(&hc->queue); + hc->queue = dList_new(10); hc->host = dStrdup(host); dList_append(host_connections, hc); @@ -729,7 +853,8 @@ static HostConnection_t *Http_host_connection_get(const char *host) static void Http_host_connection_remove(HostConnection_t *hc) { - assert(hc->queue.head == NULL); + assert(dList_length(hc->queue) == 0); + dList_free(hc->queue); dList_remove_fast(host_connections, hc); dFree(hc->host); dFree(hc); @@ -738,15 +863,29 @@ static void Http_host_connection_remove(HostConnection_t *hc) static void Http_host_connection_remove_all() { HostConnection_t *hc; + SocketData_t *sd; while (dList_length(host_connections) > 0) { hc = (HostConnection_t*) dList_nth_data(host_connections, 0); - while (Http_socket_dequeue(&hc->queue)); + while ((sd = Http_socket_dequeue(hc))) + dFree(sd); Http_host_connection_remove(hc); } dList_free(host_connections); } +static void Http_fd_map_remove_all() +{ + FdMapEntry_t *fme; + int i, n = dList_length(fd_map); + + for (i = 0; i < n; i++) { + fme = (FdMapEntry_t *) dList_nth_data(fd_map, i); + dFree(fme); + } + dList_free(fd_map); +} + /* * Deallocate memory used by http module * (Call this one at exit time) @@ -754,6 +893,7 @@ static void Http_host_connection_remove_all() void a_Http_freeall(void) { Http_host_connection_remove_all(); + Http_fd_map_remove_all(); a_Klist_free(&ValidSocks); a_Url_free(HTTP_Proxy); dFree(HTTP_Proxy_Auth_base64); |