blob: ad370ee82908d92e0ff4242c76bc0d0dec50d407 [file] [log] [blame]
Kristian Monsen5ab50182010-05-14 18:53:44 +01001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Elliott Hughes82be86d2017-09-20 17:00:17 -07008 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
Kristian Monsen5ab50182010-05-14 18:53:44 +01009 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
Alex Deymod15eaac2016-06-28 14:49:26 -070012 * are also available at https://curl.haxx.se/docs/copyright.html.
Kristian Monsen5ab50182010-05-14 18:53:44 +010013 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * 'pingpong' is for generic back-and-forth support functions used by FTP,
22 * IMAP, POP3, SMTP and whatever more that likes them.
23 *
24 ***************************************************************************/
25
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070026#include "curl_setup.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010027
28#include "urldata.h"
29#include "sendf.h"
30#include "select.h"
31#include "progress.h"
32#include "speedcheck.h"
33#include "pingpong.h"
34#include "multiif.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070035#include "non-ascii.h"
36#include "vtls/vtls.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010037
Alex Deymod15eaac2016-06-28 14:49:26 -070038/* The last 3 #include files should be in this order */
39#include "curl_printf.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010040#include "curl_memory.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010041#include "memdebug.h"
42
43#ifdef USE_PINGPONG
44
45/* Returns timeout in ms. 0 or negative number means the timeout has already
46 triggered */
Elliott Hughescee03382017-06-23 12:17:18 -070047time_t Curl_pp_state_timeout(struct pingpong *pp)
Kristian Monsen5ab50182010-05-14 18:53:44 +010048{
49 struct connectdata *conn = pp->conn;
Alex Deymo486467e2017-12-19 19:04:07 +010050 struct Curl_easy *data = conn->data;
Elliott Hughescee03382017-06-23 12:17:18 -070051 time_t timeout_ms; /* in milliseconds */
52 time_t timeout2_ms; /* in milliseconds */
Alex Deymo486467e2017-12-19 19:04:07 +010053 long response_time = (data->set.server_response_timeout)?
Kristian Monsen5ab50182010-05-14 18:53:44 +010054 data->set.server_response_timeout: pp->response_time;
55
56 /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine
57 remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is
58 supposed to govern the response for any given server response, not for
59 the time from connect to the given server response. */
60
61 /* Without a requested timeout, we only wait 'response_time' seconds for the
62 full response to arrive before we bail out */
63 timeout_ms = response_time -
Alex Deymo486467e2017-12-19 19:04:07 +010064 Curl_timediff(Curl_now(), pp->response); /* spent time */
Kristian Monsen5ab50182010-05-14 18:53:44 +010065
66 if(data->set.timeout) {
67 /* if timeout is requested, find out how much remaining time we have */
68 timeout2_ms = data->set.timeout - /* timeout time */
Alex Deymo486467e2017-12-19 19:04:07 +010069 Curl_timediff(Curl_now(), conn->now); /* spent time */
Kristian Monsen5ab50182010-05-14 18:53:44 +010070
71 /* pick the lowest number */
72 timeout_ms = CURLMIN(timeout_ms, timeout2_ms);
73 }
74
75 return timeout_ms;
76}
77
Kristian Monsen5ab50182010-05-14 18:53:44 +010078/*
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070079 * Curl_pp_statemach()
Kristian Monsen5ab50182010-05-14 18:53:44 +010080 */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070081CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
Kristian Monsen5ab50182010-05-14 18:53:44 +010082{
83 struct connectdata *conn = pp->conn;
84 curl_socket_t sock = conn->sock[FIRSTSOCKET];
85 int rc;
Elliott Hughescee03382017-06-23 12:17:18 -070086 time_t interval_ms;
87 time_t timeout_ms = Curl_pp_state_timeout(pp);
Alex Deymo486467e2017-12-19 19:04:07 +010088 struct Curl_easy *data = conn->data;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070089 CURLcode result = CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +010090
Alex Deymo486467e2017-12-19 19:04:07 +010091 if(timeout_ms <= 0) {
Kristian Monsen5ab50182010-05-14 18:53:44 +010092 failf(data, "server response timeout");
93 return CURLE_OPERATION_TIMEDOUT; /* already too little time */
94 }
95
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070096 if(block) {
97 interval_ms = 1000; /* use 1 second timeout intervals */
98 if(timeout_ms < interval_ms)
99 interval_ms = timeout_ms;
100 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100101 else
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700102 interval_ms = 0; /* immediate */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100103
Elliott Hughescee03382017-06-23 12:17:18 -0700104 if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
105 rc = 1;
106 else if(Curl_pp_moredata(pp))
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700107 /* We are receiving and there is data in the cache so just read it */
108 rc = 1;
109 else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
110 /* We are receiving and there is data ready in the SSL library */
111 rc = 1;
112 else
Elliott Hughescee03382017-06-23 12:17:18 -0700113 rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
114 CURL_SOCKET_BAD,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700115 pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
116 interval_ms);
117
118 if(block) {
119 /* if we didn't wait, we don't have to spend time on this now */
120 if(Curl_pgrsUpdate(conn))
121 result = CURLE_ABORTED_BY_CALLBACK;
122 else
Alex Deymo486467e2017-12-19 19:04:07 +0100123 result = Curl_speedcheck(data, Curl_now());
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700124
125 if(result)
126 return result;
127 }
128
129 if(rc == -1) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100130 failf(data, "select/poll error");
131 result = CURLE_OUT_OF_MEMORY;
132 }
133 else if(rc)
134 result = pp->statemach_act(conn);
135
136 return result;
137}
138
139/* initialize stuff to prepare for reading a fresh new response */
140void Curl_pp_init(struct pingpong *pp)
141{
142 struct connectdata *conn = pp->conn;
143 pp->nread_resp = 0;
144 pp->linestart_resp = conn->data->state.buffer;
145 pp->pending_resp = TRUE;
Alex Deymo486467e2017-12-19 19:04:07 +0100146 pp->response = Curl_now(); /* start response time-out now! */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100147}
148
149
150
151/***********************************************************************
152 *
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700153 * Curl_pp_vsendf()
Kristian Monsen5ab50182010-05-14 18:53:44 +0100154 *
Elliott Hughes82be86d2017-09-20 17:00:17 -0700155 * Send the formatted string as a command to a pingpong server. Note that
Kristian Monsen5ab50182010-05-14 18:53:44 +0100156 * the string should not have any CRLF appended, as this function will
157 * append the necessary things itself.
158 *
Kristian Monsen5ab50182010-05-14 18:53:44 +0100159 * made to never block
160 */
161CURLcode Curl_pp_vsendf(struct pingpong *pp,
162 const char *fmt,
163 va_list args)
164{
165 ssize_t bytes_written;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100166 size_t write_len;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700167 char *fmt_crlf;
168 char *s;
169 CURLcode result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100170 struct connectdata *conn = pp->conn;
Alex Deymo486467e2017-12-19 19:04:07 +0100171 struct Curl_easy *data;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100172
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700173#ifdef HAVE_GSSAPI
Alex Deymo486467e2017-12-19 19:04:07 +0100174 enum protection_level data_sec;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100175#endif
176
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700177 DEBUGASSERT(pp->sendleft == 0);
178 DEBUGASSERT(pp->sendsize == 0);
179 DEBUGASSERT(pp->sendthis == NULL);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100180
Alex Deymo486467e2017-12-19 19:04:07 +0100181 if(!conn)
182 /* can't send without a connection! */
183 return CURLE_SEND_ERROR;
184
185 data = conn->data;
186
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700187 fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
188 if(!fmt_crlf)
189 return CURLE_OUT_OF_MEMORY;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100190
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700191 s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
192 free(fmt_crlf);
193 if(!s)
194 return CURLE_OUT_OF_MEMORY;
195
196 bytes_written = 0;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100197 write_len = strlen(s);
198
199 Curl_pp_init(pp);
200
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700201 result = Curl_convert_to_network(data, s, write_len);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100202 /* Curl_convert_to_network calls failf if unsuccessful */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700203 if(result) {
204 free(s);
205 return result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100206 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100207
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700208#ifdef HAVE_GSSAPI
209 conn->data_prot = PROT_CMD;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100210#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700211 result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
212 &bytes_written);
213#ifdef HAVE_GSSAPI
Alex Deymo486467e2017-12-19 19:04:07 +0100214 data_sec = conn->data_prot;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700215 DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100216 conn->data_prot = data_sec;
217#endif
218
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700219 if(result) {
220 free(s);
221 return result;
222 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100223
224 if(conn->data->set.verbose)
225 Curl_debug(conn->data, CURLINFO_HEADER_OUT,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700226 s, (size_t)bytes_written, conn);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100227
228 if(bytes_written != (ssize_t)write_len) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700229 /* the whole chunk was not sent, keep it around and adjust sizes */
230 pp->sendthis = s;
231 pp->sendsize = write_len;
232 pp->sendleft = write_len - bytes_written;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100233 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700234 else {
235 free(s);
236 pp->sendthis = NULL;
237 pp->sendleft = pp->sendsize = 0;
Alex Deymo486467e2017-12-19 19:04:07 +0100238 pp->response = Curl_now();
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700239 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100240
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700241 return CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100242}
243
244
245/***********************************************************************
246 *
247 * Curl_pp_sendf()
248 *
Elliott Hughes82be86d2017-09-20 17:00:17 -0700249 * Send the formatted string as a command to a pingpong server. Note that
Kristian Monsen5ab50182010-05-14 18:53:44 +0100250 * the string should not have any CRLF appended, as this function will
251 * append the necessary things itself.
252 *
Kristian Monsen5ab50182010-05-14 18:53:44 +0100253 * made to never block
254 */
255CURLcode Curl_pp_sendf(struct pingpong *pp,
256 const char *fmt, ...)
257{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700258 CURLcode result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100259 va_list ap;
260 va_start(ap, fmt);
261
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700262 result = Curl_pp_vsendf(pp, fmt, ap);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100263
264 va_end(ap);
265
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700266 return result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100267}
268
269/*
270 * Curl_pp_readresp()
271 *
272 * Reads a piece of a server response.
273 */
274CURLcode Curl_pp_readresp(curl_socket_t sockfd,
275 struct pingpong *pp,
276 int *code, /* return the server code if done */
277 size_t *size) /* size of the response */
278{
279 ssize_t perline; /* count bytes per line */
Alex Deymo486467e2017-12-19 19:04:07 +0100280 bool keepon = TRUE;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100281 ssize_t gotbytes;
282 char *ptr;
283 struct connectdata *conn = pp->conn;
Alex Deymoe3149cc2016-10-05 11:18:42 -0700284 struct Curl_easy *data = conn->data;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100285 char * const buf = data->state.buffer;
286 CURLcode result = CURLE_OK;
287
288 *code = 0; /* 0 for errors or not done */
289 *size = 0;
290
Alex Deymo486467e2017-12-19 19:04:07 +0100291 ptr = buf + pp->nread_resp;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100292
293 /* number of bytes in the current line, so far */
294 perline = (ssize_t)(ptr-pp->linestart_resp);
295
Elliott Hughes82be86d2017-09-20 17:00:17 -0700296 while((pp->nread_resp < (size_t)data->set.buffer_size) &&
297 (keepon && !result)) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100298
299 if(pp->cache) {
300 /* we had data in the "cache", copy that instead of doing an actual
301 * read
302 *
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700303 * pp->cache_size is cast to ssize_t here. This should be safe, because
304 * it would have been populated with something of size int to begin
305 * with, even though its datatype may be larger than an int.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100306 */
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700307 if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) {
308 failf(data, "cached response data too big to handle");
309 return CURLE_RECV_ERROR;
310 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100311 memcpy(ptr, pp->cache, pp->cache_size);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700312 gotbytes = (ssize_t)pp->cache_size;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100313 free(pp->cache); /* free the cache */
314 pp->cache = NULL; /* clear the pointer */
315 pp->cache_size = 0; /* zero the size just in case */
316 }
317 else {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700318#ifdef HAVE_GSSAPI
Kristian Monsen5ab50182010-05-14 18:53:44 +0100319 enum protection_level prot = conn->data_prot;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700320 conn->data_prot = PROT_CLEAR;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100321#endif
Elliott Hughes82be86d2017-09-20 17:00:17 -0700322 DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
323 (buf + data->set.buffer_size + 1));
324 result = Curl_read(conn, sockfd, ptr,
325 data->set.buffer_size - pp->nread_resp,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700326 &gotbytes);
327#ifdef HAVE_GSSAPI
328 DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100329 conn->data_prot = prot;
330#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700331 if(result == CURLE_AGAIN)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100332 return CURLE_OK; /* return */
333
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700334 if(!result && (gotbytes > 0))
Kristian Monsen5ab50182010-05-14 18:53:44 +0100335 /* convert from the network encoding */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700336 result = Curl_convert_from_network(data, ptr, gotbytes);
337 /* Curl_convert_from_network calls failf if unsuccessful */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100338
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700339 if(result)
340 /* Set outer result variable to this error. */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100341 keepon = FALSE;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100342 }
343
344 if(!keepon)
345 ;
346 else if(gotbytes <= 0) {
347 keepon = FALSE;
348 result = CURLE_RECV_ERROR;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700349 failf(data, "response reading failed");
Kristian Monsen5ab50182010-05-14 18:53:44 +0100350 }
351 else {
352 /* we got a whole chunk of data, which can be anything from one
353 * byte to a set of lines and possible just a piece of the last
354 * line */
355 ssize_t i;
356 ssize_t clipamount = 0;
357 bool restart = FALSE;
358
359 data->req.headerbytecount += (long)gotbytes;
360
361 pp->nread_resp += gotbytes;
362 for(i = 0; i < gotbytes; ptr++, i++) {
363 perline++;
Alex Deymo486467e2017-12-19 19:04:07 +0100364 if(*ptr == '\n') {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700365 /* a newline is CRLF in pp-talk, so the CR is ignored as
Kristian Monsen5ab50182010-05-14 18:53:44 +0100366 the line isn't really terminated until the LF comes */
367
368 /* output debug output if that is requested */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700369#ifdef HAVE_GSSAPI
Kristian Monsen5ab50182010-05-14 18:53:44 +0100370 if(!conn->sec_complete)
371#endif
372 if(data->set.verbose)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700373 Curl_debug(data, CURLINFO_HEADER_IN,
374 pp->linestart_resp, (size_t)perline, conn);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100375
376 /*
377 * We pass all response-lines to the callback function registered
378 * for "headers". The response lines can be seen as a kind of
379 * headers.
380 */
381 result = Curl_client_write(conn, CLIENTWRITE_HEADER,
382 pp->linestart_resp, perline);
383 if(result)
384 return result;
385
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700386 if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100387 /* This is the end of the last line, copy the last line to the
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700388 start of the buffer and zero terminate, for old times sake */
389 size_t n = ptr - pp->linestart_resp;
390 memmove(buf, pp->linestart_resp, n);
Alex Deymo486467e2017-12-19 19:04:07 +0100391 buf[n] = 0; /* zero terminate */
392 keepon = FALSE;
393 pp->linestart_resp = ptr + 1; /* advance pointer */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100394 i++; /* skip this before getting out */
395
396 *size = pp->nread_resp; /* size of the response */
397 pp->nread_resp = 0; /* restart */
398 break;
399 }
Alex Deymo486467e2017-12-19 19:04:07 +0100400 perline = 0; /* line starts over here */
401 pp->linestart_resp = ptr + 1;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100402 }
403 }
404
405 if(!keepon && (i != gotbytes)) {
406 /* We found the end of the response lines, but we didn't parse the
407 full chunk of data we have read from the server. We therefore need
408 to store the rest of the data to be checked on the next invoke as
409 it may actually contain another end of response already! */
410 clipamount = gotbytes - i;
411 restart = TRUE;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700412 DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
413 "server response left\n",
414 (int)clipamount));
Kristian Monsen5ab50182010-05-14 18:53:44 +0100415 }
416 else if(keepon) {
417
Elliott Hughes82be86d2017-09-20 17:00:17 -0700418 if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100419 /* We got an excessive line without newlines and we need to deal
420 with it. We keep the first bytes of the line then we throw
421 away the rest. */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700422 infof(data, "Excessive server response line length received, "
423 "%zd bytes. Stripping\n", gotbytes);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100424 restart = TRUE;
425
426 /* we keep 40 bytes since all our pingpong protocols are only
427 interested in the first piece */
428 clipamount = 40;
429 }
Elliott Hughes82be86d2017-09-20 17:00:17 -0700430 else if(pp->nread_resp > (size_t)data->set.buffer_size/2) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700431 /* We got a large chunk of data and there's potentially still
432 trailing data to take care of, so we put any such part in the
433 "cache", clear the buffer to make space and restart. */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100434 clipamount = perline;
435 restart = TRUE;
436 }
437 }
438 else if(i == gotbytes)
439 restart = TRUE;
440
441 if(clipamount) {
442 pp->cache_size = clipamount;
443 pp->cache = malloc(pp->cache_size);
444 if(pp->cache)
445 memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
446 else
447 return CURLE_OUT_OF_MEMORY;
448 }
449 if(restart) {
450 /* now reset a few variables to start over nicely from the start of
451 the big buffer */
452 pp->nread_resp = 0; /* start over from scratch in the buffer */
453 ptr = pp->linestart_resp = buf;
454 perline = 0;
455 }
456
457 } /* there was data */
458
459 } /* while there's buffer left and loop is requested */
460
461 pp->pending_resp = FALSE;
462
463 return result;
464}
465
466int Curl_pp_getsock(struct pingpong *pp,
467 curl_socket_t *socks,
468 int numsocks)
469{
470 struct connectdata *conn = pp->conn;
471
472 if(!numsocks)
473 return GETSOCK_BLANK;
474
475 socks[0] = conn->sock[FIRSTSOCKET];
476
477 if(pp->sendleft) {
478 /* write mode */
479 return GETSOCK_WRITESOCK(0);
480 }
481
482 /* read mode */
483 return GETSOCK_READSOCK(0);
484}
485
486CURLcode Curl_pp_flushsend(struct pingpong *pp)
487{
488 /* we have a piece of a command still left to send */
489 struct connectdata *conn = pp->conn;
490 ssize_t written;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100491 curl_socket_t sock = conn->sock[FIRSTSOCKET];
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700492 CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize -
493 pp->sendleft, pp->sendleft, &written);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100494 if(result)
495 return result;
496
497 if(written != (ssize_t)pp->sendleft) {
498 /* only a fraction was sent */
499 pp->sendleft -= written;
500 }
501 else {
502 free(pp->sendthis);
Alex Deymo486467e2017-12-19 19:04:07 +0100503 pp->sendthis = NULL;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100504 pp->sendleft = pp->sendsize = 0;
Alex Deymo486467e2017-12-19 19:04:07 +0100505 pp->response = Curl_now();
Kristian Monsen5ab50182010-05-14 18:53:44 +0100506 }
507 return CURLE_OK;
508}
509
510CURLcode Curl_pp_disconnect(struct pingpong *pp)
511{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700512 free(pp->cache);
513 pp->cache = NULL;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100514 return CURLE_OK;
515}
516
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700517bool Curl_pp_moredata(struct pingpong *pp)
518{
519 return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
520 TRUE : FALSE;
521}
Kristian Monsen5ab50182010-05-14 18:53:44 +0100522
523#endif