diff -N -c -r -X exclude_files squid-1.0.beta9/src/comm.c squid-1.0.beta9.henrik/src/comm.c *** squid-1.0.beta9/src/comm.c Tue May 28 01:13:49 1996 --- squid-1.0.beta9.henrik/src/comm.c Tue May 28 01:14:22 1996 *************** *** 467,472 **** --- 467,475 ---- } conn = &fd_table[fd]; + safe_free(conn->rstate); + safe_free(conn->wstate); + comm_set_fd_lifetime(fd, -1); /* invalidate the lifetime */ debug(5, 5, "comm_close: FD %d\n", fd); /* update fdstat */ *************** *** 484,489 **** --- 487,495 ---- { FD_ENTRY *conn = &fd_table[fd]; + safe_free(conn->rstate); + safe_free(conn->wstate); + memset(conn, 0, sizeof(FD_ENTRY)); return 0; } *************** *** 1198,1201 **** --- 1204,1426 ---- } } return (-1); + } + + struct _RWStateData { + char *buf; + long size; + long offset; + int timeout; /* XXX Not used at present. */ + time_t time; /* XXX Not used at present. */ + rw_complete_handler *handler; + void *handler_data; + int handle_immed; + }; + + /* Read from FD. */ + static int commHandleRead(fd, state) + int fd; + RWStateData *state; + { + int len; + + len = read(fd, state->buf + state->offset, state->size - state->offset); + debug(5, 5, "commHandleRead: FD %d: read %d bytes\n", fd, len); + + if (len <= 0) { + switch (errno) { + #if EAGAIN != EWOULDBLOCK + case EAGAIN: + #endif + case EWOULDBLOCK: + /* reschedule self */ + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) commHandleRead, + state); + return COMM_OK; + default: + /* Len == 0 means connection closed; otherwise would not have been + * called by comm_select(). */ + debug(5, len == 0 ? 2 : 1, "commHandleRead: FD %d: read failure: %s\n", + fd, len == 0 ? "connection closed" : xstrerror()); + fd_table[fd].rstate = NULL; /* The handler may issue a new read */ + /* Notify caller that we failed */ + state->handler(fd, + state->buf, + state->offset, + COMM_ERROR, + state->handler_data); + safe_free(state); + return COMM_ERROR; + } + } + state->offset += len; + + /* Call handler if we have read enought */ + if (state->offset >= state->size || state->handle_immed) { + fd_table[fd].rstate = NULL; /* The handler may issue a new read */ + state->handler(fd, + state->buf, + state->offset, + COMM_OK, + state->handler_data); + safe_free(state); + } else { + /* Reschedule until we are done */ + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) commHandleRead, + state); + } + + return COMM_OK; + } + + /* Select for reading on FD, until SIZE bytes are received. Call + * HANDLER when complete. */ + void comm_read(fd, buf, size, timeout, immed, handler, handler_data) + int fd; + char *buf; + int size; + int timeout; + int immed; /* Call handler immediately when data available */ + rw_complete_handler *handler; + void *handler_data; + { + RWStateData *state = NULL; + + debug(5, 5, "comm_read: FD %d: sz %d: tout %d: hndl %p: data %p.\n", + fd, size, timeout, handler, handler_data); + + if(fd_table[fd].rstate) { + debug(5,1,"comm_read: WARNING! A comm_read is already active.\n"); + safe_free(fd_table[fd].rstate); + } + state = xcalloc(1, sizeof(RWStateData)); + fd_table[fd].rstate=state; + state->buf = buf; + state->size = size; + state->offset = 0; + state->handler = handler; + state->timeout = timeout; + state->handle_immed = immed; + state->time = squid_curtime; + state->handler_data = handler_data; + comm_set_select_handler(fd, + COMM_SELECT_READ, + (PF) commHandleRead, + state); + } + + /* Write to FD. */ + static void commHandleWrite(fd, state) + int fd; + RWStateData *state; + { + int len = 0; + int nleft; + + debug(5, 5, "commHandleWrite: FD %d: off %d: sz %d.\n", + fd, state->offset, state->size); + + nleft = state->size - state->offset; + len = write(fd, state->buf + state->offset, nleft); + + if (len == 0) { + /* XXX Is it ever possible that write() returns 0? */ + /* We're done */ + if (nleft != 0) + debug(5, 2, "commHandleWrite: FD %d: write failure: connection closed with %d bytes remaining.\n", fd, nleft); + fd_table[fd].wstate = NULL; /* The handler may call comm_write again */ + /* Notify caller */ + state->handler(fd, + state->buf, + state->offset, + nleft == 0 ? COMM_OK : COMM_ERROR, + state->handler_data); + safe_free(state); + return; + } + if (len < 0) { + /* An error */ + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* XXX: Re-install the handler rather than giving up. I hope + * this doesn't freeze this socket due to some random OS bug + * returning EWOULDBLOCK indefinitely. Ought to maintain a + * retry count in state? */ + debug(5, 10, "commHandleWrite: FD %d: write failure: %s.\n", + fd, xstrerror()); + comm_set_select_handler(fd, + COMM_SELECT_WRITE, + (PF) commHandleWrite, + state); + return; + } + debug(5, 2, "commHandleWrite: FD %d: write failure: %s.\n", + fd, xstrerror()); + fd_table[fd].wstate = NULL; /* The handler may call comm_write again */ + /* Notify caller that we failed */ + state->handler(fd, + state->buf, + state->offset, + COMM_ERROR, + state->handler_data); + safe_free(state); + return; + } + /* A successful write, continue */ + state->offset += len; + if (state->offset < state->size) { + /* Reinstall the write handler and write some more */ + comm_set_select_handler(fd, + COMM_SELECT_WRITE, + (PF) commHandleWrite, + state); + return; + } + fd_table[fd].wstate = NULL; /* The handler may call comm_write again */ + /* Notify caller that the write is complete */ + state->handler(fd, + state->buf, + state->offset, + COMM_OK, + state->handler_data); + safe_free(state); + } + + + + /* Select for Writing on FD, until SIZE bytes are sent. Call + * HANDLER when complete. */ + void comm_write(fd, buf, size, timeout, handler, handler_data) + int fd; + char *buf; + int size; + int timeout; + rw_complete_handler *handler; + void *handler_data; + { + RWStateData *state = NULL; + + debug(5, 5, "comm_write: FD %d: sz %d: tout %d: hndl %p: data %p.\n", + fd, size, timeout, handler, handler_data); + + if(fd_table[fd].wstate) { + debug(5,1,"comm_write: WARNING! A comm_write is already active.\n"); + safe_free(fd_table[fd].wstate); + } + state = xcalloc(1, sizeof(RWStateData)); + fd_table[fd].wstate=state; + state->buf = buf; + state->size = size; + state->offset = 0; + state->handler = handler; + state->timeout = timeout; + state->time = squid_curtime; + state->handler_data = handler_data; + comm_set_select_handler(fd, + COMM_SELECT_WRITE, + (PF) commHandleWrite, + state); } diff -N -c -r -X exclude_files squid-1.0.beta9/src/comm.h squid-1.0.beta9.henrik/src/comm.h *** squid-1.0.beta9/src/comm.h Tue May 28 01:13:50 1996 --- squid-1.0.beta9.henrik/src/comm.h Mon May 27 22:21:49 1996 *************** *** 26,31 **** --- 26,34 ---- typedef int (*PF) _PARAMS((int, void *)); + typedef void rw_complete_handler _PARAMS((int fd, char *buf, int size, int errflag, void *data)); + typedef struct _RWStateData RWStateData; + #define FD_ASCII_NOTE_SZ 64 typedef struct fde { *************** *** 55,60 **** --- 58,65 ---- char ascii_note[FD_ASCII_NOTE_SZ]; unsigned int comm_type; time_t stall_until; /* don't select for read until this time reached */ + RWStateData *rstate; /* State data for comm_read */ + RWStateData *wstate; /* State data for comm_write */ } FD_ENTRY; extern FD_ENTRY *fd_table; *************** *** 77,83 **** extern int comm_pending _PARAMS((int fd, long sec, long usec)); #endif extern u_short comm_local_port _PARAMS((int fd)); - extern int comm_read _PARAMS((int fd, char *buf, int size)); extern int comm_select _PARAMS((time_t sec, time_t)); extern int comm_set_fd_lifetime _PARAMS((int fd, int lifetime)); extern void comm_set_select_handler _PARAMS((int fd, unsigned int type, PF, void *)); --- 82,87 ---- *************** *** 85,95 **** extern int comm_udp_recv _PARAMS((int, char *, int, struct sockaddr_in *, int *)); extern int comm_udp_send _PARAMS((int fd, char *host, u_short port, char *buf, int len)); extern int comm_udp_sendto _PARAMS((int fd, struct sockaddr_in *, int size, char *buf, int len)); - extern int comm_write _PARAMS((int fd, char *buf, int size)); extern int fd_of_first_client _PARAMS((StoreEntry *)); extern struct in_addr *getAddress _PARAMS((char *name)); extern void comm_set_stall _PARAMS((int, int)); extern int comm_get_fd_timeout _PARAMS((int fd)); extern int RESERVED_FD; --- 89,100 ---- extern int comm_udp_recv _PARAMS((int, char *, int, struct sockaddr_in *, int *)); extern int comm_udp_send _PARAMS((int fd, char *host, u_short port, char *buf, int len)); extern int comm_udp_sendto _PARAMS((int fd, struct sockaddr_in *, int size, char *buf, int len)); extern int fd_of_first_client _PARAMS((StoreEntry *)); extern struct in_addr *getAddress _PARAMS((char *name)); extern void comm_set_stall _PARAMS((int, int)); extern int comm_get_fd_timeout _PARAMS((int fd)); + extern void comm_read _PARAMS((int fd, char *buf, int size, int timeout, int immed, rw_complete_handler *handler, void *handler_data)); + extern void comm_write _PARAMS((int fd, char *buf, int size, int timeout, rw_complete_handler *handler, void *handler_data)); extern int RESERVED_FD; diff -N -c -r -X exclude_files squid-1.0.beta9/src/ftp.c squid-1.0.beta9.henrik/src/ftp.c *** squid-1.0.beta9/src/ftp.c Tue May 28 01:13:51 1996 --- squid-1.0.beta9.henrik/src/ftp.c Mon May 27 23:58:22 1996 *************** *** 31,39 **** char *icp_page_ptr; /* Used to send proxy-http request: * put_free_8k_page(me) if the lifetime * expires */ - char *icp_rwd_ptr; /* When a lifetime expires during the - * middle of an icpwrite, don't lose the - * icpReadWriteData */ int got_marker; /* denotes end of successful request */ int reply_hdr_state; } FtpData; --- 31,36 ---- *************** *** 48,54 **** /* Global functions not declared in ftp.h */ void ftpLifetimeExpire _PARAMS((int fd, FtpData * data)); int ftpReadReply _PARAMS((int fd, FtpData * data)); ! void ftpSendComplete _PARAMS((int fd, char *buf, int size, int errflag, FtpData * data)); void ftpSendRequest _PARAMS((int fd, FtpData * data)); void ftpConnInProgress _PARAMS((int fd, FtpData * data)); void ftpServerClose _PARAMS((void)); --- 45,51 ---- /* Global functions not declared in ftp.h */ void ftpLifetimeExpire _PARAMS((int fd, FtpData * data)); int ftpReadReply _PARAMS((int fd, FtpData * data)); ! void ftpSendComplete _PARAMS((int fd, char *buf, int size, int errflag, void *ftpData)); void ftpSendRequest _PARAMS((int fd, FtpData * data)); void ftpConnInProgress _PARAMS((int fd, FtpData * data)); void ftpServerClose _PARAMS((void)); *************** *** 68,75 **** put_free_8k_page(ftpState->icp_page_ptr); ftpState->icp_page_ptr = NULL; } - if (ftpState->icp_rwd_ptr) - safe_free(ftpState->icp_rwd_ptr); if (--ftpState->request->link_count == 0) safe_free(ftpState->request); xfree(ftpState); --- 65,70 ---- *************** *** 340,350 **** char *buf; int size; int errflag; ! FtpData *data; { StoreEntry *entry = NULL; ! entry = data->entry; debug(9, 5, "ftpSendComplete: FD %d: size %d: errflag %d.\n", fd, size, errflag); --- 335,346 ---- char *buf; int size; int errflag; ! void *data; { + FtpData *ftpState=(FtpData *)data; StoreEntry *entry = NULL; ! entry = ftpState->entry; debug(9, 5, "ftpSendComplete: FD %d: size %d: errflag %d.\n", fd, size, errflag); *************** *** 352,373 **** put_free_8k_page(buf); /* Allocated by ftpSendRequest. */ buf = NULL; } ! data->icp_page_ptr = NULL; /* So lifetime expire doesn't re-free */ ! data->icp_rwd_ptr = NULL; /* Don't double free in lifetimeexpire */ if (errflag) { squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); comm_close(fd); return; } else { ! comm_set_select_handler(data->ftp_fd, COMM_SELECT_READ, (PF) ftpReadReply, ! (void *) data); ! comm_set_select_handler_plus_timeout(data->ftp_fd, COMM_SELECT_TIMEOUT, (PF) ftpLifetimeExpire, ! (void *) data, getReadTimeout()); } } --- 348,368 ---- put_free_8k_page(buf); /* Allocated by ftpSendRequest. */ buf = NULL; } ! ftpState->icp_page_ptr = NULL; /* So lifetime expire doesn't re-free */ if (errflag) { squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); comm_close(fd); return; } else { ! comm_set_select_handler(ftpState->ftp_fd, COMM_SELECT_READ, (PF) ftpReadReply, ! (void *) ftpState); ! comm_set_select_handler_plus_timeout(ftpState->ftp_fd, COMM_SELECT_TIMEOUT, (PF) ftpLifetimeExpire, ! (void *) ftpState, getReadTimeout()); } } *************** *** 459,465 **** strcat(buf, *data->password ? data->password : "\"\""); strcat(buf, "\n"); debug(9, 5, "ftpSendRequest: FD %d: buf '%s'\n", fd, buf); ! data->icp_rwd_ptr = icpWrite(fd, buf, strlen(buf), 30, --- 454,460 ---- strcat(buf, *data->password ? data->password : "\"\""); strcat(buf, "\n"); debug(9, 5, "ftpSendRequest: FD %d: buf '%s'\n", fd, buf); ! comm_write(fd, buf, strlen(buf), 30, diff -N -c -r -X exclude_files squid-1.0.beta9/src/gopher.c squid-1.0.beta9.henrik/src/gopher.c *** squid-1.0.beta9/src/gopher.c Tue May 28 01:13:52 1996 --- squid-1.0.beta9.henrik/src/gopher.c Mon May 27 23:42:35 1996 *************** *** 58,64 **** int len; char *buf; /* pts to a 4k page */ char *icp_page_ptr; /* Pts to gopherStart buffer that needs to be freed */ - char *icp_rwd_ptr; /* Pts to icp rw structure that needs to be freed */ } GopherData; GopherData *CreateGopherData(); --- 58,63 ---- *************** *** 573,580 **** squid_error_entry(entry, ERR_READ_TIMEOUT, NULL); if (data->icp_page_ptr) put_free_4k_page(data->icp_page_ptr); - if (data->icp_rwd_ptr) - safe_free(data->icp_rwd_ptr); comm_close(fd); return 0; } --- 572,577 ---- *************** *** 590,597 **** squid_error_entry(entry, ERR_LIFETIME_EXP, NULL); if (data->icp_page_ptr) put_free_4k_page(data->icp_page_ptr); - if (data->icp_rwd_ptr) - safe_free(data->icp_rwd_ptr); comm_set_select_handler(fd, COMM_SELECT_READ | COMM_SELECT_WRITE, 0, --- 587,592 ---- *************** *** 740,749 **** char *buf; int size; int errflag; ! GopherData *data; { StoreEntry *entry = NULL; ! entry = data->entry; debug(10, 5, "gopherSendComplete: FD %d size: %d errflag: %d\n", fd, size, errflag); if (errflag) { --- 735,745 ---- char *buf; int size; int errflag; ! void *data; { + GopherData *gopherState=(GopherData *)data; StoreEntry *entry = NULL; ! entry = gopherState->entry; debug(10, 5, "gopherSendComplete: FD %d size: %d errflag: %d\n", fd, size, errflag); if (errflag) { *************** *** 757,811 **** * OK. We successfully reach remote site. Start MIME typing * stuff. Do it anyway even though request is not HTML type. */ ! gopherMimeCreate(data); if (!BIT_TEST(entry->flag, ENTRY_HTML)) ! data->conversion = NORMAL; else ! switch (data->type_id) { case GOPHER_DIRECTORY: /* we got to convert it first */ BIT_SET(entry->flag, DELAY_SENDING); ! data->conversion = HTML_DIR; ! data->HTML_header_added = 0; break; case GOPHER_INDEX: /* we got to convert it first */ BIT_SET(entry->flag, DELAY_SENDING); ! data->conversion = HTML_INDEX_RESULT; ! data->HTML_header_added = 0; break; case GOPHER_CSO: /* we got to convert it first */ BIT_SET(entry->flag, DELAY_SENDING); ! data->conversion = HTML_CSO_RESULT; ! data->cso_recno = 0; ! data->HTML_header_added = 0; break; default: ! data->conversion = NORMAL; } /* Schedule read reply. */ comm_set_select_handler(fd, COMM_SELECT_READ, (PF) gopherReadReply, ! (void *) data); comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) gopherReadReplyTimeout, ! (void *) data, getReadTimeout()); comm_set_fd_lifetime(fd, -1); /* disable */ if (buf) put_free_4k_page(buf); /* Allocated by gopherSendRequest. */ ! data->icp_page_ptr = NULL; ! data->icp_rwd_ptr = NULL; } /* This will be called when connect completes. Write request. */ --- 753,806 ---- * OK. We successfully reach remote site. Start MIME typing * stuff. Do it anyway even though request is not HTML type. */ ! gopherMimeCreate(gopherState); if (!BIT_TEST(entry->flag, ENTRY_HTML)) ! gopherState->conversion = NORMAL; else ! switch (gopherState->type_id) { case GOPHER_DIRECTORY: /* we got to convert it first */ BIT_SET(entry->flag, DELAY_SENDING); ! gopherState->conversion = HTML_DIR; ! gopherState->HTML_header_added = 0; break; case GOPHER_INDEX: /* we got to convert it first */ BIT_SET(entry->flag, DELAY_SENDING); ! gopherState->conversion = HTML_INDEX_RESULT; ! gopherState->HTML_header_added = 0; break; case GOPHER_CSO: /* we got to convert it first */ BIT_SET(entry->flag, DELAY_SENDING); ! gopherState->conversion = HTML_CSO_RESULT; ! gopherState->cso_recno = 0; ! gopherState->HTML_header_added = 0; break; default: ! gopherState->conversion = NORMAL; } /* Schedule read reply. */ comm_set_select_handler(fd, COMM_SELECT_READ, (PF) gopherReadReply, ! (void *) gopherState); comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT, (PF) gopherReadReplyTimeout, ! (void *) gopherState, getReadTimeout()); comm_set_fd_lifetime(fd, -1); /* disable */ if (buf) put_free_4k_page(buf); /* Allocated by gopherSendRequest. */ ! gopherState->icp_page_ptr = NULL; } /* This will be called when connect completes. Write request. */ *************** *** 836,842 **** } debug(10, 5, "gopherSendRequest: FD %d\n", fd); ! data->icp_rwd_ptr = icpWrite(fd, buf, len, 30, --- 831,837 ---- } debug(10, 5, "gopherSendRequest: FD %d\n", fd); ! comm_write(fd, buf, len, 30, diff -N -c -r -X exclude_files squid-1.0.beta9/src/http.c squid-1.0.beta9.henrik/src/http.c *** squid-1.0.beta9/src/http.c Tue May 28 01:13:53 1996 --- squid-1.0.beta9.henrik/src/http.c Mon May 27 23:45:04 1996 *************** *** 23,30 **** put_free_8k_page(httpState->icp_page_ptr); httpState->icp_page_ptr = NULL; } - if (httpState->icp_rwd_ptr) - safe_free(httpState->icp_rwd_ptr); if (--httpState->request->link_count == 0) safe_free(httpState->request); xfree(httpState); --- 23,28 ---- *************** *** 379,391 **** /* This will be called when request write is complete. Schedule read of * reply. */ ! static void httpSendComplete(fd, buf, size, errflag, httpState) int fd; char *buf; int size; int errflag; ! HttpStateData *httpState; { StoreEntry *entry = NULL; entry = httpState->entry; --- 377,390 ---- /* This will be called when request write is complete. Schedule read of * reply. */ ! static void httpSendComplete(fd, buf, size, errflag, data) int fd; char *buf; int size; int errflag; ! void *data; { + HttpStateData *httpState=(HttpStateData *)data; StoreEntry *entry = NULL; entry = httpState->entry; *************** *** 397,403 **** buf = NULL; } httpState->icp_page_ptr = NULL; /* So lifetime expire doesn't re-free */ - httpState->icp_rwd_ptr = NULL; /* Don't double free in lifetimeexpire */ if (errflag) { squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror()); --- 396,401 ---- *************** *** 504,510 **** xfree(post_buf); } debug(11, 6, "httpSendRequest: FD %d: buf '%s'\n", fd, buf); ! httpState->icp_rwd_ptr = icpWrite(fd, buf, len, 30, --- 502,508 ---- xfree(post_buf); } debug(11, 6, "httpSendRequest: FD %d: buf '%s'\n", fd, buf); ! comm_write(fd, buf, len, 30, diff -N -c -r -X exclude_files squid-1.0.beta9/src/icp.c squid-1.0.beta9.henrik/src/icp.c *** squid-1.0.beta9/src/icp.c Tue May 28 01:13:56 1996 --- squid-1.0.beta9.henrik/src/icp.c Mon May 27 23:59:17 1996 *************** *** 70,88 **** static icpUdpData *UdpQueueTail = NULL; #define ICP_SENDMOREDATA_BUF SM_PAGE_SIZE - typedef void (*complete_handler) _PARAMS((int fd, char *buf, int size, int errflag, void *data)); - typedef struct ireadd { - int fd; - char *buf; - long size; - long offset; - int timeout; /* XXX Not used at present. */ - time_t time; - complete_handler handler; - void *client_data; - int handle_immed; - } icpRWStateData; - #ifdef UDP_HIT_WITH_OBJ typedef struct { int fd; --- 70,75 ---- *************** *** 96,109 **** /* Local functions */ static void icpHandleStore _PARAMS((int, StoreEntry *, icpStateData *)); ! static void icpHandleStoreComplete _PARAMS((int, char *, int, int, icpStateData *)); static void icpHandleStoreIMS _PARAMS((int, StoreEntry *, icpStateData *)); ! static void icpHandleIMSComplete _PARAMS((int, char *, int, int, icpStateData *)); static int icpProcessHIT _PARAMS((int, icpStateData *)); static int icpProcessIMS _PARAMS((int, icpStateData *)); static int icpProcessMISS _PARAMS((int, icpStateData *)); static void CheckQuickAbort _PARAMS((icpStateData *)); - static void icpRead _PARAMS((int, int, char *, int, int, int, complete_handler, void *)); #ifdef UDP_HIT_WITH_OBJ static void icpHitObjHandler _PARAMS((int, void *)); #endif --- 83,95 ---- /* Local functions */ static void icpHandleStore _PARAMS((int, StoreEntry *, icpStateData *)); ! static void icpHandleStoreComplete _PARAMS((int, char *, int, int, void *icpState)); static void icpHandleStoreIMS _PARAMS((int, StoreEntry *, icpStateData *)); ! static void icpHandleIMSComplete _PARAMS((int, char *, int, int, void *icpState)); static int icpProcessHIT _PARAMS((int, icpStateData *)); static int icpProcessIMS _PARAMS((int, icpStateData *)); static int icpProcessMISS _PARAMS((int, icpStateData *)); static void CheckQuickAbort _PARAMS((icpStateData *)); #ifdef UDP_HIT_WITH_OBJ static void icpHitObjHandler _PARAMS((int, void *)); #endif *************** *** 240,439 **** return 1; } ! /* Read from FD. */ ! static int icpHandleRead(fd, icpRWState) ! int fd; ! icpRWStateData *icpRWState; ! { ! int len; ! ! len = read(fd, icpRWState->buf + icpRWState->offset, icpRWState->size - icpRWState->offset); ! debug(12, 5, "icpHandleRead: FD %d: read %d bytes\n", fd, len); ! ! if (len <= 0) { ! switch (errno) { ! #if EAGAIN != EWOULDBLOCK ! case EAGAIN: ! #endif ! case EWOULDBLOCK: ! /* reschedule self */ ! comm_set_select_handler(fd, ! COMM_SELECT_READ, ! (PF) icpHandleRead, ! (void *) icpRWState); ! return COMM_OK; ! default: ! /* Len == 0 means connection closed; otherwise would not have been ! * called by comm_select(). */ ! debug(12, 1, "icpHandleRead: FD %d: read failure: %s\n", ! fd, len == 0 ? "connection closed" : xstrerror()); ! icpRWState->handler(fd, ! icpRWState->buf, ! icpRWState->offset, ! COMM_ERROR, ! icpRWState->client_data); ! safe_free(icpRWState); ! return COMM_ERROR; ! } ! } ! icpRWState->offset += len; ! ! /* Check for \r\n delimiting end of ascii transmission, or */ ! /* if we've read content-length bytes already */ ! if (icpRWState->offset >= icpRWState->size || icpRWState->handle_immed) { ! icpRWState->handler(fd, ! icpRWState->buf, ! icpRWState->offset, ! COMM_OK, ! icpRWState->client_data); ! safe_free(icpRWState); ! } else { ! comm_set_select_handler(fd, ! COMM_SELECT_READ, ! (PF) icpHandleRead, ! (void *) icpRWState); ! } ! ! return COMM_OK; ! } ! ! /* Select for reading on FD, until SIZE bytes are received. Call ! * HANDLER when complete. */ ! static void icpRead(fd, bin_mode, buf, size, timeout, immed, handler, client_data) ! int fd; ! int bin_mode; ! char *buf; ! int size; ! int timeout; ! int immed; ! void (*handler) _PARAMS((int fd, char *buf, int size, int errflag, void *data)); ! void *client_data; ! { ! icpRWStateData *data = NULL; ! data = xcalloc(1, sizeof(icpRWStateData)); ! data->fd = fd; ! data->buf = buf; ! data->size = size; ! data->offset = 0; ! data->handler = handler; ! data->timeout = timeout; ! data->handle_immed = immed; ! data->time = squid_curtime; ! data->client_data = client_data; ! comm_set_select_handler(fd, ! COMM_SELECT_READ, ! (PF) icpHandleRead, ! (void *) data); ! } ! ! /* Write to FD. */ ! static void icpHandleWrite(fd, icpRWState) ! int fd; ! icpRWStateData *icpRWState; ! { ! int len = 0; ! int nleft; ! ! debug(12, 5, "icpHandleWrite: FD %d: off %d: sz %d.\n", ! fd, icpRWState->offset, icpRWState->size); ! ! nleft = icpRWState->size - icpRWState->offset; ! len = write(fd, icpRWState->buf + icpRWState->offset, nleft); ! ! if (len == 0) { ! /* We're done */ ! if (nleft != 0) ! debug(12, 2, "icpHandleWrite: FD %d: write failure: connection closed with %d bytes remaining.\n", fd, nleft); ! icpRWState->handler(fd, ! icpRWState->buf, ! icpRWState->offset, ! nleft == 0 ? COMM_OK : COMM_ERROR, ! icpRWState->client_data); ! safe_free(icpRWState); ! return; ! } ! if (len < 0) { ! /* An error */ ! if (errno == EWOULDBLOCK || errno == EAGAIN) { ! /* XXX: Re-install the handler rather than giving up. I hope ! * this doesn't freeze this socket due to some random OS bug ! * returning EWOULDBLOCK indefinitely. Ought to maintain a ! * retry count in icpRWState? */ ! debug(12, 10, "icpHandleWrite: FD %d: write failure: %s.\n", ! fd, xstrerror()); ! comm_set_select_handler(fd, ! COMM_SELECT_WRITE, ! (PF) icpHandleWrite, ! (void *) icpRWState); ! return; ! } ! debug(12, 2, "icpHandleWrite: FD %d: write failure: %s.\n", ! fd, xstrerror()); ! icpRWState->handler(fd, ! icpRWState->buf, ! icpRWState->offset, ! COMM_ERROR, ! icpRWState->client_data); ! safe_free(icpRWState); ! return; ! } ! /* A successful write, continue */ ! icpRWState->offset += len; ! if (icpRWState->offset < icpRWState->size) { ! /* Reinstall the read handler and write some more */ ! comm_set_select_handler(fd, ! COMM_SELECT_WRITE, ! (PF) icpHandleWrite, ! (void *) icpRWState); ! return; ! } ! icpRWState->handler(fd, ! icpRWState->buf, ! icpRWState->offset, ! COMM_OK, ! icpRWState->client_data); ! safe_free(icpRWState); ! } ! ! ! ! /* Select for Writing on FD, until SIZE bytes are sent. Call ! * HANDLER when complete. */ ! char *icpWrite(fd, buf, size, timeout, handler, client_data) ! int fd; ! char *buf; ! int size; ! int timeout; ! void (*handler) _PARAMS((int fd, char *buf, int size, int errflag, void *data)); ! void *client_data; ! { ! icpRWStateData *data = NULL; ! ! debug(12, 5, "icpWrite: FD %d: sz %d: tout %d: hndl %p: data %p.\n", ! fd, size, timeout, handler, client_data); ! ! data = xcalloc(1, sizeof(icpRWStateData)); ! data->fd = fd; ! data->buf = buf; ! data->size = size; ! data->offset = 0; ! data->handler = handler; ! data->timeout = timeout; ! data->time = squid_curtime; ! data->client_data = client_data; ! comm_set_select_handler(fd, ! COMM_SELECT_WRITE, ! (PF) icpHandleWrite, ! (void *) data); ! return ((char *) data); ! } ! ! static void icpSendERRORComplete(fd, buf, size, errflag, icpState) int fd; char *buf; int size; int errflag; ! icpStateData *icpState; { debug(12, 4, "icpSendERRORComplete: FD %d: sz %d: err %d.\n", fd, size, errflag); --- 226,237 ---- return 1; } ! static void icpSendERRORComplete(fd, buf, size, errflag, data) int fd; char *buf; int size; int errflag; ! void *data; { debug(12, 4, "icpSendERRORComplete: FD %d: sz %d: err %d.\n", fd, size, errflag); *************** *** 476,482 **** icpState->buf = NULL; strcpy(buf, msg); *(buf + buf_len) = '\0'; ! icpWrite(fd, buf, buf_len, 30, icpSendERRORComplete, (void *) icpState); return COMM_OK; } --- 274,280 ---- icpState->buf = NULL; strcpy(buf, msg); *(buf + buf_len) = '\0'; ! comm_write(fd, buf, buf_len, 30, icpSendERRORComplete, (void *) icpState); return COMM_OK; } *************** *** 545,551 **** /* Do this here, so HandleStoreComplete can tell whether more data * needs to be sent. */ ! icpWrite(fd, buf, buf_len, 30, icpHandleStoreComplete, (void *) icpState); result = COMM_OK; return result; } --- 343,349 ---- /* Do this here, so HandleStoreComplete can tell whether more data * needs to be sent. */ ! comm_write(fd, buf, buf_len, 30, icpHandleStoreComplete, (void *) icpState); result = COMM_OK; return result; } *************** *** 578,590 **** icpSendMoreData(fd, icpState); } ! static void icpHandleStoreComplete(fd, buf, size, errflag, icpState) int fd; char *buf; int size; int errflag; ! icpStateData *icpState; { StoreEntry *entry = NULL; entry = icpState->entry; --- 376,389 ---- icpSendMoreData(fd, icpState); } ! static void icpHandleStoreComplete(fd, buf, size, errflag, data) int fd; char *buf; int size; int errflag; ! void *data; { + icpStateData *icpState=(icpStateData *)data; StoreEntry *entry = NULL; entry = icpState->entry; *************** *** 701,707 **** /* The object is not modified */ debug(12,4,"icpGetHeadersForIMS: Not modified '%s'\n",entry->url); strcpy(buf,"HTTP/1.0 304 Not modified\n\r\n\r"); ! icpWrite(fd, "HTTP/1.0 304 Not modified\r\n\r\n", strlen("HTTP/1.0 304 Not modified\r\n\r\n"), 30, icpHandleIMSComplete, (void *) icpState); return COMM_OK; } else { debug(12,4,"icpGetHeadersForIMS: We have newer '%s'\n",entry->url); --- 500,506 ---- /* The object is not modified */ debug(12,4,"icpGetHeadersForIMS: Not modified '%s'\n",entry->url); strcpy(buf,"HTTP/1.0 304 Not modified\n\r\n\r"); ! comm_write(fd, "HTTP/1.0 304 Not modified\r\n\r\n", strlen("HTTP/1.0 304 Not modified\r\n\r\n"), 30, icpHandleIMSComplete, (void *) icpState); return COMM_OK; } else { debug(12,4,"icpGetHeadersForIMS: We have newer '%s'\n",entry->url); *************** *** 718,730 **** icpGetHeadersForIMS(fd,icpState); } ! static void icpHandleIMSComplete(fd, buf, size, errflag, icpState) int fd; char *buf; int size; int errflag; ! icpStateData *icpState; { StoreEntry *entry = icpState->entry; debug(12,5,"icpHandleIMSComplete: Not Modified sent '%s'\n",entry->url); --- 517,530 ---- icpGetHeadersForIMS(fd,icpState); } ! static void icpHandleIMSComplete(fd, buf, size, errflag, data) int fd; char *buf; int size; int errflag; ! void *data; { + icpStateData *icpState=(icpStateData *)data; StoreEntry *entry = icpState->entry; debug(12,5,"icpHandleIMSComplete: Not Modified sent '%s'\n",entry->url); *************** *** 1601,1613 **** * icp_hit_or_miss() * icpSendERROR() */ ! static void asciiProcessInput(fd, buf, size, flag, icpState) int fd; char *buf; int size; int flag; ! icpStateData *icpState; { static char client_msg[64]; int parser_return_code = 0; int k; --- 1401,1414 ---- * icp_hit_or_miss() * icpSendERROR() */ ! static void asciiProcessInput(fd, buf, size, flag, data) int fd; char *buf; int size; int flag; ! void *data; { + icpStateData *icpState=(icpStateData *)data; static char client_msg[64]; int parser_return_code = 0; int k; *************** *** 1636,1642 **** icpState->http_code, NULL)); icpState->ptr_to_4k_page = NULL; ! icpWrite(fd, icpState->buf, strlen(icpState->buf), 30, --- 1437,1443 ---- icpState->http_code, NULL)); icpState->ptr_to_4k_page = NULL; ! comm_write(fd, icpState->buf, strlen(icpState->buf), 30, *************** *** 1654,1660 **** icpState->url, fd_table[fd].ipaddr)); icpState->ptr_to_4k_page = NULL; ! icpWrite(fd, icpState->buf, strlen(tmp_error_buf), 30, --- 1455,1461 ---- icpState->url, fd_table[fd].ipaddr)); icpState->ptr_to_4k_page = NULL; ! comm_write(fd, icpState->buf, strlen(tmp_error_buf), 30, *************** *** 1700,1712 **** icpState->offset, icpState->inbufsize); k = icpState->inbufsize - 1 - icpState->offset; } ! icpRead(fd, ! FALSE, icpState->inbuf + icpState->offset, k, /* size */ 30, /* timeout */ TRUE, /* handle immed */ ! (complete_handler) asciiProcessInput, (void *) icpState); } else { /* parser returned -1 */ --- 1501,1512 ---- icpState->offset, icpState->inbufsize); k = icpState->inbufsize - 1 - icpState->offset; } ! comm_read(fd, icpState->inbuf + icpState->offset, k, /* size */ 30, /* timeout */ TRUE, /* handle immed */ ! asciiProcessInput, (void *) icpState); } else { /* parser returned -1 */ *************** *** 1717,1723 **** ERR_INVALID_REQ, fd_table[fd].ipaddr, icpState->http_code)); ! icpWrite(fd, icpState->buf, strlen(icpState->buf), 30, --- 1517,1523 ---- ERR_INVALID_REQ, fd_table[fd].ipaddr, icpState->http_code)); ! comm_write(fd, icpState->buf, strlen(icpState->buf), 30, *************** *** 1729,1770 **** /* general lifetime handler for ascii connection */ ! static void asciiConnLifetimeHandle(fd, data) int fd; ! void *data; { - icpStateData *icpState = (icpStateData *) data; - PF handler; - void *client_data; - icpRWStateData *icpRWState = NULL; StoreEntry *entry = icpState->entry; debug(12, 2, "asciiConnLifetimeHandle: Socket: %d lifetime is expired. Free up data structure.\n", fd); - /* If we were in the middle of an icpWrite we're going to need - * to deallocate the icpReadWrite state data. */ - handler = NULL; - client_data = NULL; - comm_get_select_handler(fd, - COMM_SELECT_WRITE, - &handler, - (void **) &client_data); - if (handler == (PF) icpHandleWrite && client_data != NULL) { - icpRWState = (icpRWStateData *) client_data; - safe_free(icpRWState); - } - /* If we were in the middle of an icpRead we're going to need - * to deallocate the icpReadWrite state data. */ - handler = NULL; - client_data = NULL; - comm_get_select_handler(fd, - COMM_SELECT_READ, - &handler, - (void **) &client_data); - if (handler == icpHandleRead && client_data != NULL) { - icpRWState = (icpRWStateData *) client_data; - safe_free(icpRWState); - } CheckQuickAbort(icpState); if (entry && icpState->url) /* Unregister us from the dnsserver pending list and cause a DNS --- 1529,1542 ---- /* general lifetime handler for ascii connection */ ! static void asciiConnLifetimeHandle(fd, icpState) int fd; ! icpStateData *icpState; { StoreEntry *entry = icpState->entry; debug(12, 2, "asciiConnLifetimeHandle: Socket: %d lifetime is expired. Free up data structure.\n", fd); CheckQuickAbort(icpState); if (entry && icpState->url) /* Unregister us from the dnsserver pending list and cause a DNS *************** *** 1815,1827 **** COMM_SELECT_CLOSE, (PF) icpStateFree, (void *) icpState); ! icpRead(fd, ! FALSE, icpState->inbuf, icpState->inbufsize - 1, /* size */ 30, /* timeout */ 1, /* handle immed */ ! (complete_handler) asciiProcessInput, (void *) icpState); comm_set_select_handler(sock, COMM_SELECT_READ, --- 1587,1598 ---- COMM_SELECT_CLOSE, (PF) icpStateFree, (void *) icpState); ! comm_read(fd, icpState->inbuf, icpState->inbufsize - 1, /* size */ 30, /* timeout */ 1, /* handle immed */ ! asciiProcessInput, (void *) icpState); comm_set_select_handler(sock, COMM_SELECT_READ, diff -N -c -r -X exclude_files squid-1.0.beta9/src/wais.c squid-1.0.beta9.henrik/src/wais.c *** squid-1.0.beta9/src/wais.c Tue May 28 01:13:57 1996 --- squid-1.0.beta9.henrik/src/wais.c Mon May 27 23:35:55 1996 *************** *** 214,220 **** else sprintf(buf, "%s %s\r\n", Method, data->request); debug(24, 6, "waisSendRequest - buf:%s\n", buf); ! icpWrite(fd, buf, len, 30, --- 214,220 ---- else sprintf(buf, "%s %s\r\n", Method, data->request); debug(24, 6, "waisSendRequest - buf:%s\n", buf); ! comm_write(fd, buf, len, 30,