From: wessels <> Date: Tue, 2 Apr 1996 07:51:52 +0000 (+0000) Subject: Made {ftp,gopher,wais} more like http. ie, protoCloseAndFree(). X-Git-Tag: SQUID_3_0_PRE1~6307 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ba718c8f6f578a2215f37e98d8a1e622c44a2cf2;p=thirdparty%2Fsquid.git Made {ftp,gopher,wais} more like http. ie, protoCloseAndFree(). treat ECONNRESET like any other read error. All read errors should be ejected immediately. Added ERR_ZERO_SIZE_OBJECT. --- diff --git a/src/errorpage.cc b/src/errorpage.cc index e095d210ed..5005c4fcbb 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -1,4 +1,4 @@ -/* $Id: errorpage.cc,v 1.8 1996/04/01 18:21:29 wessels Exp $ */ +/* $Id: errorpage.cc,v 1.9 1996/04/02 00:51:52 wessels Exp $ */ /* DEBUG: Section 4 cached_error: Error printing routines */ @@ -86,6 +86,9 @@ error_data ErrorData[] = {"ERR_URL_BLOCKED", "Access Denied", "You are not allowed to access this URL."}, + {"ERR_ZERO_SIZE_OBJECT", + "No Object Data", + "The remote server closed the connection before sending any data."}, {"ERR_MAX" "", ""} diff --git a/src/ftp.cc b/src/ftp.cc index 9859c25a51..edb08eecee 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -1,4 +1,4 @@ -/* $Id: ftp.cc,v 1.16 1996/04/01 23:34:43 wessels Exp $ */ +/* $Id: ftp.cc,v 1.17 1996/04/02 00:51:53 wessels Exp $ */ /* * DEBUG: Section 9 ftp: FTP @@ -33,6 +33,15 @@ typedef struct _Ftpdata { int got_marker; /* denotes end of successful request */ } FtpData; +static void ftpCloseAndFree(fd, data) + int fd; + FtpData *data; +{ + if (fd > -1) + comm_close(fd); + xfree(data); +} + /* XXX: this does not support FTP on a different port! */ int ftp_url_parser(url, data) char *url; @@ -122,8 +131,7 @@ void ftpLifetimeExpire(fd, data) } safe_free(data->icp_rwd_ptr); cached_error_entry(entry, ERR_LIFETIME_EXP, NULL); - comm_close(fd); - safe_free(data); + ftpCloseAndFree(fd, data); } @@ -147,7 +155,8 @@ int ftpReadReply(fd, data) clen = entry->mem_obj->e_current_len; off = entry->mem_obj->e_lowest_offset; if ((clen - off) > FTP_DELETE_GAP) { - debug(9, 3, "ftpReadReply: Read deferred for Object: %s\n", entry->key); + debug(9, 3, "ftpReadReply: Read deferred for Object: %s\n", + entry->url); debug(9, 3, "--> Current Gap: %d bytes\n", clen - off); /* reschedule, so it will automatically be reactivated when * Gap is big enough. */ @@ -161,8 +170,7 @@ int ftpReadReply(fd, data) } else { /* we can terminate connection right now */ cached_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL); - comm_close(fd); - safe_free(data); + ftpCloseAndFree(fd, data); return 0; } } @@ -170,20 +178,9 @@ int ftpReadReply(fd, data) len = read(fd, buf, READBUFSIZ); debug(9, 5, "ftpReadReply: FD %d, Read %d bytes\n", fd, len); - if (len < 0 || ((len == 0) && (entry->mem_obj->e_current_len == 0))) { - if (len < 0) - debug(9, 1, "ftpReadReply: read error: %s\n", xstrerror()); - if (errno == ECONNRESET) { - /* Connection reset by peer */ - /* consider it as a EOF */ - if (!(entry->flag & DELETE_BEHIND)) - entry->expires = cached_curtime + ttlSet(entry); - sprintf(tmp_error_buf, "\nWarning: The Remote Server sent RESET at the end of transmission.\n"); - storeAppend(entry, tmp_error_buf, strlen(tmp_error_buf)); - storeComplete(entry); - comm_close(fd); - safe_free(data); - } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (len < 0) { + debug(9, 1, "ftpReadReply: read error: %s\n", xstrerror()); + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* reinstall handlers */ /* XXX This may loop forever */ comm_set_select_handler(fd, COMM_SELECT_READ, @@ -191,15 +188,22 @@ int ftpReadReply(fd, data) /* note there is no ftpReadReplyTimeout. Timeouts are handled * by `ftpget'. */ } else { + BIT_RESET(entry->flag, CACHABLE); + BIT_SET(entry->flag, RELEASE_REQUEST); cached_error_entry(entry, ERR_READ_ERROR, xstrerror()); - comm_close(fd); - safe_free(data); + ftpCloseAndFree(fd, data); } + } else if (len == 0 && entry->mem_obj->e_current_len == 0) { + cached_error_entry(entry, + ERR_ZERO_SIZE_OBJECT, + errno ? xstrerror() : NULL); + ftpCloseAndFree(fd, data); } else if (len == 0) { /* Connection closed; retrieval done. */ if (!data->got_marker) { - /* If we didn't see the magic marker, assume the transfer failed and arrange - * so the object gets ejected and never gets to disk. */ + /* If we didn't see the magic marker, assume the transfer + * failed and arrange so the object gets ejected and + * never gets to disk. */ debug(9, 1, "ftpReadReply: Didn't see magic marker, purging .\n", entry->url); entry->expires = cached_curtime + getNegativeTTL(); BIT_RESET(entry->flag, CACHABLE); @@ -208,9 +212,8 @@ int ftpReadReply(fd, data) entry->expires = cached_curtime + ttlSet(entry); } /* update fdstat and fdtable */ - comm_close(fd); storeComplete(entry); - safe_free(data); + ftpCloseAndFree(fd, data); } else if (((entry->mem_obj->e_current_len + len) > getFtpMax()) && !(entry->flag & DELETE_BEHIND)) { /* accept data, but start to delete behind it */ @@ -224,10 +227,10 @@ int ftpReadReply(fd, data) /* append the last bit of info we get */ storeAppend(entry, buf, len); cached_error_entry(entry, ERR_CLIENT_ABORT, NULL); - comm_close(fd); - safe_free(data); + ftpCloseAndFree(fd, data); } else { /* check for a magic marker at the end of the read */ + data->got_marker = 0; if (len >= MAGIC_MARKER_SZ) { if (!memcmp(MAGIC_MARKER, buf + len - MAGIC_MARKER_SZ, MAGIC_MARKER_SZ)) { data->got_marker = 1; @@ -270,8 +273,7 @@ void ftpSendComplete(fd, buf, size, errflag, data) if (errflag) { cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - comm_close(fd); - safe_free(data); + ftpCloseAndFree(fd, data); return; } else { comm_set_select_handler(data->ftp_fd, @@ -392,9 +394,8 @@ void ftpConnInProgress(fd, data) debug(9, 5, "ftpConnInProgress: FD %d is now connected.", fd); break; /* cool, we're connected */ default: - comm_close(fd); cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - safe_free(data); + ftpCloseAndFree(fd, data); return; } /* Call the real write handler, now that we're fully connected */ @@ -438,9 +439,8 @@ int ftpStart(unusedfd, url, entry) /* Now connect ... */ if ((status = comm_connect(data->ftp_fd, "localhost", 3131))) { if (status != EINPROGRESS) { - comm_close(data->ftp_fd); cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - safe_free(data); + ftpCloseAndFree(data->ftp_fd, data); return COMM_ERROR; } else { debug(9, 5, "ftpStart: FD %d: EINPROGRESS.\n", data->ftp_fd); diff --git a/src/gopher.cc b/src/gopher.cc index 3decf8e891..b82cc9735f 100644 --- a/src/gopher.cc +++ b/src/gopher.cc @@ -1,4 +1,4 @@ -/* $Id: gopher.cc,v 1.12 1996/04/01 23:34:43 wessels Exp $ */ +/* $Id: gopher.cc,v 1.13 1996/04/02 00:51:54 wessels Exp $ */ /* * DEBUG: Section 10 gopher: GOPHER @@ -53,7 +53,6 @@ typedef struct gopher_ds { } conversion; int HTML_header_added; int port; - char *mime_hdr; char type_id; char request[MAX_URL]; int data_in; @@ -66,11 +65,21 @@ typedef struct gopher_ds { GopherData *CreateGopherData(); -static void freeGopherData _PARAMS((GopherData *)); char def_gopher_bin[] = "www/unknown"; char def_gopher_text[] = "text/plain"; +static void gopherCloseAndFree(fd, data) + int fd; + GopherData *data; +{ + if (fd > 0) + comm_close(fd); + put_free_4k_page(data->buf); + xfree(data); +} + + /* figure out content type from file extension */ static void gopher_mime_content(buf, name, def) char *buf; @@ -245,7 +254,7 @@ int gopherCachable(url, type, mime_hdr) default: cachable = 1; } - freeGopherData(data); + gopherCloseAndFree(-1, data); return cachable; } @@ -571,8 +580,7 @@ int gopherReadReplyTimeout(fd, data) put_free_4k_page(data->icp_page_ptr); if (data->icp_rwd_ptr) safe_free(data->icp_rwd_ptr); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); return 0; } @@ -593,8 +601,7 @@ void gopherLifetimeExpire(fd, data) COMM_SELECT_READ | COMM_SELECT_WRITE, 0, 0); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); } @@ -619,7 +626,7 @@ int gopherReadReply(fd, data) off = entry->mem_obj->e_lowest_offset; if ((clen - off) > GOPHER_DELETE_GAP) { debug(10, 3, "gopherReadReply: Read deferred for Object: %s\n", - entry->key); + entry->url); debug(10, 3, " Current Gap: %d bytes\n", clen - off); @@ -649,8 +656,7 @@ int gopherReadReply(fd, data) } else { /* we can terminate connection right now */ cached_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); return 0; } } @@ -659,20 +665,9 @@ int gopherReadReply(fd, data) len = read(fd, buf, TEMP_BUF_SIZE - 1); /* leave one space for \0 in gopherToHTML */ debug(10, 5, "gopherReadReply: FD %d read len=%d\n", fd, len); - if (len < 0 || ((len == 0) && (entry->mem_obj->e_current_len == 0))) { - debug(10, 1, "gopherReadReply: error reading: %s\n", - xstrerror()); - if (errno == ECONNRESET) { - /* Connection reset by peer */ - /* consider it as a EOF */ - if (!(entry->flag & DELETE_BEHIND)) - entry->expires = cached_curtime + ttlSet(entry); - sprintf(tmp_error_buf, "\nWarning: The Remote Server sent RESET at the end of transmission.\n"); - storeAppend(entry, tmp_error_buf, strlen(tmp_error_buf)); - storeComplete(entry); - comm_close(fd); - freeGopherData(data); - } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (len < 0) { + debug(10, 1, "gopherReadReply: error reading: %s\n", xstrerror()); + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* reinstall handlers */ /* XXX This may loop forever */ comm_set_select_handler(fd, COMM_SELECT_READ, @@ -680,10 +675,16 @@ int gopherReadReply(fd, data) comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) gopherReadReplyTimeout, (caddr_t) data, getReadTimeout()); } else { + BIT_RESET(entry->flag, CACHABLE); + BIT_SET(entry->flag, RELEASE_REQUEST); cached_error_entry(entry, ERR_READ_ERROR, xstrerror()); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); } + } else if (len == 0 && entry->mem_obj->e_current_len == 0) { + cached_error_entry(entry, + ERR_ZERO_SIZE_OBJECT, + errno ? xstrerror() : NULL); + gopherCloseAndFree(fd, data); } else if (len == 0) { /* Connection closed; retrieval done. */ /* flush the rest of data in temp buf if there is one. */ @@ -693,8 +694,7 @@ int gopherReadReply(fd, data) entry->expires = cached_curtime + ttlSet(entry); BIT_RESET(entry->flag, DELAY_SENDING); storeComplete(entry); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); } else if (((entry->mem_obj->e_current_len + len) > getGopherMax()) && !(entry->flag & DELETE_BEHIND)) { /* accept data, but start to delete behind it */ @@ -705,10 +705,15 @@ int gopherReadReply(fd, data) } else { storeAppend(entry, buf, len); } - comm_set_select_handler(fd, COMM_SELECT_READ, (PF) gopherReadReply, (caddr_t) data); - comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) gopherReadReplyTimeout, - (caddr_t) data, getReadTimeout()); - + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) gopherReadReply, + (caddr_t) data); + comm_set_select_handler_plus_timeout(fd, + COMM_SELECT_TIMEOUT, + (PF) gopherReadReplyTimeout, + (caddr_t) data, + getReadTimeout()); } else if (entry->flag & CLIENT_ABORT_REQUEST) { /* append the last bit of info we got */ if (data->conversion != NORMAL) { @@ -720,17 +725,22 @@ int gopherReadReply(fd, data) if (data->conversion != NORMAL) gopherEndHTML(data); BIT_RESET(entry->flag, DELAY_SENDING); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); } else { if (data->conversion != NORMAL) { gopherToHTML(data, buf, len); } else { storeAppend(entry, buf, len); } - comm_set_select_handler(fd, COMM_SELECT_READ, (PF) gopherReadReply, (caddr_t) data); - comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) gopherReadReplyTimeout, - (caddr_t) data, getReadTimeout()); + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) gopherReadReply, + (caddr_t) data); + comm_set_select_handler_plus_timeout(fd, + COMM_SELECT_TIMEOUT, + (PF) gopherReadReplyTimeout, + (caddr_t) data, + getReadTimeout()); } put_free_4k_page(buf); return 0; @@ -751,8 +761,7 @@ void gopherSendComplete(fd, buf, size, errflag, data) fd, size, errflag); if (errflag) { cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - comm_close(fd); - freeGopherData(data); + gopherCloseAndFree(fd, data); if (buf) put_free_4k_page(buf); /* Allocated by gopherSendRequest. */ return; @@ -868,7 +877,7 @@ int gopherStart(unusedfd, url, entry) if (gopher_url_parser(url, data->host, &data->port, &data->type_id, data->request)) { cached_error_entry(entry, ERR_INVALID_URL, NULL); - freeGopherData(data); + gopherCloseAndFree(-1, data); return COMM_ERROR; } /* Create socket. */ @@ -876,7 +885,7 @@ int gopherStart(unusedfd, url, entry) if (sock == COMM_ERROR) { debug(10, 4, "gopherStart: Failed because we're out of sockets.\n"); cached_error_entry(entry, ERR_NO_FDS, xstrerror()); - freeGopherData(data); + gopherCloseAndFree(-1, data); return COMM_ERROR; } /* check if IP is already in cache. It must be. @@ -884,9 +893,8 @@ int gopherStart(unusedfd, url, entry) * Otherwise, we cannot check return code for connect. */ if (!ipcache_gethostbyname(data->host)) { debug(10, 4, "gopherStart: Called without IP entry in ipcache. OR lookup failed.\n"); - comm_close(sock); cached_error_entry(entry, ERR_DNS_FAIL, dns_error_message); - freeGopherData(data); + gopherCloseAndFree(sock, data); return COMM_ERROR; } if (((data->type_id == GOPHER_INDEX) || (data->type_id == GOPHER_CSO)) @@ -907,16 +915,14 @@ int gopherStart(unusedfd, url, entry) } gopherToHTML(data, (char *) NULL, 0); storeComplete(entry); - freeGopherData(data); - comm_close(sock); + gopherCloseAndFree(sock, data); return COMM_OK; } /* Open connection. */ if ((status = comm_connect(sock, data->host, data->port)) != 0) { if (status != EINPROGRESS) { - comm_close(sock); cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - freeGopherData(data); + gopherCloseAndFree(sock, data); return COMM_ERROR; } else { debug(10, 5, "startGopher: conn %d EINPROGRESS\n", sock); @@ -943,10 +949,3 @@ GopherData *CreateGopherData() gd->buf = get_free_4k_page(); return (gd); } - -static void freeGopherData(gd) - GopherData *gd; -{ - put_free_4k_page(gd->buf); - safe_free(gd); -} diff --git a/src/http.cc b/src/http.cc index ee9fdfd4fb..956b8b9b67 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1,4 +1,4 @@ -/* $Id: http.cc,v 1.22 1996/04/01 23:34:44 wessels Exp $ */ +/* $Id: http.cc,v 1.23 1996/04/02 00:51:54 wessels Exp $ */ /* * DEBUG: Section 11 http: HTTP @@ -249,7 +249,8 @@ static void httpReadReply(fd, data) clen = entry->mem_obj->e_current_len; off = entry->mem_obj->e_lowest_offset; if ((clen - off) > HTTP_DELETE_GAP) { - debug(11, 3, "httpReadReply: Read deferred for Object: %s\n", entry->key); + debug(11, 3, "httpReadReply: Read deferred for Object: %s\n", + entry->url); debug(11, 3, " Current Gap: %d bytes\n", clen - off); /* reschedule, so it will be automatically reactivated * when Gap is big enough. */ @@ -285,20 +286,10 @@ static void httpReadReply(fd, data) len = read(fd, buf, READBUFSIZ); debug(11, 5, "httpReadReply: FD %d: len %d.\n", fd, len); - if (len < 0 || ((len == 0) && (entry->mem_obj->e_current_len == 0))) { - /* XXX we we should log when len==0 and current_len==0 */ + if (len < 0) { debug(11, 2, "httpReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); - if (errno == ECONNRESET) { - /* Connection reset by peer, junk the object */ - /* XXX this line we add assumes HTML. Should we lose it? -DPW */ - sprintf(tmp_error_buf, "\n

Warning: The Remote Server sent RESET at the end of transmission.\n"); - storeAppend(entry, tmp_error_buf, strlen(tmp_error_buf)); - BIT_RESET(entry->flag, CACHABLE); - BIT_SET(entry->flag, RELEASE_REQUEST); - storeComplete(entry); - httpCloseAndFree(fd, data); - } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* reinstall handlers */ /* XXX This may loop forever */ comm_set_select_handler(fd, COMM_SELECT_READ, @@ -306,24 +297,34 @@ static void httpReadReply(fd, data) comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) httpReadReplyTimeout, (caddr_t) data, getReadTimeout()); } else { + BIT_RESET(entry->flag, CACHABLE); + BIT_SET(entry->flag, RELEASE_REQUEST); cached_error_entry(entry, ERR_READ_ERROR, xstrerror()); httpCloseAndFree(fd, data); } + } else if (len == 0 && entry->mem_obj->e_current_len == 0) { + cached_error_entry(entry, + ERR_ZERO_SIZE_OBJECT, + errno ? xstrerror() : NULL); + httpCloseAndFree(fd, data); } else if (len == 0) { /* Connection closed; retrieval done. */ storeComplete(entry); httpCloseAndFree(fd, data); - } else if (((entry->mem_obj->e_current_len + len) > getHttpMax()) && + } else if ((entry->mem_obj->e_current_len + len) > getHttpMax() && !(entry->flag & DELETE_BEHIND)) { /* accept data, but start to delete behind it */ storeStartDeleteBehind(entry); - storeAppend(entry, buf, len); - comm_set_select_handler(fd, COMM_SELECT_READ, - (PF) httpReadReply, (caddr_t) data); - comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, - (PF) httpReadReplyTimeout, (caddr_t) data, getReadTimeout()); - + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) httpReadReply, + (caddr_t) data); + comm_set_select_handler_plus_timeout(fd, + COMM_SELECT_TIMEOUT, + (PF) httpReadReplyTimeout, + (caddr_t) data, + getReadTimeout()); } else if (entry->flag & CLIENT_ABORT_REQUEST) { /* append the last bit of info we get */ storeAppend(entry, buf, len); @@ -333,10 +334,15 @@ static void httpReadReply(fd, data) storeAppend(entry, buf, len); if (data->reply_hdr_state < 2) httpProcessReplyHeader(data, buf); - comm_set_select_handler(fd, COMM_SELECT_READ, - (PF) httpReadReply, (caddr_t) data); - comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, - (PF) httpReadReplyTimeout, (caddr_t) data, getReadTimeout()); + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) httpReadReply, + (caddr_t) data); + comm_set_select_handler_plus_timeout(fd, + COMM_SELECT_TIMEOUT, + (PF) httpReadReplyTimeout, + (caddr_t) data, + getReadTimeout()); } } diff --git a/src/store.cc b/src/store.cc index 612ffefc86..5de4b76a07 100644 --- a/src/store.cc +++ b/src/store.cc @@ -1,5 +1,5 @@ -/* $Id: store.cc,v 1.20 1996/04/01 23:34:45 wessels Exp $ */ +/* $Id: store.cc,v 1.21 1996/04/02 00:51:55 wessels Exp $ */ /* * DEBUG: Section 20 store @@ -2038,7 +2038,6 @@ void storeChangeKey(e) debug(25, 0, "storeChangeKey: NULL key for %s\n", e->url); return; } - if ((table_entry = hash_lookup(table, e->key))) result = (StoreEntry *) table_entry; if (result != e) { @@ -2073,7 +2072,6 @@ void storeUnChangeKey(e) debug(25, 0, "storeUnChangeKey: NULL key for %s\n", e->url); return; } - if ((table_entry = hash_lookup(table, e->key))) E1 = (StoreEntry *) table_entry; if (E1 != e) { diff --git a/src/wais.cc b/src/wais.cc index bee52f0e80..fbf3978922 100644 --- a/src/wais.cc +++ b/src/wais.cc @@ -1,4 +1,4 @@ -/* $Id: wais.cc,v 1.15 1996/04/01 23:34:47 wessels Exp $ */ +/* $Id: wais.cc,v 1.16 1996/04/02 00:51:56 wessels Exp $ */ /* * DEBUG: Section 24 wais @@ -20,7 +20,17 @@ typedef struct _waisdata { extern char *dns_error_message; -int wais_url_parser(url, host, port, request) +static void waisCloseAndFree(fd, data) + int fd; + WAISData *data; +{ + if (fd > 0) + comm_close(fd); + xfree(data); +} + + +static int wais_url_parser(url, host, port, request) char *url; char *host; int *port; @@ -34,7 +44,7 @@ int wais_url_parser(url, host, port, request) } /* This will be called when timeout on read. */ -void waisReadReplyTimeout(fd, data) +static void waisReadReplyTimeout(fd, data) int fd; WAISData *data; { @@ -44,8 +54,7 @@ void waisReadReplyTimeout(fd, data) debug(24, 4, "waisReadReplyTimeout: Timeout on %d\n url: %s\n", fd, entry->url); cached_error_entry(entry, ERR_READ_TIMEOUT, NULL); comm_set_select_handler(fd, COMM_SELECT_READ, 0, 0); - comm_close(fd); - safe_free(data); + waisCloseAndFree(fd, data); } /* This will be called when socket lifetime is expired. */ @@ -59,8 +68,7 @@ void waisLifetimeExpire(fd, data) debug(24, 4, "waisLifeTimeExpire: FD %d: \n", fd, entry->url); cached_error_entry(entry, ERR_LIFETIME_EXP, NULL); comm_set_select_handler(fd, COMM_SELECT_READ | COMM_SELECT_WRITE, 0, 0); - comm_close(fd); - safe_free(data); + waisCloseAndFree(fd, data); } @@ -82,12 +90,13 @@ void waisReadReply(fd, data) /* check if we want to defer reading */ if ((entry->mem_obj->e_current_len - entry->mem_obj->e_lowest_offset) > WAIS_DELETE_GAP) { - debug(24, 3, "waisReadReply: Read deferred for Object: %s\n", entry->key); + debug(24, 3, "waisReadReply: Read deferred for Object: %s\n", + entry->url); debug(24, 3, " Current Gap: %d bytes\n", entry->mem_obj->e_current_len - entry->mem_obj->e_lowest_offset); - - /* reschedule, so it will automatically reactivated when Gap is big enough. */ + /* reschedule, so it will automatically reactivated + * when Gap is big enough. */ comm_set_select_handler(fd, COMM_SELECT_READ, (PF) waisReadReply, @@ -105,34 +114,23 @@ void waisReadReply(fd, data) (caddr_t) NULL, (time_t) 0); #endif - comm_set_stall(fd, getStallDelay()); /* dont try reading again for a while */ + /* dont try reading again for a while */ + comm_set_stall(fd, getStallDelay()); return; } } else { /* we can terminate connection right now */ cached_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL); - comm_close(fd); - safe_free(data); + waisCloseAndFree(fd, data); return; } } len = read(fd, buf, 4096); debug(24, 5, "waisReadReply - fd: %d read len:%d\n", fd, len); - if (len < 0 || ((len == 0) && (entry->mem_obj->e_current_len == 0))) { - debug(24, 1, "waisReadReply - error reading errno %d: %s\n", - errno, xstrerror()); - if (errno == ECONNRESET) { - /* Connection reset by peer */ - /* consider it as a EOF */ - if (!(entry->flag & DELETE_BEHIND)) - entry->expires = cached_curtime + ttlSet(entry); - sprintf(tmp_error_buf, "\nWarning: The Remote Server sent RESET at the end of transmission.\n"); - storeAppend(entry, tmp_error_buf, strlen(tmp_error_buf)); - storeComplete(entry); - comm_close(fd); - safe_free(data); - } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (len < 0) { + debug(24, 1, "waisReadReply: FD %d: read failure: %s.\n", xstrerror()); + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* reinstall handlers */ /* XXX This may loop forever */ comm_set_select_handler(fd, COMM_SELECT_READ, @@ -140,21 +138,25 @@ void waisReadReply(fd, data) comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) waisReadReplyTimeout, (caddr_t) data, getReadTimeout()); } else { + BIT_RESET(entry->flag, CACHABLE); + BIT_SET(entry->flag, RELEASE_REQUEST); cached_error_entry(entry, ERR_READ_ERROR, xstrerror()); - comm_close(fd); - safe_free(data); + waisCloseAndFree(fd, data); } + } else if (len == 0 && entry->mem_obj->e_current_len == 0) { + cached_error_entry(entry, + ERR_ZERO_SIZE_OBJECT, + errno ? xstrerror() : NULL); + waisCloseAndFree(fd, data); } else if (len == 0) { /* Connection closed; retrieval done. */ entry->expires = cached_curtime; storeComplete(entry); - comm_close(fd); - safe_free(data); + waisCloseAndFree(fd, data); } else if (((entry->mem_obj->e_current_len + len) > getWAISMax()) && !(entry->flag & DELETE_BEHIND)) { /* accept data, but start to delete behind it */ storeStartDeleteBehind(entry); - storeAppend(entry, buf, len); comm_set_select_handler(fd, COMM_SELECT_READ, @@ -194,8 +196,7 @@ void waisSendComplete(fd, buf, size, errflag, data) fd, size, errflag); if (errflag) { cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - comm_close(fd); - safe_free(data); + waisCloseAndFree(fd, data); } else { /* Schedule read reply. */ comm_set_select_handler(fd, @@ -280,17 +281,15 @@ int waisStart(unusedfd, url, type, mime_hdr, entry) * Otherwise, we cannot check return code for connect. */ if (!ipcache_gethostbyname(data->host)) { debug(24, 4, "waisstart: Called without IP entry in ipcache. OR lookup failed.\n"); - comm_close(sock); cached_error_entry(entry, ERR_DNS_FAIL, dns_error_message); - safe_free(data); + waisCloseAndFree(sock, data); return COMM_ERROR; } /* Open connection. */ if ((status = comm_connect(sock, data->host, data->port))) { if (status != EINPROGRESS) { - comm_close(sock); cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); - safe_free(data); + waisCloseAndFree(sock, data); return COMM_ERROR; } else { debug(24, 5, "waisStart - conn %d EINPROGRESS\n", sock);