Loading CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,10 @@ Changelog Daniel (23 October 2006) - Ravi Pratap provided a major update with pipelining fixes. We also no longer re-use connections (for pipelining) before the name resolving is done. Daniel (21 October 2006) - Nir Soffer made the tests/libtest/Makefile.am use a proper variable for all the single test applications' link and dependences, so that you easier can Loading lib/multi.c +2 −1 Original line number Diff line number Diff line Loading @@ -773,7 +773,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, return CURLM_BAD_EASY_HANDLE; if (easy->easy_handle->state.pipe_broke) { infof(easy->easy_handle, "Pipe broke: handle 0x%x\n", easy); infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n", easy, easy->easy_handle->reqdata.path); if(easy->easy_handle->state.is_in_pipeline) { /* Head back to the CONNECT state */ multistate(easy, CURLM_STATE_CONNECT); Loading lib/sendf.c +40 −29 Original line number Diff line number Diff line Loading @@ -438,14 +438,25 @@ CURLcode Curl_client_write(struct connectdata *conn, return CURLE_OK; } #define MIN(a,b) (a < b ? a : b) void Curl_read_rewind(struct connectdata *conn, size_t extraBytesRead) { char buf[512 + 1]; size_t bytesToShow; conn->read_pos -= extraBytesRead; conn->bits.stream_was_rewound = TRUE; } #define MIN(a,b) (a < b ? a : b) bytesToShow = MIN(conn->buf_len - conn->read_pos, sizeof(buf)-1); memcpy(buf, conn->master_buffer + conn->read_pos, bytesToShow); buf[bytesToShow] = '\0'; DEBUGF(infof(conn->data, "Buffer after stream rewind (read_pos = %d): [%s]", conn->read_pos, buf)); } /* * Internal read-from-socket function. This is meant to deal with plain Loading @@ -457,12 +468,12 @@ void Curl_read_rewind(struct connectdata *conn, int Curl_read(struct connectdata *conn, /* connection data */ curl_socket_t sockfd, /* read from this socket */ char *buf, /* store read data here */ size_t buffersize, /* max amount to read */ size_t sizerequested, /* max amount to read */ ssize_t *n) /* amount bytes read */ { ssize_t nread; size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, buffersize); size_t bytesremaining = buffersize - bytestocopy; size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested); size_t bytesfromsocket = 0; /* Set 'num' to 0 or 1, depending on which socket that has been sent here. If it is the second socket, we set num to 1. Otherwise to 0. This lets Loading @@ -471,34 +482,34 @@ int Curl_read(struct connectdata *conn, /* connection data */ *n=0; /* reset amount to zero */ bytesremaining = MIN(bytesremaining, sizeof(conn->master_buffer)); /* Copy from our master buffer first */ /* Copy from our master buffer first if we have some unread data there*/ if (bytestocopy > 0) { memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); conn->read_pos += bytestocopy; conn->bits.stream_was_rewound = FALSE; *n = (ssize_t)bytestocopy; if (bytesremaining == 0) { return CURLE_OK; } /* If we come here, it means that there is no data to read from the buffer, * so we read from the socket */ bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer)); if(conn->ssl[num].use) { nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesremaining); nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesfromsocket); if(nread == -1 && bytestocopy == 0) { if(nread == -1) return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */ } } else { else { if(conn->sec_complete) nread = Curl_sec_read(conn, sockfd, conn->master_buffer, bytesremaining); nread = Curl_sec_read(conn, sockfd, conn->master_buffer, bytesfromsocket); else nread = sread(sockfd, conn->master_buffer, bytesremaining); nread = sread(sockfd, conn->master_buffer, bytesfromsocket); if(-1 == nread && bytestocopy == 0) { if(-1 == nread) { int err = Curl_sockerrno(); #ifdef USE_WINSOCK if(WSAEWOULDBLOCK == err) Loading @@ -509,12 +520,12 @@ int Curl_read(struct connectdata *conn, /* connection data */ } } if (nread > 0) { if (nread >= 0) { memcpy(buf, conn->master_buffer, nread); conn->buf_len = nread; conn->read_pos = nread; *n += nread; *n = nread; } return CURLE_OK; Loading lib/transfer.c +16 −10 Original line number Diff line number Diff line Loading @@ -743,8 +743,10 @@ CURLcode Curl_readwrite(struct connectdata *conn, failf(data, "Maximum file size exceeded"); return CURLE_FILESIZE_EXCEEDED; } if(contentlength >= 0) if(contentlength >= 0) { k->size = contentlength; k->maxdownload = k->size; } else { /* Negative Content-Length is really odd, and we know it happens for example when older Apache servers send large Loading Loading @@ -1133,13 +1135,17 @@ CURLcode Curl_readwrite(struct connectdata *conn, if((-1 != k->maxdownload) && (k->bytecount + nread >= k->maxdownload)) { size_t excess = (size_t)(k->bytecount + (curl_off_t)nread - k->maxdownload); if (excess > 0) { infof(data, "Rewinding stream by : %d bytes\n", excess); curl_off_t excess = k->bytecount + ((curl_off_t) nread) - k->maxdownload; if (excess > 0 && !k->ignorebody) { infof(data, "Rewinding stream by : %" FORMAT_OFF_T " bytes on url %s (size = %" FORMAT_OFF_T ", maxdownload = %" FORMAT_OFF_T ", bytecount = %" FORMAT_OFF_T ", nread = %d)\n", excess, conn->data->reqdata.path, k->size, k->maxdownload, k->bytecount, nread); Curl_read_rewind(conn, excess); conn->bits.stream_was_rewound = TRUE; } nread = (ssize_t) (k->maxdownload - k->bytecount); Loading lib/url.c +40 −18 Original line number Diff line number Diff line Loading @@ -1854,6 +1854,7 @@ int Curl_removeHandleFromPipeline(struct SessionHandle *handle, } curr = curr->next; } return 0; } Loading Loading @@ -1899,8 +1900,8 @@ static void signalPipeClose(struct curl_llist *pipe) } else #endif data->state.pipe_broke = TRUE; data->state.pipe_broke = TRUE; Curl_llist_remove(pipe, curr, NULL); curr = next; } Loading Loading @@ -1936,12 +1937,19 @@ ConnectionExists(struct SessionHandle *data, /* NULL pointer means not filled-in entry */ continue; #ifdef USE_ARES /* ip_addr_str is NULL only if the resolving of the name hasn't completed yet and until then we don't re-use this connection */ if (!check->ip_addr_str) continue; #endif if(check->inuse && !canPipeline) /* can only happen within multi handles, and means that another easy handle is using this connection */ continue; if (check->send_pipe->size >= MAX_PIPELINE_LENGTH || if (check->send_pipe->size + check->recv_pipe->size >= MAX_PIPELINE_LENGTH) continue; Loading Loading @@ -1994,14 +2002,28 @@ ConnectionExists(struct SessionHandle *data, } if(match) { bool dead = SocketIsDead(check->sock[FIRSTSOCKET]); if(dead) { /* */ if (!check->is_in_pipeline) { check->data = data; infof(data, "Connection %d seems to be dead!\n", i); Curl_disconnect(check); /* disconnect resources */ data->state.connc->connects[i]=NULL; /* nothing here */ } else { /* In the pipelining case, freeing the connection right away * doesn't work. Instead, we mark the connection for close * so that the handles will detect this automatically when * they try to do something and deal with it there. * Prematurely freeing this connection prevents handles that * have already finished with their transfers to shut down * cleanly. */ infof(data, "Connection %d seems dead - marking for close\n", i); check->bits.close = TRUE; } /* There's no need to continue searching, because we only store one connection for each unique set of identifiers */ Loading @@ -2016,6 +2038,9 @@ ConnectionExists(struct SessionHandle *data, check->is_in_pipeline = TRUE; } check->connectindex = i; /* Set this appropriately since it might have been set to -1 when the easy was removed from the multi */ *usethis = check; return TRUE; /* yes, we found one to use! */ } Loading Loading @@ -2690,6 +2715,9 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->readchannel_inuse = FALSE; conn->writechannel_inuse = FALSE; conn->read_pos = 0; conn->buf_len = 0; /* Initialize the pipeline lists */ conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); Loading Loading @@ -3622,12 +3650,6 @@ static CURLcode CreateConnection(struct SessionHandle *data, infof(data, "Re-using existing connection! (#%ld) with host %s\n", conn->connectindex, conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname); #ifdef CURLRES_ASYNCH if(!conn->ip_addr_str) { infof(data, "... but it is not resolved yet!\n"); *async = TRUE; } #endif } else { /* Loading Loading @@ -3990,10 +4012,10 @@ CURLcode Curl_done(struct connectdata **connp, if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && conn->readchannel_inuse) conn->readchannel_inuse--; conn->readchannel_inuse = FALSE; if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && conn->writechannel_inuse) conn->writechannel_inuse--; conn->writechannel_inuse = FALSE; /* cleanups done even if the connection is re-used */ if(data->reqdata.rangestringalloc) { Loading Loading
CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,10 @@ Changelog Daniel (23 October 2006) - Ravi Pratap provided a major update with pipelining fixes. We also no longer re-use connections (for pipelining) before the name resolving is done. Daniel (21 October 2006) - Nir Soffer made the tests/libtest/Makefile.am use a proper variable for all the single test applications' link and dependences, so that you easier can Loading
lib/multi.c +2 −1 Original line number Diff line number Diff line Loading @@ -773,7 +773,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, return CURLM_BAD_EASY_HANDLE; if (easy->easy_handle->state.pipe_broke) { infof(easy->easy_handle, "Pipe broke: handle 0x%x\n", easy); infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n", easy, easy->easy_handle->reqdata.path); if(easy->easy_handle->state.is_in_pipeline) { /* Head back to the CONNECT state */ multistate(easy, CURLM_STATE_CONNECT); Loading
lib/sendf.c +40 −29 Original line number Diff line number Diff line Loading @@ -438,14 +438,25 @@ CURLcode Curl_client_write(struct connectdata *conn, return CURLE_OK; } #define MIN(a,b) (a < b ? a : b) void Curl_read_rewind(struct connectdata *conn, size_t extraBytesRead) { char buf[512 + 1]; size_t bytesToShow; conn->read_pos -= extraBytesRead; conn->bits.stream_was_rewound = TRUE; } #define MIN(a,b) (a < b ? a : b) bytesToShow = MIN(conn->buf_len - conn->read_pos, sizeof(buf)-1); memcpy(buf, conn->master_buffer + conn->read_pos, bytesToShow); buf[bytesToShow] = '\0'; DEBUGF(infof(conn->data, "Buffer after stream rewind (read_pos = %d): [%s]", conn->read_pos, buf)); } /* * Internal read-from-socket function. This is meant to deal with plain Loading @@ -457,12 +468,12 @@ void Curl_read_rewind(struct connectdata *conn, int Curl_read(struct connectdata *conn, /* connection data */ curl_socket_t sockfd, /* read from this socket */ char *buf, /* store read data here */ size_t buffersize, /* max amount to read */ size_t sizerequested, /* max amount to read */ ssize_t *n) /* amount bytes read */ { ssize_t nread; size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, buffersize); size_t bytesremaining = buffersize - bytestocopy; size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested); size_t bytesfromsocket = 0; /* Set 'num' to 0 or 1, depending on which socket that has been sent here. If it is the second socket, we set num to 1. Otherwise to 0. This lets Loading @@ -471,34 +482,34 @@ int Curl_read(struct connectdata *conn, /* connection data */ *n=0; /* reset amount to zero */ bytesremaining = MIN(bytesremaining, sizeof(conn->master_buffer)); /* Copy from our master buffer first */ /* Copy from our master buffer first if we have some unread data there*/ if (bytestocopy > 0) { memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); conn->read_pos += bytestocopy; conn->bits.stream_was_rewound = FALSE; *n = (ssize_t)bytestocopy; if (bytesremaining == 0) { return CURLE_OK; } /* If we come here, it means that there is no data to read from the buffer, * so we read from the socket */ bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer)); if(conn->ssl[num].use) { nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesremaining); nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesfromsocket); if(nread == -1 && bytestocopy == 0) { if(nread == -1) return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */ } } else { else { if(conn->sec_complete) nread = Curl_sec_read(conn, sockfd, conn->master_buffer, bytesremaining); nread = Curl_sec_read(conn, sockfd, conn->master_buffer, bytesfromsocket); else nread = sread(sockfd, conn->master_buffer, bytesremaining); nread = sread(sockfd, conn->master_buffer, bytesfromsocket); if(-1 == nread && bytestocopy == 0) { if(-1 == nread) { int err = Curl_sockerrno(); #ifdef USE_WINSOCK if(WSAEWOULDBLOCK == err) Loading @@ -509,12 +520,12 @@ int Curl_read(struct connectdata *conn, /* connection data */ } } if (nread > 0) { if (nread >= 0) { memcpy(buf, conn->master_buffer, nread); conn->buf_len = nread; conn->read_pos = nread; *n += nread; *n = nread; } return CURLE_OK; Loading
lib/transfer.c +16 −10 Original line number Diff line number Diff line Loading @@ -743,8 +743,10 @@ CURLcode Curl_readwrite(struct connectdata *conn, failf(data, "Maximum file size exceeded"); return CURLE_FILESIZE_EXCEEDED; } if(contentlength >= 0) if(contentlength >= 0) { k->size = contentlength; k->maxdownload = k->size; } else { /* Negative Content-Length is really odd, and we know it happens for example when older Apache servers send large Loading Loading @@ -1133,13 +1135,17 @@ CURLcode Curl_readwrite(struct connectdata *conn, if((-1 != k->maxdownload) && (k->bytecount + nread >= k->maxdownload)) { size_t excess = (size_t)(k->bytecount + (curl_off_t)nread - k->maxdownload); if (excess > 0) { infof(data, "Rewinding stream by : %d bytes\n", excess); curl_off_t excess = k->bytecount + ((curl_off_t) nread) - k->maxdownload; if (excess > 0 && !k->ignorebody) { infof(data, "Rewinding stream by : %" FORMAT_OFF_T " bytes on url %s (size = %" FORMAT_OFF_T ", maxdownload = %" FORMAT_OFF_T ", bytecount = %" FORMAT_OFF_T ", nread = %d)\n", excess, conn->data->reqdata.path, k->size, k->maxdownload, k->bytecount, nread); Curl_read_rewind(conn, excess); conn->bits.stream_was_rewound = TRUE; } nread = (ssize_t) (k->maxdownload - k->bytecount); Loading
lib/url.c +40 −18 Original line number Diff line number Diff line Loading @@ -1854,6 +1854,7 @@ int Curl_removeHandleFromPipeline(struct SessionHandle *handle, } curr = curr->next; } return 0; } Loading Loading @@ -1899,8 +1900,8 @@ static void signalPipeClose(struct curl_llist *pipe) } else #endif data->state.pipe_broke = TRUE; data->state.pipe_broke = TRUE; Curl_llist_remove(pipe, curr, NULL); curr = next; } Loading Loading @@ -1936,12 +1937,19 @@ ConnectionExists(struct SessionHandle *data, /* NULL pointer means not filled-in entry */ continue; #ifdef USE_ARES /* ip_addr_str is NULL only if the resolving of the name hasn't completed yet and until then we don't re-use this connection */ if (!check->ip_addr_str) continue; #endif if(check->inuse && !canPipeline) /* can only happen within multi handles, and means that another easy handle is using this connection */ continue; if (check->send_pipe->size >= MAX_PIPELINE_LENGTH || if (check->send_pipe->size + check->recv_pipe->size >= MAX_PIPELINE_LENGTH) continue; Loading Loading @@ -1994,14 +2002,28 @@ ConnectionExists(struct SessionHandle *data, } if(match) { bool dead = SocketIsDead(check->sock[FIRSTSOCKET]); if(dead) { /* */ if (!check->is_in_pipeline) { check->data = data; infof(data, "Connection %d seems to be dead!\n", i); Curl_disconnect(check); /* disconnect resources */ data->state.connc->connects[i]=NULL; /* nothing here */ } else { /* In the pipelining case, freeing the connection right away * doesn't work. Instead, we mark the connection for close * so that the handles will detect this automatically when * they try to do something and deal with it there. * Prematurely freeing this connection prevents handles that * have already finished with their transfers to shut down * cleanly. */ infof(data, "Connection %d seems dead - marking for close\n", i); check->bits.close = TRUE; } /* There's no need to continue searching, because we only store one connection for each unique set of identifiers */ Loading @@ -2016,6 +2038,9 @@ ConnectionExists(struct SessionHandle *data, check->is_in_pipeline = TRUE; } check->connectindex = i; /* Set this appropriately since it might have been set to -1 when the easy was removed from the multi */ *usethis = check; return TRUE; /* yes, we found one to use! */ } Loading Loading @@ -2690,6 +2715,9 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->readchannel_inuse = FALSE; conn->writechannel_inuse = FALSE; conn->read_pos = 0; conn->buf_len = 0; /* Initialize the pipeline lists */ conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); Loading Loading @@ -3622,12 +3650,6 @@ static CURLcode CreateConnection(struct SessionHandle *data, infof(data, "Re-using existing connection! (#%ld) with host %s\n", conn->connectindex, conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname); #ifdef CURLRES_ASYNCH if(!conn->ip_addr_str) { infof(data, "... but it is not resolved yet!\n"); *async = TRUE; } #endif } else { /* Loading Loading @@ -3990,10 +4012,10 @@ CURLcode Curl_done(struct connectdata **connp, if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && conn->readchannel_inuse) conn->readchannel_inuse--; conn->readchannel_inuse = FALSE; if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && conn->writechannel_inuse) conn->writechannel_inuse--; conn->writechannel_inuse = FALSE; /* cleanups done even if the connection is re-used */ if(data->reqdata.rangestringalloc) { Loading