Index: squid/src/HttpRequest.c diff -c squid/src/HttpRequest.c:1.30 squid/src/HttpRequest.c:1.30.2.2 *** squid/src/HttpRequest.c:1.30 Fri Apr 13 18:25:17 2001 --- squid/src/HttpRequest.c Thu Oct 7 11:01:13 2004 *************** *** 55,62 **** requestDestroy(request_t * req) { assert(req); ! if (req->body_connection) ! clientAbortBody(req); if (req->auth_user_request) authenticateAuthUserRequestUnlock(req->auth_user_request); safe_free(req->canonical); --- 55,62 ---- requestDestroy(request_t * req) { assert(req); ! if (req->body_reader) ! requestAbortBody(req); if (req->auth_user_request) authenticateAuthUserRequestUnlock(req->auth_user_request); safe_free(req->canonical); *************** *** 158,160 **** --- 158,198 ---- return 0; return 1; } + + /* + * Read request body contents + */ + void + requestReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata) + { + if (request->body_reader) { + if (cbdataValid(request->body_reader_data)) { + request->body_reader(request, buf, size, callback, cbdata); + } else { + debug(73, 1) ("requestReadBody: Aborted\n"); + request->body_reader = NULL; + cbdataUnlock(request->body_reader_data); + request->body_reader_data = NULL; + callback(buf, 0, cbdata); /* Signal end of body */ + } + } else { + callback(buf, 0, cbdata); /* Signal end of body */ + } + } + + void + requestAbortBody(request_t * request) + { + if (!request) + return; + if (request->body_reader) { + if (cbdataValid(request->body_reader_data)) { + request->body_reader(request, NULL, -1, NULL, NULL); + } else { + debug(73, 2) ("requestAbortBody: Aborted\n"); + request->body_reader = NULL; + cbdataUnlock(request->body_reader_data); + request->body_reader_data = NULL; + } + } + } Index: squid/src/client_side.c diff -c squid/src/client_side.c:1.561.2.59 squid/src/client_side.c:1.561.2.60 *** squid/src/client_side.c:1.561.2.59 Mon Sep 27 12:17:38 2004 --- squid/src/client_side.c Tue Oct 5 16:34:42 2004 *************** *** 129,134 **** --- 129,136 ---- static int clientRequestBodyTooLarge(int clen); static void clientProcessBody(ConnStateData * conn); static void clientEatRequestBody(clientHttpRequest *); + static BODY_HANDLER clientReadBody; + static void clientAbortBody(request_t * req); static int checkAccelOnly(clientHttpRequest * http) *************** *** 360,368 **** new_request->auth_user_request = old_request->auth_user_request; authenticateAuthUserRequestLock(new_request->auth_user_request); } ! if (old_request->body_connection) { ! new_request->body_connection = old_request->body_connection; ! old_request->body_connection = NULL; } new_request->content_length = old_request->content_length; new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive; --- 362,372 ---- new_request->auth_user_request = old_request->auth_user_request; authenticateAuthUserRequestLock(new_request->auth_user_request); } ! if (old_request->body_reader) { ! new_request->body_reader = old_request->body_reader; ! new_request->body_reader_data = old_request->body_reader_data; ! old_request->body_reader = NULL; ! old_request->body_reader_data = NULL; } new_request->content_length = old_request->content_length; new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive; *************** *** 813,822 **** MemObject *mem = NULL; debug(33, 3) ("httpRequestFree: %s\n", storeUrl(http->entry)); if (!clientCheckTransferDone(http)) { ! if (request && request->body_connection) { ! clientAbortBody(request); /* abort request body transter */ ! request->body_connection = NULL; ! } /* HN: This looks a bit odd.. why should client_side care about * the ICP selection status? */ --- 817,823 ---- MemObject *mem = NULL; debug(33, 3) ("httpRequestFree: %s\n", storeUrl(http->entry)); if (!clientCheckTransferDone(http)) { ! requestAbortBody(request); /* abort request body transter */ /* HN: This looks a bit odd.. why should client_side care about * the ICP selection status? */ *************** *** 2220,2226 **** } else if (clientGotNotEnough(http)) { debug(33, 5) ("clientWriteComplete: client didn't get all it expected\n"); comm_close(fd); ! } else if (http->request->body_connection) { debug(33, 5) ("clientWriteComplete: closing, but first we need to read the rest of the request\n"); /* XXX We assumes the reply does fit in the TCP transmit window. * If not the connection may stall while sending the reply --- 2221,2227 ---- } else if (clientGotNotEnough(http)) { debug(33, 5) ("clientWriteComplete: client didn't get all it expected\n"); comm_close(fd); ! } else if (http->request->body_reader == clientReadBody) { debug(33, 5) ("clientWriteComplete: closing, but first we need to read the rest of the request\n"); /* XXX We assumes the reply does fit in the TCP transmit window. * If not the connection may stall while sending the reply *************** *** 3112,3118 **** /* Do we expect a request-body? */ if (request->content_length> 0) { conn->body.size_left = request->content_length; ! request->body_connection = conn; /* Is it too large? */ if (clientRequestBodyTooLarge(request->content_length)) { err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE); --- 3113,3121 ---- /* Do we expect a request-body? */ if (request->content_length> 0) { conn->body.size_left = request->content_length; ! request->body_reader = clientReadBody; ! request->body_reader_data = conn; ! cbdataLock(conn); /* Is it too large? */ if (clientRequestBodyTooLarge(request->content_length)) { err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE); *************** *** 3168,3182 **** } /* file_read like function, for reading body content */ ! void clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata) { ! ConnStateData *conn = request->body_connection; if (!conn) { debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request); callback(buf, 0, cbdata); /* Signal end of body */ return; } debug(33, 2) ("clientReadBody: start fd=%d body_size=%lu in.offset=%ld cb=%p req=%p\n", conn->fd, (unsigned long int) conn->body.size_left, (long int) conn->in.offset, callback, request); conn->body.callback = callback; conn->body.cbdata = cbdata; --- 3171,3190 ---- } /* file_read like function, for reading body content */ ! static void clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata) { ! ConnStateData *conn = request->body_reader_data; ! if (!callback) { ! clientAbortBody(request); ! return; ! } if (!conn) { debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request); callback(buf, 0, cbdata); /* Signal end of body */ return; } + assert(cbdataValid(conn)); debug(33, 2) ("clientReadBody: start fd=%d body_size=%lu in.offset=%ld cb=%p req=%p\n", conn->fd, (unsigned long int) conn->body.size_left, (long int) conn->in.offset, callback, request); conn->body.callback = callback; conn->body.cbdata = cbdata; *************** *** 3218,3224 **** ConnStateData *conn = http->conn; cbdataLock(conn); if (conn->body.request) ! clientAbortBody(conn->body.request); if (cbdataValid(conn)) clientEatRequestBodyHandler(NULL, -1, http); cbdataUnlock(conn); --- 3226,3232 ---- ConnStateData *conn = http->conn; cbdataLock(conn); if (conn->body.request) ! requestAbortBody(conn->body.request); if (cbdataValid(conn)) clientEatRequestBodyHandler(NULL, -1, http); cbdataUnlock(conn); *************** *** 3261,3268 **** xmemmove(conn->in.buf, conn->in.buf + size, conn->in.offset); /* Remove request link if this is the last part of the body, as * clientReadRequest automatically continues to process next request */ ! if (conn->body.size_left <= 0 && request != NULL) ! request->body_connection = NULL; /* Remove clientReadBody arguments (the call is completed) */ conn->body.request = NULL; conn->body.callback = NULL; --- 3269,3280 ---- xmemmove(conn->in.buf, conn->in.buf + size, conn->in.offset); /* Remove request link if this is the last part of the body, as * clientReadRequest automatically continues to process next request */ ! if (conn->body.size_left <= 0 && request != NULL) { ! request->body_reader = NULL; ! if (request->body_reader_data) ! cbdataUnlock(request->body_reader_data); ! request->body_reader_data = NULL; ! } /* Remove clientReadBody arguments (the call is completed) */ conn->body.request = NULL; conn->body.callback = NULL; *************** *** 3283,3296 **** } /* Abort a body request */ ! void clientAbortBody(request_t * request) { ! ConnStateData *conn = request->body_connection; char *buf; CBCB *callback; void *cbdata; int valid; if (!conn->body.callback || conn->body.request != request) return; buf = conn->body.buf; --- 3295,3310 ---- } /* Abort a body request */ ! static void clientAbortBody(request_t * request) { ! ConnStateData *conn = request->body_reader_data; char *buf; CBCB *callback; void *cbdata; int valid; + if (!cbdataValid(conn)) + return; if (!conn->body.callback || conn->body.request != request) return; buf = conn->body.buf; Index: squid/src/forward.c diff -c squid/src/forward.c:1.82.2.12 squid/src/forward.c:1.82.2.13 *** squid/src/forward.c:1.82.2.12 Wed Feb 18 06:44:55 2004 --- squid/src/forward.c Tue Oct 5 16:34:42 2004 *************** *** 152,158 **** /* If there is a request body then Squid can only try once * even if the method is indempotent */ ! if (fwdState->request->body_connection) return 0; /* RFC2616 9.1 Safe and Idempotent Methods */ --- 152,158 ---- /* If there is a request body then Squid can only try once * even if the method is indempotent */ ! if (fwdState->request->body_reader) return 0; /* RFC2616 9.1 Safe and Idempotent Methods */ Index: squid/src/ftp.c diff -c squid/src/ftp.c:1.316.2.14 squid/src/ftp.c:1.316.2.15 *** squid/src/ftp.c:1.316.2.14 Mon May 31 17:14:37 2004 --- squid/src/ftp.c Tue Oct 5 16:34:42 2004 *************** *** 2309,2315 **** return; if (!err) { /* Shedule the rest of the request */ ! clientReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } else { debug(9, 1) ("ftpDataWriteCallback: write error: %s\n", xstrerror()); ftpFailed(ftpState, ERR_WRITE_ERROR); --- 2309,2315 ---- return; if (!err) { /* Shedule the rest of the request */ ! requestReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } else { debug(9, 1) ("ftpDataWriteCallback: write error: %s\n", xstrerror()); ftpFailed(ftpState, ERR_WRITE_ERROR); *************** *** 2322,2328 **** FtpStateData *ftpState = (FtpStateData *) data; debug(9, 3) ("ftpDataWrite\n"); /* This starts the body transfer */ ! clientReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } static void --- 2322,2328 ---- FtpStateData *ftpState = (FtpStateData *) data; debug(9, 3) ("ftpDataWrite\n"); /* This starts the body transfer */ ! requestReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } static void Index: squid/src/http.c diff -c squid/src/http.c:1.384.2.17 squid/src/http.c:1.384.2.18 *** squid/src/http.c:1.384.2.17 Tue Oct 5 15:31:26 2004 --- squid/src/http.c Tue Oct 5 16:34:42 2004 *************** *** 65,73 **** if (httpState == NULL) return; if (httpState->body_buf) { ! if (httpState->orig_request->body_connection) { ! clientAbortBody(httpState->orig_request); ! } if (httpState->body_buf) { memFree(httpState->body_buf, MEM_8K_BUF); httpState->body_buf = NULL; --- 65,71 ---- if (httpState == NULL) return; if (httpState->body_buf) { ! requestAbortBody(httpState->orig_request); if (httpState->body_buf) { memFree(httpState->body_buf, MEM_8K_BUF); httpState->body_buf = NULL; *************** *** 1033,1039 **** commSetTimeout(fd, Config.Timeout.lifetime, httpTimeout, httpState); commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); ! if (httpState->orig_request->body_connection) sendHeaderDone = httpSendRequestEntry; else sendHeaderDone = httpSendComplete; --- 1031,1037 ---- commSetTimeout(fd, Config.Timeout.lifetime, httpTimeout, httpState); commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); ! if (httpState->orig_request->body_reader) sendHeaderDone = httpSendRequestEntry; else sendHeaderDone = httpSendComplete; *************** *** 1219,1225 **** return; } httpState->body_buf = memAllocate(MEM_8K_BUF); ! clientReadBody(httpState->orig_request, httpState->body_buf, 8192, httpRequestBodyHandler, httpState); } void --- 1217,1223 ---- return; } httpState->body_buf = memAllocate(MEM_8K_BUF); ! requestReadBody(httpState->orig_request, httpState->body_buf, 8192, httpRequestBodyHandler, httpState); } void Index: squid/src/protos.h diff -c squid/src/protos.h:1.420.2.24 squid/src/protos.h:1.420.2.25 *** squid/src/protos.h:1.420.2.24 Tue Oct 5 15:31:26 2004 --- squid/src/protos.h Tue Oct 5 16:34:42 2004 *************** *** 141,148 **** extern void clientHttpConnectionsClose(void); extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags); extern int isTcpHit(log_type); - extern void clientReadBody(request_t * req, char *buf, size_t size, CBCB * callback, void *data); - extern void clientAbortBody(request_t * req); extern int commSetNonBlocking(int fd); extern int commUnsetNonBlocking(int fd); --- 141,146 ---- *************** *** 519,524 **** --- 517,524 ---- extern int httpRequestPrefixLen(const request_t * req); extern int httpRequestHdrAllowed(const HttpHeaderEntry * e, String * strConnection); extern int httpRequestHdrAllowedByName(http_hdr_type id); + extern void requestReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata); + extern void requestAbortBody(request_t * request); extern void icmpOpen(void); extern void icmpClose(void); Index: squid/src/structs.h diff -c squid/src/structs.h:1.408.2.28 squid/src/structs.h:1.408.2.30 *** squid/src/structs.h:1.408.2.28 Tue Oct 5 15:31:27 2004 --- squid/src/structs.h Tue Oct 5 16:56:36 2004 *************** *** 1672,1684 **** struct in_addr my_addr; unsigned short my_port; HttpHeader header; - ConnStateData *body_connection; /* used by clientReadBody() */ int content_length; HierarchyLogEntry hier; err_type err_type; char *peer_login; /* Configured peer login:password */ time_t lastmod; /* Used on refreshes */ const char *vary_headers; /* Used when varying entities are detected. Changes how the store key is calculated */ }; struct _cachemgr_passwd { --- 1672,1685 ---- struct in_addr my_addr; unsigned short my_port; HttpHeader header; int content_length; HierarchyLogEntry hier; err_type err_type; char *peer_login; /* Configured peer login:password */ time_t lastmod; /* Used on refreshes */ const char *vary_headers; /* Used when varying entities are detected. Changes how the store key is calculated */ + BODY_HANDLER *body_reader; + void *body_reader_data; }; struct _cachemgr_passwd { Index: squid/src/typedefs.h diff -c squid/src/typedefs.h:1.132.2.5 squid/src/typedefs.h:1.132.2.6 *** squid/src/typedefs.h:1.132.2.5 Sat Sep 25 05:56:16 2004 --- squid/src/typedefs.h Tue Oct 5 16:34:42 2004 *************** *** 236,241 **** --- 236,242 ---- typedef int READ_HANDLER(int, char *, int); typedef int WRITE_HANDLER(int, const char *, int); typedef void CBCB(char *buf, ssize_t size, void *data); + typedef void BODY_HANDLER(request_t * req, char *, size_t, CBCB *, void *); typedef void STIOCB(void *their_data, int errflag, storeIOState *); typedef void STFNCB(void *their_data, int errflag, storeIOState *);