aboutsummaryrefslogtreecommitdiff
path: root/src/IO
diff options
context:
space:
mode:
Diffstat (limited to 'src/IO')
-rw-r--r--src/IO/IO.c13
-rw-r--r--src/IO/about.c70
-rw-r--r--src/IO/http.c270
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);