diff options
author | corvid <devnull@localhost> | 2016-04-09 15:53:21 +0000 |
---|---|---|
committer | corvid <devnull@localhost> | 2016-04-09 15:53:21 +0000 |
commit | 2e31d0502fd10c46fea3eb5e8f52fa3bc8e53f04 (patch) | |
tree | 1aa16917d1ef6fa96fe73a7af58411fb0cf3d3b2 | |
parent | 17601c3157a73965b23789285953953a54960ce2 (diff) |
if we get an error (e.g. ECONNRESET) while reading, abort the read and show a status message
-rw-r--r-- | src/IO/IO.c | 7 | ||||
-rw-r--r-- | src/IO/http.c | 11 | ||||
-rw-r--r-- | src/cache.c | 52 | ||||
-rw-r--r-- | src/cache.h | 4 | ||||
-rw-r--r-- | src/capi.c | 6 |
5 files changed, 52 insertions, 28 deletions
diff --git a/src/IO/IO.c b/src/IO/IO.c index 139cf667..4312fddb 100644 --- a/src/IO/IO.c +++ b/src/IO/IO.c @@ -285,6 +285,10 @@ static void IO_fd_read_cb(int fd, void *data) } else { if (IO_callback(io) == 0) a_IOwatch_remove_fd(fd, DIO_READ); + if ((io = IO_get(io_key)) && io->Status) { + /* check io because IO_read OpSend could trigger abort */ + a_IO_ccc(OpAbort, 2, FWD, io->Info, io, NULL); + } } } @@ -443,7 +447,8 @@ void a_IO_ccc(int Op, int Branch, int Dir, ChainLink *Info, dFree(dbuf); break; case OpEnd: - a_Chain_fcb(OpEnd, Info, NULL, NULL); + case OpAbort: + a_Chain_fcb(Op, Info, NULL, NULL); IO_close_fd(io, IO_StopRdWr); /* IO_StopRd would leak FDs */ IO_free(io); dFree(Info); diff --git a/src/IO/http.c b/src/IO/http.c index 379d51c1..15cd173c 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -911,6 +911,17 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, } dFree(Info); break; + case OpAbort: + if (sd->https_proxy_reply) { + MSG("CONNECT through proxy failed. " + "Full reply not received:\n%s\n", + sd->https_proxy_reply->len ? sd->https_proxy_reply->str : + "(nothing)"); + } + Http_socket_free(SKey); + a_Chain_fcb(OpAbort, Info, NULL, "Both"); + dFree(Info); + break; default: MSG_WARN("Unused CCC 2F Op %d\n", Op); break; diff --git a/src/cache.c b/src/cache.c index ec3a04bd..3929ca33 100644 --- a/src/cache.c +++ b/src/cache.c @@ -206,7 +206,7 @@ static void Cache_entry_init(CacheEntry_t *NewEntry, const DilloUrl *Url) NewEntry->CharsetDecoder = NULL; NewEntry->ExpectedSize = 0; NewEntry->TransferSize = 0; - NewEntry->Flags = CA_IsEmpty | CA_KeepAlive; + NewEntry->Flags = CA_IsEmpty | CA_InProgress | CA_KeepAlive; } /* @@ -270,7 +270,7 @@ static void Cache_entry_inject(const DilloUrl *Url, Dstr *data_ds) if (!(entry = Cache_entry_search(Url))) entry = Cache_entry_add(Url); - entry->Flags |= CA_GotData + CA_GotHeader + CA_GotLength + CA_InternalUrl; + entry->Flags |= CA_GotHeader + CA_GotLength + CA_InternalUrl; if (data_ds->len) entry->Flags &= ~CA_IsEmpty; dStr_truncate(entry->Data, 0); @@ -847,7 +847,7 @@ static int Cache_get_header(CacheEntry_t *entry, static void Cache_finish_msg(CacheEntry_t *entry) { - if (entry->Flags & CA_GotData) { + if (!(entry->Flags & CA_InProgress)) { /* already finished */ return; } @@ -858,13 +858,10 @@ static void Cache_finish_msg(CacheEntry_t *entry) } if ((entry->Flags & CA_GotLength) && (entry->ExpectedSize != entry->TransferSize)) { - MSG_HTTP("Content-Length does NOT match message body at\n" - "%s\n", URL_STR_(entry->Url)); - MSG("Expected size: %d, Transfer size: %d\n", - entry->ExpectedSize, entry->TransferSize); + MSG_HTTP("Content-Length (%d) does NOT match message body (%d) for %s\n", + entry->ExpectedSize, entry->TransferSize, URL_STR_(entry->Url)); } - entry->Flags |= CA_GotData; - entry->Flags &= ~CA_Stopped; /* it may catch up! */ + entry->Flags &= ~CA_InProgress; if (entry->TransferDecoder) { a_Decode_transfer_free(entry->TransferDecoder); entry->TransferDecoder = NULL; @@ -963,16 +960,22 @@ bool_t a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, } else if (Op == IOClose) { Cache_finish_msg(entry); } else if (Op == IOAbort) { - int i; - CacheClient_t *Client; + entry->Flags |= CA_Aborted; + if (entry->Data->len) { + MSG("Premature close for %s\n", URL_STR(entry->Url)); + Cache_finish_msg(entry); + } else { + int i; + CacheClient_t *Client; - for (i = 0; (Client = dList_nth_data(ClientQueue, i)); ++i) { - if (Client->Url == entry->Url) { - DilloWeb *web = (DilloWeb *)Client->Web; + for (i = 0; (Client = dList_nth_data(ClientQueue, i)); ++i) { + if (Client->Url == entry->Url) { + DilloWeb *web = (DilloWeb *)Client->Web; - a_Bw_remove_client(web->bw, Client->Key); - Cache_client_dequeue(Client); - --i; /* Keep the index value in the next iteration */ + a_Bw_remove_client(web->bw, Client->Key); + Cache_client_dequeue(Client); + --i; /* Keep the index value in the next iteration */ + } } } } @@ -1184,7 +1187,7 @@ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) st = a_Misc_get_content_type_from_data( entry->Data->str, entry->Data->len, &Type); _MSG("Cache: detected Content-Type '%s'\n", Type); - if (st == 0 || entry->Flags & CA_GotData) { + if (st == 0 || !(entry->Flags & CA_InProgress)) { if (a_Misc_content_type_check(entry->TypeHdr, Type) < 0) { MSG_HTTP("Content-Type '%s' doesn't match the real data.\n", entry->TypeHdr); @@ -1289,7 +1292,7 @@ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) } /* Remove client when done */ - if (entry->Flags & CA_GotData) { + if (!(entry->Flags & CA_InProgress)) { /* Copy flags to a local var */ int flags = ClientWeb->flags; @@ -1299,12 +1302,17 @@ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) } /* We finished sending data, let the client know */ (Client->Callback)(CA_Close, Client); - if (ClientWeb->flags & WEB_RootUrl) + if (ClientWeb->flags & WEB_RootUrl) { + if (entry->Flags & CA_Aborted) { + a_UIcmd_set_msg(Client_bw, "ERROR: Connection closed early, " + "read not complete."); + } a_UIcmd_set_page_prog(Client_bw, 0, 0); + } Cache_client_dequeue(Client); --i; /* Keep the index value in the next iteration */ - /* within CA_GotData, we assert just one redirect call */ + /* we assert just one redirect call */ if (entry->Flags & CA_Redirect) Cache_redirect(entry, flags, Client_bw); } @@ -1327,7 +1335,7 @@ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) } } a_Url_free(url); - } else if (entry->Auth && (entry->Flags & CA_GotData)) { + } else if (entry->Auth && !(entry->Flags & CA_InProgress)) { Cache_auth_entry(entry, Client_bw); } diff --git a/src/cache.h b/src/cache.h index f3b064f2..833e4394 100644 --- a/src/cache.h +++ b/src/cache.h @@ -22,12 +22,12 @@ extern "C" { #define CA_GotHeader 0x1 /* True after header is completely got */ #define CA_GotContentType 0x2 /* True after Content-Type is known */ #define CA_GotLength 0x4 /* True if Content-Length is known */ -#define CA_GotData 0x8 /* True if we have all Data in cache */ +#define CA_InProgress 0x8 /* True if we are getting data */ #define CA_Redirect 0x10 /* Data actually points to a redirect */ #define CA_ForceRedirect 0x20 /* Unconditional redirect */ #define CA_TempRedirect 0x40 /* Temporary redirect */ #define CA_NotFound 0x80 /* True if remote server didn't find the URL */ -#define CA_Stopped 0x100 /* True if the entry has been stopped */ +#define CA_Aborted 0x100 /* Aborted before getting full data */ #define CA_MsgErased 0x200 /* Used to erase the bw's status bar */ #define CA_RedirectLoop 0x400 /* Redirect loop */ #define CA_InternalUrl 0x800 /* URL content is generated by dillo */ @@ -502,10 +502,10 @@ static int Capi_map_cache_flags(uint_t flags) status |= CAPI_IsCached; if (flags & CA_IsEmpty) status |= CAPI_IsEmpty; - if (flags & CA_GotData) - status |= CAPI_Completed; - else + if (flags & CA_InProgress) status |= CAPI_InProgress; + else + status |= CAPI_Completed; /* CAPI_Aborted is not yet used/defined */ } |