From ec3bb8f727405642a471b4b1b9eb0118fc003104 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 12 Dec 2009 21:54:01 +0000 Subject: introducing IMAP, POP3 and SMTP support (still lots of polish left to do) --- lib/pingpong.c | 536 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 536 insertions(+) create mode 100644 lib/pingpong.c (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c new file mode 100644 index 000000000..9de6e6f05 --- /dev/null +++ b/lib/pingpong.c @@ -0,0 +1,536 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * 'pingpong' is for generic back-and-forth support functions used by FTP, + * IMAP, POP3, SMTP and whatever more that likes them. + * + * $Id$ + ***************************************************************************/ + +#include "setup.h" + +#include "urldata.h" +#include "sendf.h" +#include "select.h" +#include "progress.h" +#include "speedcheck.h" +#include "pingpong.h" +#include "multiif.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +#ifdef USE_PINGPONG + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +long Curl_pp_state_timeout(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + struct SessionHandle *data=conn->data; + long timeout_ms=360000; /* in milliseconds */ + + if(data->set.server_response_timeout ) + /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine + remaining time. Also, use pp->response because SERVER_RESPONSE_TIMEOUT + is supposed to govern the response for any given server response, not + for the time from connect to the given server response. */ + timeout_ms = data->set.server_response_timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ + else if(data->set.timeout) + /* if timeout is requested, find out how much remaining time we have */ + timeout_ms = data->set.timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ + else + /* Without a requested timeout, we only wait 'response_time' seconds for + the full response to arrive before we bail out */ + timeout_ms = pp->response_time - + Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ + + return timeout_ms; +} + + +/* + * Curl_pp_multi_statemach() + * + * called repeatedly until done when the multi interface is used. + */ +CURLcode Curl_pp_multi_statemach(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc; + struct SessionHandle *data=conn->data; + CURLcode result = CURLE_OK; + long timeout_ms = Curl_pp_state_timeout(pp); + + if(timeout_ms <= 0) { + failf(data, "server response timeout"); + return CURLE_OPERATION_TIMEDOUT; + } + + rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ + pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ + 0); + + if(rc == -1) { + failf(data, "select/poll error"); + return CURLE_OUT_OF_MEMORY; + } + else if(rc != 0) + result = pp->statemach_act(conn); + + /* if rc == 0, then select() timed out */ + + return result; +} + +/* + * Curl_pp_easy_statemach() + * + * called repeatedly until done when the easy interface is used. + */ +CURLcode Curl_pp_easy_statemach(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int rc; + long interval_ms; + long timeout_ms = Curl_pp_state_timeout(pp); + struct SessionHandle *data=conn->data; + CURLcode result; + + if(timeout_ms <=0 ) { + failf(data, "server response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout_ms < interval_ms) + interval_ms = timeout_ms; + + rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ + pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ + (int)interval_ms); + + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + else + result = Curl_speedcheck(data, Curl_tvnow()); + + if(result) + ; + else if(rc == -1) { + failf(data, "select/poll error"); + result = CURLE_OUT_OF_MEMORY; + } + else if(rc) + result = pp->statemach_act(conn); + + return result; +} + +/* initialize stuff to prepare for reading a fresh new response */ +void Curl_pp_init(struct pingpong *pp) +{ + struct connectdata *conn = pp->conn; + pp->nread_resp = 0; + pp->linestart_resp = conn->data->state.buffer; + pp->pending_resp = TRUE; + pp->response = Curl_tvnow(); /* start response time-out now! */ +} + + + +/*********************************************************************** + * + * Curl_pp_sendfv() + * + * Send the formated string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * NOTE: we build the command in a fixed-length buffer, which sets length + * restrictions on the command! + * + * made to never block + */ +CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args) +{ + ssize_t bytes_written; +/* may still not be big enough for some krb5 tokens */ +#define SBUF_SIZE 1024 + char s[SBUF_SIZE]; + size_t write_len; + char *sptr=s; + CURLcode res = CURLE_OK; + struct connectdata *conn = pp->conn; + struct SessionHandle *data = conn->data; + +#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + enum protection_level data_sec = conn->data_prot; +#endif + + vsnprintf(s, SBUF_SIZE-3, fmt, args); + + strcat(s, "\r\n"); /* append a trailing CRLF */ + + bytes_written=0; + write_len = strlen(s); + + Curl_pp_init(pp); + +#ifdef CURL_DOES_CONVERSIONS + res = Curl_convert_to_network(data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(res != CURLE_OK) { + return res; + } +#endif /* CURL_DOES_CONVERSIONS */ + +#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + conn->data_prot = prot_cmd; +#endif + res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, + &bytes_written); +#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + conn->data_prot = data_sec; +#endif + + if(CURLE_OK != res) + return res; + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, + sptr, (size_t)bytes_written, conn); + + if(bytes_written != (ssize_t)write_len) { + /* the whole chunk was not sent, store the rest of the data */ + write_len -= bytes_written; + sptr += bytes_written; + pp->sendthis = malloc(write_len); + if(pp->sendthis) { + memcpy(pp->sendthis, sptr, write_len); + pp->sendsize = pp->sendleft = write_len; + } + else { + failf(data, "out of memory"); + res = CURLE_OUT_OF_MEMORY; + } + } + else + pp->response = Curl_tvnow(); + + return res; +} + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formated string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * NOTE: we build the command in a fixed-length buffer, which sets length + * restrictions on the command! + * + * made to never block + */ +CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...) +{ + CURLcode res; + va_list ap; + va_start(ap, fmt); + + res = Curl_pp_vsendf(pp, fmt, ap); + + va_end(ap); + + return res; +} + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size) /* size of the response */ +{ + ssize_t perline; /* count bytes per line */ + bool keepon=TRUE; + ssize_t gotbytes; + char *ptr; + struct connectdata *conn = pp->conn; + struct SessionHandle *data = conn->data; + char * const buf = data->state.buffer; + CURLcode result = CURLE_OK; + + *code = 0; /* 0 for errors or not done */ + *size = 0; + + ptr=buf + pp->nread_resp; + + /* number of bytes in the current line, so far */ + perline = (ssize_t)(ptr-pp->linestart_resp); + + keepon=TRUE; + + while((pp->nread_respcache) { + /* we had data in the "cache", copy that instead of doing an actual + * read + * + * ftp->cache_size is cast to int here. This should be safe, + * because it would have been populated with something of size + * int to begin with, even though its datatype may be larger + * than an int. + */ + DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1)); + memcpy(ptr, pp->cache, pp->cache_size); + gotbytes = pp->cache_size; + free(pp->cache); /* free the cache */ + pp->cache = NULL; /* clear the pointer */ + pp->cache_size = 0; /* zero the size just in case */ + } + else { + int res; +#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + enum protection_level prot = conn->data_prot; + + conn->data_prot = 0; +#endif + DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); + res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, + &gotbytes); +#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + conn->data_prot = prot; +#endif + if(res < 0) + /* EWOULDBLOCK */ + return CURLE_OK; /* return */ + +#ifdef CURL_DOES_CONVERSIONS + if((res == CURLE_OK) && (gotbytes > 0)) { + /* convert from the network encoding */ + res = Curl_convert_from_network(data, ptr, gotbytes); + /* Curl_convert_from_network calls failf if unsuccessful */ + } +#endif /* CURL_DOES_CONVERSIONS */ + + if(CURLE_OK != res) { + result = (CURLcode)res; /* Set outer result variable to this error. */ + keepon = FALSE; + } + } + + if(!keepon) + ; + else if(gotbytes <= 0) { + keepon = FALSE; + result = CURLE_RECV_ERROR; + failf(data, "FTP response reading failed"); + } + else { + /* we got a whole chunk of data, which can be anything from one + * byte to a set of lines and possible just a piece of the last + * line */ + ssize_t i; + ssize_t clipamount = 0; + bool restart = FALSE; + + data->req.headerbytecount += gotbytes; + + pp->nread_resp += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; + if(*ptr=='\n') { + /* a newline is CRLF in ftp-talk, so the CR is ignored as + the line isn't really terminated until the LF comes */ + + /* output debug output if that is requested */ +#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + if(!conn->sec_complete) +#endif + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + pp->linestart_resp, (size_t)perline, conn); + + /* + * We pass all response-lines to the callback function registered + * for "headers". The response lines can be seen as a kind of + * headers. + */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, + pp->linestart_resp, perline); + if(result) + return result; + + if(pp->endofresp(pp, code)) { + /* This is the end of the last line, copy the last line to the + start of the buffer and zero terminate, for old times sake (and + krb4)! */ + char *meow; + int n; + for(meow=pp->linestart_resp, n=0; meowlinestart_resp = ptr+1; /* advance pointer */ + i++; /* skip this before getting out */ + + *size = pp->nread_resp; /* size of the response */ + pp->nread_resp = 0; /* restart */ + break; + } + perline=0; /* line starts over here */ + pp->linestart_resp = ptr+1; + } + } + + if(!keepon && (i != gotbytes)) { + /* We found the end of the response lines, but we didn't parse the + full chunk of data we have read from the server. We therefore need + to store the rest of the data to be checked on the next invoke as + it may actually contain another end of response already! */ + clipamount = gotbytes - i; + restart = TRUE; + } + else if(keepon) { + + if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) { + /* We got an excessive line without newlines and we need to deal + with it. We keep the first bytes of the line then we throw + away the rest. */ + infof(data, "Excessive server response line length received, %zd bytes." + " Stripping\n", gotbytes); + restart = TRUE; + + /* we keep 40 bytes since all our pingpong protocols are only + interested in the first piece */ + clipamount = 40; + } + else if(pp->nread_resp > BUFSIZE/2) { + /* We got a large chunk of data and there's potentially still trailing + data to take care of, so we put any such part in the "cache", clear + the buffer to make space and restart. */ + clipamount = perline; + restart = TRUE; + } + } + else if(i == gotbytes) + restart = TRUE; + + if(clipamount) { + pp->cache_size = clipamount; + pp->cache = malloc(pp->cache_size); + if(pp->cache) + memcpy(pp->cache, pp->linestart_resp, pp->cache_size); + else + return CURLE_OUT_OF_MEMORY; + } + if(restart) { + /* now reset a few variables to start over nicely from the start of + the big buffer */ + pp->nread_resp = 0; /* start over from scratch in the buffer */ + ptr = pp->linestart_resp = buf; + perline = 0; + } + + } /* there was data */ + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +int Curl_pp_getsock(struct pingpong *pp, + curl_socket_t *socks, + int numsocks) +{ + struct connectdata *conn = pp->conn; + + if(!numsocks) + return GETSOCK_BLANK; + + socks[0] = conn->sock[FIRSTSOCKET]; + + if(pp->sendleft) { + /* write mode */ + return GETSOCK_WRITESOCK(0); + } + + /* read mode */ + return GETSOCK_READSOCK(0); +} + +CURLcode Curl_pp_flushsend(struct pingpong *pp) +{ + /* we have a piece of a command still left to send */ + struct connectdata *conn = pp->conn; + ssize_t written; + CURLcode result = CURLE_OK; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + + result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - + pp->sendleft, pp->sendleft, &written); + if(result) + return result; + + if(written != (ssize_t)pp->sendleft) { + /* only a fraction was sent */ + pp->sendleft -= written; + } + else { + free(pp->sendthis); + pp->sendthis=NULL; + pp->sendleft = pp->sendsize = 0; + pp->response = Curl_tvnow(); + } + return CURLE_OK; +} + +CURLcode Curl_pp_disconnect(struct pingpong *pp) +{ + if(pp->cache) { + free(pp->cache); + pp->cache = NULL; + } + return CURLE_OK; +} + + + +#endif -- cgit v1.2.1 From b0f548fb56d61a44a1f689b25955140c01e1821b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 14 Dec 2009 14:02:43 +0000 Subject: Fix compiler warnings --- lib/pingpong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 9de6e6f05..fcc9dd560 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -369,7 +369,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, ssize_t clipamount = 0; bool restart = FALSE; - data->req.headerbytecount += gotbytes; + data->req.headerbytecount += (long)gotbytes; pp->nread_resp += gotbytes; for(i = 0; i < gotbytes; ptr++, i++) { -- cgit v1.2.1 From 8719398d052b9b52a6f75b6b0e4ab5de13896a4e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Mar 2010 13:05:02 +0000 Subject: remove assignment never used --- lib/pingpong.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index fcc9dd560..6f27f5761 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -49,7 +49,7 @@ long Curl_pp_state_timeout(struct pingpong *pp) { struct connectdata *conn = pp->conn; struct SessionHandle *data=conn->data; - long timeout_ms=360000; /* in milliseconds */ + long timeout_ms; /* in milliseconds */ if(data->set.server_response_timeout ) /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine -- cgit v1.2.1 From 13ac29382f9087d410a96f7ca943b16d39a10afb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Mar 2010 13:26:23 +0000 Subject: - Made the pingpong timeout code properly deal with the response timeout AND the global timeout if set. Also, as was reported in the bug report #2956437 by Ryan Chan, the time stamp to use as basis for the per command timeout was not set properly in the DONE phase for FTP (and not for SMTP) so I fixed that just now. This was a regression compared to 7.19.7 due to the conversion of FTP code over to the generic pingpong concepts. http://curl.haxx.se/bug/view.cgi?id=2956437 --- lib/pingpong.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 6f27f5761..072e56207 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -50,23 +50,28 @@ long Curl_pp_state_timeout(struct pingpong *pp) struct connectdata *conn = pp->conn; struct SessionHandle *data=conn->data; long timeout_ms; /* in milliseconds */ + long timeout2_ms; /* in milliseconds */ + long response_time= (data->set.server_response_timeout)? + data->set.server_response_timeout: pp->response_time; - if(data->set.server_response_timeout ) - /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine - remaining time. Also, use pp->response because SERVER_RESPONSE_TIMEOUT - is supposed to govern the response for any given server response, not - for the time from connect to the given server response. */ - timeout_ms = data->set.server_response_timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ - else if(data->set.timeout) + /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine + remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is + supposed to govern the response for any given server response, not for + the time from connect to the given server response. */ + + /* Without a requested timeout, we only wait 'response_time' seconds for the + full response to arrive before we bail out */ + timeout_ms = response_time - + Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ + + if(data->set.timeout) { /* if timeout is requested, find out how much remaining time we have */ - timeout_ms = data->set.timeout - /* timeout time */ + timeout2_ms = data->set.timeout - /* timeout time */ Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ - else - /* Without a requested timeout, we only wait 'response_time' seconds for - the full response to arrive before we bail out */ - timeout_ms = pp->response_time - - Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ + + /* pick the lowest number */ + timeout_ms = CURLMIN(timeout_ms, timeout2_ms); + } return timeout_ms; } -- cgit v1.2.1 From 2309b4e330b96bc2e1f8e36b6184015e59544037 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Mar 2010 11:02:54 +0100 Subject: remove the CVSish $Id$ lines --- lib/pingpong.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 072e56207..c6b6f2fb8 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -21,7 +21,6 @@ * 'pingpong' is for generic back-and-forth support functions used by FTP, * IMAP, POP3, SMTP and whatever more that likes them. * - * $Id$ ***************************************************************************/ #include "setup.h" -- cgit v1.2.1 From d64bd82bdcb169d0647a80f00068cedd761f8163 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 7 May 2010 15:05:34 +0200 Subject: sendrecv: split the I/O handling into private handler Howard Chu brought the bulk work of this patch that properly moves out the sending and recving of data to the parts of the code that are properly responsible for the various ways of doing so. Daniel Stenberg assisted with polishing a few bits and fixed some minor flaws in the original patch. Another upside of this patch is that we now abuse CURLcodes less with the "magic" -1 return codes and instead use CURLE_AGAIN more consistently. --- lib/pingpong.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index c6b6f2fb8..6172833f8 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -340,8 +340,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) conn->data_prot = prot; #endif - if(res < 0) - /* EWOULDBLOCK */ + if(res == CURLE_AGAIN) return CURLE_OK; /* return */ #ifdef CURL_DOES_CONVERSIONS -- cgit v1.2.1 From 40ecd6c9b8104019bc210d6cb39dfbf79389550c Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 19 Jul 2010 18:07:50 +0200 Subject: pingpong: Fix indentation (whitespace change only) Signed-off-by: Ben Greear --- lib/pingpong.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 6172833f8..7b2a66477 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -386,8 +386,8 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, if(!conn->sec_complete) #endif if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - pp->linestart_resp, (size_t)perline, conn); + Curl_debug(data, CURLINFO_HEADER_IN, + pp->linestart_resp, (size_t)perline, conn); /* * We pass all response-lines to the callback function registered -- cgit v1.2.1 From 40253e32feab237fa89cbd7be7367ef1f8990148 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 Aug 2010 18:53:03 +0200 Subject: build: add typecast to avoid warning There is an implicit conversion from "unsigned long" to "long"; rounding, sign extension, or loss of accuracy may result. --- lib/pingpong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 7b2a66477..876a6a215 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -322,7 +322,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, */ DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1)); memcpy(ptr, pp->cache, pp->cache_size); - gotbytes = pp->cache_size; + gotbytes = (ssize_t)pp->cache_size; free(pp->cache); /* free the cache */ pp->cache = NULL; /* clear the pointer */ pp->cache_size = 0; /* zero the size just in case */ -- cgit v1.2.1 From 59db31902c87dc321d8747eae49ac7f996afa204 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 28 Oct 2010 15:47:57 -0700 Subject: Removed a leftover mention of FTP in an error message --- lib/pingpong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 876a6a215..bced110ed 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -362,7 +362,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, else if(gotbytes <= 0) { keepon = FALSE; result = CURLE_RECV_ERROR; - failf(data, "FTP response reading failed"); + failf(data, "response reading failed"); } else { /* we got a whole chunk of data, which can be anything from one -- cgit v1.2.1 From 8d59d69449c2a86c478699a50d920541aa106201 Mon Sep 17 00:00:00 2001 From: Julien Chaffraix Date: Sat, 13 Nov 2010 12:01:33 -0800 Subject: security: tighten enum protection_level usage. While changing Curl_sec_read_msg to accept an enum protection_level instead of an int, I went ahead and fixed the usage of the associated fields. Some code was assuming that prot_clear == 0. Fixed those to use the proper value. Added assertions prior to any code that would set the protection level. --- lib/pingpong.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index bced110ed..01f850677 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -217,11 +217,13 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, #endif /* CURL_DOES_CONVERSIONS */ #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + DEBUGASSERT(prot_cmd > prot_none && prot_cmd < prot_last); conn->data_prot = prot_cmd; #endif res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, &bytes_written); #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + DEBUGASSERT(data_sec > prot_none && data_sec < prot_last); conn->data_prot = data_sec; #endif @@ -331,13 +333,13 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, int res; #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) enum protection_level prot = conn->data_prot; - - conn->data_prot = 0; + conn->data_prot = prot_clear; #endif DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, &gotbytes); #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) + DEBUGASSERT(prot > prot_none && prot < prot_last); conn->data_prot = prot; #endif if(res == CURLE_AGAIN) -- cgit v1.2.1 From add5766dd4d8a15f3f96254fc65e9ab5c9ff3d48 Mon Sep 17 00:00:00 2001 From: Julien Chaffraix Date: Sat, 13 Nov 2010 14:42:34 -0800 Subject: urldata: Capitalize enum protect_level values. This makes it easier to spot the enum values from the variables. Removed some unneeded DEBUGASSERT added in the previous commit. --- lib/pingpong.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 01f850677..81f804f8e 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -217,13 +217,12 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, #endif /* CURL_DOES_CONVERSIONS */ #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - DEBUGASSERT(prot_cmd > prot_none && prot_cmd < prot_last); - conn->data_prot = prot_cmd; + conn->data_prot = PROT_CMD; #endif res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, &bytes_written); #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - DEBUGASSERT(data_sec > prot_none && data_sec < prot_last); + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); conn->data_prot = data_sec; #endif @@ -333,13 +332,13 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, int res; #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) enum protection_level prot = conn->data_prot; - conn->data_prot = prot_clear; + conn->data_prot = PROT_CLEAR; #endif DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, &gotbytes); #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - DEBUGASSERT(prot > prot_none && prot < prot_last); + DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST); conn->data_prot = prot; #endif if(res == CURLE_AGAIN) -- cgit v1.2.1 From f0aad0089e7113312d59bf5aad0f566653662b8e Mon Sep 17 00:00:00 2001 From: Brad Hards Date: Fri, 17 Dec 2010 14:57:39 +1100 Subject: Trival comment fix. --- lib/pingpong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 81f804f8e..67ce63e59 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -170,7 +170,7 @@ void Curl_pp_init(struct pingpong *pp) /*********************************************************************** * - * Curl_pp_sendfv() + * Curl_pp_vsendf() * * Send the formated string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will -- cgit v1.2.1 From c828646f60b5bffb2bfcf924eba36da767bf08bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 00:48:20 +0200 Subject: CURL_DOES_CONVERSIONS: cleanup Massively reduce #ifdefs all over (23 #ifdef lines less so far) Moved conversion-specific code to non-ascii.c --- lib/pingpong.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 67ce63e59..a49aad960 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,6 +32,7 @@ #include "speedcheck.h" #include "pingpong.h" #include "multiif.h" +#include "non-ascii.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -208,13 +209,10 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, Curl_pp_init(pp); -#ifdef CURL_DOES_CONVERSIONS res = Curl_convert_to_network(data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ - if(res != CURLE_OK) { + if(res) return res; - } -#endif /* CURL_DOES_CONVERSIONS */ #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) conn->data_prot = PROT_CMD; @@ -344,13 +342,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, if(res == CURLE_AGAIN) return CURLE_OK; /* return */ -#ifdef CURL_DOES_CONVERSIONS - if((res == CURLE_OK) && (gotbytes > 0)) { + if((res == CURLE_OK) && (gotbytes > 0)) /* convert from the network encoding */ res = Curl_convert_from_network(data, ptr, gotbytes); - /* Curl_convert_from_network calls failf if unsuccessful */ - } -#endif /* CURL_DOES_CONVERSIONS */ + /* Curl_convert_from_network calls failf if unsuccessful */ if(CURLE_OK != res) { result = (CURLcode)res; /* Set outer result variable to this error. */ -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/pingpong.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index a49aad960..8f0266760 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -431,8 +431,8 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, /* We got an excessive line without newlines and we need to deal with it. We keep the first bytes of the line then we throw away the rest. */ - infof(data, "Excessive server response line length received, %zd bytes." - " Stripping\n", gotbytes); + infof(data, "Excessive server response line length received, " + "%zd bytes. Stripping\n", gotbytes); restart = TRUE; /* we keep 40 bytes since all our pingpong protocols are only @@ -440,9 +440,9 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, clipamount = 40; } else if(pp->nread_resp > BUFSIZE/2) { - /* We got a large chunk of data and there's potentially still trailing - data to take care of, so we put any such part in the "cache", clear - the buffer to make space and restart. */ + /* We got a large chunk of data and there's potentially still + trailing data to take care of, so we put any such part in the + "cache", clear the buffer to make space and restart. */ clipamount = perline; restart = TRUE; } -- cgit v1.2.1 From 4f170ee8f9c1d067022300df2da331c30dcda9dd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 4 Jun 2011 21:19:14 +0200 Subject: Curl_socket_ready: make timeout a 'long' It was mostly typecasted to int all over the code so switching to long instead all over should be a net gain. --- lib/pingpong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 8f0266760..23ab69fb2 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -138,7 +138,7 @@ CURLcode Curl_pp_easy_statemach(struct pingpong *pp) rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ - (int)interval_ms); + interval_ms); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; -- cgit v1.2.1 From 5a45dc4a29b7b65406b8e3d1a78bed99478a9a3a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 29 Aug 2011 14:27:06 +0200 Subject: pingpong.c: fix Curl_pp_vsendf() arbitrary restrictions on command length This removes command length restrictions on calling functions. --- lib/pingpong.c | 66 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 23ab69fb2..da1391e8e 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -177,9 +177,6 @@ void Curl_pp_init(struct pingpong *pp) * the string should not have any CRLF appended, as this function will * append the necessary things itself. * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * * made to never block */ CURLcode Curl_pp_vsendf(struct pingpong *pp, @@ -187,12 +184,10 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, va_list args) { ssize_t bytes_written; -/* may still not be big enough for some krb5 tokens */ -#define SBUF_SIZE 1024 - char s[SBUF_SIZE]; size_t write_len; - char *sptr=s; - CURLcode res = CURLE_OK; + char *fmt_crlf; + char *s; + CURLcode error; struct connectdata *conn = pp->conn; struct SessionHandle *data = conn->data; @@ -200,55 +195,61 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, enum protection_level data_sec = conn->data_prot; #endif - vsnprintf(s, SBUF_SIZE-3, fmt, args); + fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */ + if(!fmt_crlf) + return CURLE_OUT_OF_MEMORY; - strcat(s, "\r\n"); /* append a trailing CRLF */ + s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */ + free(fmt_crlf); + if(!s) + return CURLE_OUT_OF_MEMORY; - bytes_written=0; + bytes_written = 0; write_len = strlen(s); Curl_pp_init(pp); - res = Curl_convert_to_network(data, s, write_len); + error = Curl_convert_to_network(data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ - if(res) - return res; + if(error) { + free(s); + return error; + } #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) conn->data_prot = PROT_CMD; #endif - res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, - &bytes_written); + error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, + &bytes_written); #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); conn->data_prot = data_sec; #endif - if(CURLE_OK != res) - return res; + if(error) { + free(s); + return error; + } if(conn->data->set.verbose) Curl_debug(conn->data, CURLINFO_HEADER_OUT, - sptr, (size_t)bytes_written, conn); + s, (size_t)bytes_written, conn); if(bytes_written != (ssize_t)write_len) { /* the whole chunk was not sent, store the rest of the data */ write_len -= bytes_written; - sptr += bytes_written; - pp->sendthis = malloc(write_len); - if(pp->sendthis) { - memcpy(pp->sendthis, sptr, write_len); - pp->sendsize = pp->sendleft = write_len; - } - else { - failf(data, "out of memory"); - res = CURLE_OUT_OF_MEMORY; - } + memmove(s, s + bytes_written, write_len + 1); + pp->sendthis = s; + pp->sendsize = pp->sendleft = write_len; } - else + else { + free(s); + pp->sendthis = NULL; + pp->sendleft = pp->sendsize = 0; pp->response = Curl_tvnow(); + } - return res; + return CURLE_OK; } @@ -260,9 +261,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, * the string should not have any CRLF appended, as this function will * append the necessary things itself. * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * * made to never block */ CURLcode Curl_pp_sendf(struct pingpong *pp, -- cgit v1.2.1 From e9e894905c5743d24f318b5a3d33802caa136f5f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 5 Sep 2011 23:45:04 +0200 Subject: pingpong.c: avoid a memmove call in function Curl_pp_vsendf --- lib/pingpong.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index da1391e8e..84ce88148 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -195,6 +195,10 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, enum protection_level data_sec = conn->data_prot; #endif + DEBUGASSERT(pp->sendleft == 0); + DEBUGASSERT(pp->sendsize == 0); + DEBUGASSERT(pp->sendthis == NULL); + fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */ if(!fmt_crlf) return CURLE_OUT_OF_MEMORY; @@ -236,11 +240,10 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, s, (size_t)bytes_written, conn); if(bytes_written != (ssize_t)write_len) { - /* the whole chunk was not sent, store the rest of the data */ - write_len -= bytes_written; - memmove(s, s + bytes_written, write_len + 1); + /* the whole chunk was not sent, keep it around and adjust sizes */ pp->sendthis = s; - pp->sendsize = pp->sendleft = write_len; + pp->sendsize = write_len; + pp->sendleft = write_len - bytes_written; } else { free(s); -- cgit v1.2.1 From 06a83e805070b01e8c8ebffb1f6b56e113b1810a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 6 Nov 2011 17:38:36 +0100 Subject: pingpong: change two comments wrongly referring "FTP" Just a sign of where the code originally was ripped out from. Now it is generic "pingpong". --- lib/pingpong.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index 84ce88148..c10894654 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -315,10 +315,9 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, /* we had data in the "cache", copy that instead of doing an actual * read * - * ftp->cache_size is cast to int here. This should be safe, - * because it would have been populated with something of size - * int to begin with, even though its datatype may be larger - * than an int. + * pp->cache_size is cast to ssize_t here. This should be safe, because + * it would have been populated with something of size int to begin + * with, even though its datatype may be larger than an int. */ DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1)); memcpy(ptr, pp->cache, pp->cache_size); @@ -375,7 +374,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, for(i = 0; i < gotbytes; ptr++, i++) { perline++; if(*ptr=='\n') { - /* a newline is CRLF in ftp-talk, so the CR is ignored as + /* a newline is CRLF in pp-talk, so the CR is ignored as the line isn't really terminated until the LF comes */ /* output debug output if that is requested */ -- cgit v1.2.1 From b2954e66e87be7414a4508f8167ca531e653bea8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 4 Nov 2012 18:22:48 +0100 Subject: FTP: prevent the multi interface from blocking As pointed out in Bug report #3579064, curl_multi_perform() would wrongly use a blocking mechanism internally for some commands which could lead to for example a very long block if the LIST response never showed. The solution was to make sure to properly continue to use the multi interface non-blocking state machine. The new test 1501 verifies the fix. Bug: http://curl.haxx.se/bug/view.cgi?id=3579064 Reported by: Guido Berhoerster --- lib/pingpong.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/pingpong.c') diff --git a/lib/pingpong.c b/lib/pingpong.c index c10894654..85a7a45af 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -424,6 +424,9 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, it may actually contain another end of response already! */ clipamount = gotbytes - i; restart = TRUE; + DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing " + "server response left\n", + (int)clipamount)); } else if(keepon) { -- cgit v1.2.1