source: asp3_tinet_ecnl_arm/trunk/curl-7.57.0/lib/sendf.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 24.8 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
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 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#ifdef HAVE_LINUX_TCP_H
26#include <linux/tcp.h>
27#endif
28
29#include <curl/curl.h>
30
31#include "urldata.h"
32#include "sendf.h"
33#include "connect.h"
34#include "vtls/vtls.h"
35#include "ssh.h"
36#include "multiif.h"
37#include "non-ascii.h"
38#include "strerror.h"
39#include "select.h"
40#include "strdup.h"
41
42/* The last 3 #include files should be in this order */
43#include "curl_printf.h"
44#include "curl_memory.h"
45#include "memdebug.h"
46
47#ifdef CURL_DO_LINEEND_CONV
48/*
49 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
50 * (\n), with special processing for CRLF sequences that are split between two
51 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
52 * size of the data is returned.
53 */
54static size_t convert_lineends(struct Curl_easy *data,
55 char *startPtr, size_t size)
56{
57 char *inPtr, *outPtr;
58
59 /* sanity check */
60 if((startPtr == NULL) || (size < 1)) {
61 return size;
62 }
63
64 if(data->state.prev_block_had_trailing_cr) {
65 /* The previous block of incoming data
66 had a trailing CR, which was turned into a LF. */
67 if(*startPtr == '\n') {
68 /* This block of incoming data starts with the
69 previous block's LF so get rid of it */
70 memmove(startPtr, startPtr + 1, size-1);
71 size--;
72 /* and it wasn't a bare CR but a CRLF conversion instead */
73 data->state.crlf_conversions++;
74 }
75 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
76 }
77
78 /* find 1st CR, if any */
79 inPtr = outPtr = memchr(startPtr, '\r', size);
80 if(inPtr) {
81 /* at least one CR, now look for CRLF */
82 while(inPtr < (startPtr + size-1)) {
83 /* note that it's size-1, so we'll never look past the last byte */
84 if(memcmp(inPtr, "\r\n", 2) == 0) {
85 /* CRLF found, bump past the CR and copy the NL */
86 inPtr++;
87 *outPtr = *inPtr;
88 /* keep track of how many CRLFs we converted */
89 data->state.crlf_conversions++;
90 }
91 else {
92 if(*inPtr == '\r') {
93 /* lone CR, move LF instead */
94 *outPtr = '\n';
95 }
96 else {
97 /* not a CRLF nor a CR, just copy whatever it is */
98 *outPtr = *inPtr;
99 }
100 }
101 outPtr++;
102 inPtr++;
103 } /* end of while loop */
104
105 if(inPtr < startPtr + size) {
106 /* handle last byte */
107 if(*inPtr == '\r') {
108 /* deal with a CR at the end of the buffer */
109 *outPtr = '\n'; /* copy a NL instead */
110 /* note that a CRLF might be split across two blocks */
111 data->state.prev_block_had_trailing_cr = TRUE;
112 }
113 else {
114 /* copy last byte */
115 *outPtr = *inPtr;
116 }
117 outPtr++;
118 }
119 if(outPtr < startPtr + size)
120 /* tidy up by null terminating the now shorter data */
121 *outPtr = '\0';
122
123 return (outPtr - startPtr);
124 }
125 return size;
126}
127#endif /* CURL_DO_LINEEND_CONV */
128
129#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
130bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
131{
132 struct postponed_data * const psnd = &(conn->postponed[sockindex]);
133 return psnd->buffer && psnd->allocated_size &&
134 psnd->recv_size > psnd->recv_processed;
135}
136
137static void pre_receive_plain(struct connectdata *conn, int num)
138{
139 const curl_socket_t sockfd = conn->sock[num];
140 struct postponed_data * const psnd = &(conn->postponed[num]);
141 size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
142 /* WinSock will destroy unread received data if send() is
143 failed.
144 To avoid lossage of received data, recv() must be
145 performed before every send() if any incoming data is
146 available. However, skip this, if buffer is already full. */
147 if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
148 conn->recv[num] == Curl_recv_plain &&
149 (!psnd->buffer || bytestorecv)) {
150 const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
151 CURL_SOCKET_BAD, 0);
152 if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
153 /* Have some incoming data */
154 if(!psnd->buffer) {
155 /* Use buffer double default size for intermediate buffer */
156 psnd->allocated_size = 2 * conn->data->set.buffer_size;
157 psnd->buffer = malloc(psnd->allocated_size);
158 psnd->recv_size = 0;
159 psnd->recv_processed = 0;
160#ifdef DEBUGBUILD
161 psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
162#endif /* DEBUGBUILD */
163 bytestorecv = psnd->allocated_size;
164 }
165 if(psnd->buffer) {
166 ssize_t recvedbytes;
167 DEBUGASSERT(psnd->bindsock == sockfd);
168 recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
169 bytestorecv);
170 if(recvedbytes > 0)
171 psnd->recv_size += recvedbytes;
172 }
173 else
174 psnd->allocated_size = 0;
175 }
176 }
177}
178
179static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
180 size_t len)
181{
182 struct postponed_data * const psnd = &(conn->postponed[num]);
183 size_t copysize;
184 if(!psnd->buffer)
185 return 0;
186
187 DEBUGASSERT(psnd->allocated_size > 0);
188 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
189 DEBUGASSERT(psnd->recv_processed <= psnd->recv_size);
190 /* Check and process data that already received and storied in internal
191 intermediate buffer */
192 if(psnd->recv_size > psnd->recv_processed) {
193 DEBUGASSERT(psnd->bindsock == conn->sock[num]);
194 copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed);
195 memcpy(buf, psnd->buffer + psnd->recv_processed, copysize);
196 psnd->recv_processed += copysize;
197 }
198 else
199 copysize = 0; /* buffer was allocated, but nothing was received */
200
201 /* Free intermediate buffer if it has no unprocessed data */
202 if(psnd->recv_processed == psnd->recv_size) {
203 free(psnd->buffer);
204 psnd->buffer = NULL;
205 psnd->allocated_size = 0;
206 psnd->recv_size = 0;
207 psnd->recv_processed = 0;
208#ifdef DEBUGBUILD
209 psnd->bindsock = CURL_SOCKET_BAD;
210#endif /* DEBUGBUILD */
211 }
212 return (ssize_t)copysize;
213}
214#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
215/* Use "do-nothing" macros instead of functions when workaround not used */
216bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
217{
218 (void)conn;
219 (void)sockindex;
220 return false;
221}
222#define pre_receive_plain(c,n) do {} WHILE_FALSE
223#define get_pre_recved(c,n,b,l) 0
224#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
225
226/* Curl_infof() is for info message along the way */
227
228void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
229{
230 if(data && data->set.verbose) {
231 va_list ap;
232 size_t len;
233 char print_buffer[2048 + 1];
234 va_start(ap, fmt);
235 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
236 va_end(ap);
237 len = strlen(print_buffer);
238 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
239 }
240}
241
242/* Curl_failf() is for messages stating why we failed.
243 * The message SHALL NOT include any LF or CR.
244 */
245
246void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
247{
248 if(data->set.verbose || data->set.errorbuffer) {
249 va_list ap;
250 size_t len;
251 char error[CURL_ERROR_SIZE + 2];
252 va_start(ap, fmt);
253 vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
254 len = strlen(error);
255
256 if(data->set.errorbuffer && !data->state.errorbuf) {
257 strcpy(data->set.errorbuffer, error);
258 data->state.errorbuf = TRUE; /* wrote error string */
259 }
260 if(data->set.verbose) {
261 error[len] = '\n';
262 error[++len] = '\0';
263 Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
264 }
265 va_end(ap);
266 }
267}
268
269/* Curl_sendf() sends formatted data to the server */
270CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
271 const char *fmt, ...)
272{
273 struct Curl_easy *data = conn->data;
274 ssize_t bytes_written;
275 size_t write_len;
276 CURLcode result = CURLE_OK;
277 char *s;
278 char *sptr;
279 va_list ap;
280 va_start(ap, fmt);
281 s = vaprintf(fmt, ap); /* returns an allocated string */
282 va_end(ap);
283 if(!s)
284 return CURLE_OUT_OF_MEMORY; /* failure */
285
286 bytes_written = 0;
287 write_len = strlen(s);
288 sptr = s;
289
290 for(;;) {
291 /* Write the buffer to the socket */
292 result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
293
294 if(result)
295 break;
296
297 if(data->set.verbose)
298 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
299
300 if((size_t)bytes_written != write_len) {
301 /* if not all was written at once, we must advance the pointer, decrease
302 the size left and try again! */
303 write_len -= bytes_written;
304 sptr += bytes_written;
305 }
306 else
307 break;
308 }
309
310 free(s); /* free the output string */
311
312 return result;
313}
314
315/*
316 * Curl_write() is an internal write function that sends data to the
317 * server. Works with plain sockets, SCP, SSL or kerberos.
318 *
319 * If the write would block (CURLE_AGAIN), we return CURLE_OK and
320 * (*written == 0). Otherwise we return regular CURLcode value.
321 */
322CURLcode Curl_write(struct connectdata *conn,
323 curl_socket_t sockfd,
324 const void *mem,
325 size_t len,
326 ssize_t *written)
327{
328 ssize_t bytes_written;
329 CURLcode result = CURLE_OK;
330 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
331
332 bytes_written = conn->send[num](conn, num, mem, len, &result);
333
334 *written = bytes_written;
335 if(bytes_written >= 0)
336 /* we completely ignore the curlcode value when subzero is not returned */
337 return CURLE_OK;
338
339 /* handle CURLE_AGAIN or a send failure */
340 switch(result) {
341 case CURLE_AGAIN:
342 *written = 0;
343 return CURLE_OK;
344
345 case CURLE_OK:
346 /* general send failure */
347 return CURLE_SEND_ERROR;
348
349 default:
350 /* we got a specific curlcode, forward it */
351 return result;
352 }
353}
354
355ssize_t Curl_send_plain(struct connectdata *conn, int num,
356 const void *mem, size_t len, CURLcode *code)
357{
358 curl_socket_t sockfd = conn->sock[num];
359 ssize_t bytes_written;
360 /* WinSock will destroy unread received data if send() is
361 failed.
362 To avoid lossage of received data, recv() must be
363 performed before every send() if any incoming data is
364 available. */
365 pre_receive_plain(conn, num);
366
367#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
368 if(conn->bits.tcp_fastopen) {
369 bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
370 conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
371 conn->bits.tcp_fastopen = FALSE;
372 }
373 else
374#endif
375 bytes_written = swrite(sockfd, mem, len);
376
377 *code = CURLE_OK;
378 if(-1 == bytes_written) {
379 int err = SOCKERRNO;
380
381 if(
382#ifdef WSAEWOULDBLOCK
383 /* This is how Windows does it */
384 (WSAEWOULDBLOCK == err)
385#else
386 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
387 due to its inability to send off data without blocking. We therefor
388 treat both error codes the same here */
389 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
390 (EINPROGRESS == err)
391#endif
392 ) {
393 /* this is just a case of EWOULDBLOCK */
394 bytes_written = 0;
395 *code = CURLE_AGAIN;
396 }
397 else {
398 failf(conn->data, "Send failure: %s",
399 Curl_strerror(conn, err));
400 conn->data->state.os_errno = err;
401 *code = CURLE_SEND_ERROR;
402 }
403 }
404 return bytes_written;
405}
406
407/*
408 * Curl_write_plain() is an internal write function that sends data to the
409 * server using plain sockets only. Otherwise meant to have the exact same
410 * proto as Curl_write()
411 */
412CURLcode Curl_write_plain(struct connectdata *conn,
413 curl_socket_t sockfd,
414 const void *mem,
415 size_t len,
416 ssize_t *written)
417{
418 ssize_t bytes_written;
419 CURLcode result;
420 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
421
422 bytes_written = Curl_send_plain(conn, num, mem, len, &result);
423
424 *written = bytes_written;
425
426 return result;
427}
428
429ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
430 size_t len, CURLcode *code)
431{
432 curl_socket_t sockfd = conn->sock[num];
433 ssize_t nread;
434 /* Check and return data that already received and storied in internal
435 intermediate buffer */
436 nread = get_pre_recved(conn, num, buf, len);
437 if(nread > 0) {
438 *code = CURLE_OK;
439 return nread;
440 }
441
442 nread = sread(sockfd, buf, len);
443
444 *code = CURLE_OK;
445 if(-1 == nread) {
446 int err = SOCKERRNO;
447
448 if(
449#ifdef WSAEWOULDBLOCK
450 /* This is how Windows does it */
451 (WSAEWOULDBLOCK == err)
452#else
453 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
454 due to its inability to send off data without blocking. We therefor
455 treat both error codes the same here */
456 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
457#endif
458 ) {
459 /* this is just a case of EWOULDBLOCK */
460 *code = CURLE_AGAIN;
461 }
462 else {
463 failf(conn->data, "Recv failure: %s",
464 Curl_strerror(conn, err));
465 conn->data->state.os_errno = err;
466 *code = CURLE_RECV_ERROR;
467 }
468 }
469 return nread;
470}
471
472static CURLcode pausewrite(struct Curl_easy *data,
473 int type, /* what type of data */
474 const char *ptr,
475 size_t len)
476{
477 /* signalled to pause sending on this connection, but since we have data
478 we want to send we need to dup it to save a copy for when the sending
479 is again enabled */
480 struct SingleRequest *k = &data->req;
481 struct UrlState *s = &data->state;
482 char *dupl;
483 unsigned int i;
484 bool newtype = TRUE;
485
486 if(s->tempcount) {
487 for(i = 0; i< s->tempcount; i++) {
488 if(s->tempwrite[i].type == type) {
489 /* data for this type exists */
490 newtype = FALSE;
491 break;
492 }
493 }
494 DEBUGASSERT(i < 3);
495 }
496 else
497 i = 0;
498
499 if(!newtype) {
500 /* append new data to old data */
501
502 /* figure out the new size of the data to save */
503 size_t newlen = len + s->tempwrite[i].len;
504 /* allocate the new memory area */
505 char *newptr = realloc(s->tempwrite[i].buf, newlen);
506 if(!newptr)
507 return CURLE_OUT_OF_MEMORY;
508 /* copy the new data to the end of the new area */
509 memcpy(newptr + s->tempwrite[i].len, ptr, len);
510
511 /* update the pointer and the size */
512 s->tempwrite[i].buf = newptr;
513 s->tempwrite[i].len = newlen;
514 }
515 else {
516 dupl = Curl_memdup(ptr, len);
517 if(!dupl)
518 return CURLE_OUT_OF_MEMORY;
519
520 /* store this information in the state struct for later use */
521 s->tempwrite[i].buf = dupl;
522 s->tempwrite[i].len = len;
523 s->tempwrite[i].type = type;
524
525 if(newtype)
526 s->tempcount++;
527 }
528
529 /* mark the connection as RECV paused */
530 k->keepon |= KEEP_RECV_PAUSE;
531
532 DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n",
533 len, type));
534
535 return CURLE_OK;
536}
537
538
539/* Curl_client_chop_write() writes chunks of data not larger than
540 * CURL_MAX_WRITE_SIZE via client write callback(s) and
541 * takes care of pause requests from the callbacks.
542 */
543CURLcode Curl_client_chop_write(struct connectdata *conn,
544 int type,
545 char *ptr,
546 size_t len)
547{
548 struct Curl_easy *data = conn->data;
549 curl_write_callback writeheader = NULL;
550 curl_write_callback writebody = NULL;
551
552 if(!len)
553 return CURLE_OK;
554
555 /* If reading is paused, append this data to the already held data for this
556 type. */
557 if(data->req.keepon & KEEP_RECV_PAUSE)
558 return pausewrite(data, type, ptr, len);
559
560 /* Determine the callback(s) to use. */
561 if(type & CLIENTWRITE_BODY)
562 writebody = data->set.fwrite_func;
563 if((type & CLIENTWRITE_HEADER) &&
564 (data->set.fwrite_header || data->set.writeheader)) {
565 /*
566 * Write headers to the same callback or to the especially setup
567 * header callback function (added after version 7.7.1).
568 */
569 writeheader =
570 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
571 }
572
573 /* Chop data, write chunks. */
574 while(len) {
575 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
576
577 if(writebody) {
578 size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
579
580 if(CURL_WRITEFUNC_PAUSE == wrote) {
581 if(conn->handler->flags & PROTOPT_NONETWORK) {
582 /* Protocols that work without network cannot be paused. This is
583 actually only FILE:// just now, and it can't pause since the
584 transfer isn't done using the "normal" procedure. */
585 failf(data, "Write callback asked for PAUSE when not supported!");
586 return CURLE_WRITE_ERROR;
587 }
588 return pausewrite(data, type, ptr, len);
589 }
590 if(wrote != chunklen) {
591 failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
592 return CURLE_WRITE_ERROR;
593 }
594 }
595
596 if(writeheader) {
597 size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
598
599 if(CURL_WRITEFUNC_PAUSE == wrote)
600 /* here we pass in the HEADER bit only since if this was body as well
601 then it was passed already and clearly that didn't trigger the
602 pause, so this is saved for later with the HEADER bit only */
603 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
604
605 if(wrote != chunklen) {
606 failf(data, "Failed writing header");
607 return CURLE_WRITE_ERROR;
608 }
609 }
610
611 ptr += chunklen;
612 len -= chunklen;
613 }
614
615 return CURLE_OK;
616}
617
618
619/* Curl_client_write() sends data to the write callback(s)
620
621 The bit pattern defines to what "streams" to write to. Body and/or header.
622 The defines are in sendf.h of course.
623
624 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
625 local character encoding. This is a problem and should be changed in
626 the future to leave the original data alone.
627 */
628CURLcode Curl_client_write(struct connectdata *conn,
629 int type,
630 char *ptr,
631 size_t len)
632{
633 struct Curl_easy *data = conn->data;
634
635 if(0 == len)
636 len = strlen(ptr);
637
638 DEBUGASSERT(type <= 3);
639
640 /* FTP data may need conversion. */
641 if((type & CLIENTWRITE_BODY) &&
642 (conn->handler->protocol & PROTO_FAMILY_FTP) &&
643 conn->proto.ftpc.transfertype == 'A') {
644 /* convert from the network encoding */
645 CURLcode result = Curl_convert_from_network(data, ptr, len);
646 /* Curl_convert_from_network calls failf if unsuccessful */
647 if(result)
648 return result;
649
650#ifdef CURL_DO_LINEEND_CONV
651 /* convert end-of-line markers */
652 len = convert_lineends(data, ptr, len);
653#endif /* CURL_DO_LINEEND_CONV */
654 }
655
656 return Curl_client_chop_write(conn, type, ptr, len);
657}
658
659CURLcode Curl_read_plain(curl_socket_t sockfd,
660 char *buf,
661 size_t bytesfromsocket,
662 ssize_t *n)
663{
664 ssize_t nread = sread(sockfd, buf, bytesfromsocket);
665
666 if(-1 == nread) {
667 int err = SOCKERRNO;
668 int return_error;
669#ifdef USE_WINSOCK
670 return_error = WSAEWOULDBLOCK == err;
671#else
672 return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err;
673#endif
674 if(return_error)
675 return CURLE_AGAIN;
676 return CURLE_RECV_ERROR;
677 }
678
679 /* we only return number of bytes read when we return OK */
680 *n = nread;
681 return CURLE_OK;
682}
683
684/*
685 * Internal read-from-socket function. This is meant to deal with plain
686 * sockets, SSL sockets and kerberos sockets.
687 *
688 * Returns a regular CURLcode value.
689 */
690CURLcode Curl_read(struct connectdata *conn, /* connection data */
691 curl_socket_t sockfd, /* read from this socket */
692 char *buf, /* store read data here */
693 size_t sizerequested, /* max amount to read */
694 ssize_t *n) /* amount bytes read */
695{
696 CURLcode result = CURLE_RECV_ERROR;
697 ssize_t nread = 0;
698 size_t bytesfromsocket = 0;
699 char *buffertofill = NULL;
700 struct Curl_easy *data = conn->data;
701
702 /* if HTTP/1 pipelining is both wanted and possible */
703 bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
704 (conn->bundle->multiuse == BUNDLE_PIPELINING);
705
706 /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
707 If it is the second socket, we set num to 1. Otherwise to 0. This lets
708 us use the correct ssl handle. */
709 int num = (sockfd == conn->sock[SECONDARYSOCKET]);
710
711 *n = 0; /* reset amount to zero */
712
713 /* If session can pipeline, check connection buffer */
714 if(pipelining) {
715 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
716 sizerequested);
717
718 /* Copy from our master buffer first if we have some unread data there*/
719 if(bytestocopy > 0) {
720 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
721 conn->read_pos += bytestocopy;
722 conn->bits.stream_was_rewound = FALSE;
723
724 *n = (ssize_t)bytestocopy;
725 return CURLE_OK;
726 }
727 /* If we come here, it means that there is no data to read from the buffer,
728 * so we read from the socket */
729 bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE);
730 buffertofill = conn->master_buffer;
731 }
732 else {
733 bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
734 buffertofill = buf;
735 }
736
737 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
738 if(nread < 0)
739 return result;
740
741 if(pipelining) {
742 memcpy(buf, conn->master_buffer, nread);
743 conn->buf_len = nread;
744 conn->read_pos = nread;
745 }
746
747 *n += nread;
748
749 return CURLE_OK;
750}
751
752/* return 0 on success */
753static int showit(struct Curl_easy *data, curl_infotype type,
754 char *ptr, size_t size)
755{
756 static const char s_infotype[CURLINFO_END][3] = {
757 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
758 int rc = 0;
759
760#ifdef CURL_DOES_CONVERSIONS
761 char *buf = NULL;
762 size_t conv_size = 0;
763
764 switch(type) {
765 case CURLINFO_HEADER_OUT:
766 buf = Curl_memdup(ptr, size);
767 if(!buf)
768 return 1;
769 conv_size = size;
770
771 /* Special processing is needed for this block if it
772 * contains both headers and data (separated by CRLFCRLF).
773 * We want to convert just the headers, leaving the data as-is.
774 */
775 if(size > 4) {
776 size_t i;
777 for(i = 0; i < size-4; i++) {
778 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
779 /* convert everything through this CRLFCRLF but no further */
780 conv_size = i + 4;
781 break;
782 }
783 }
784 }
785
786 Curl_convert_from_network(data, buf, conv_size);
787 /* Curl_convert_from_network calls failf if unsuccessful */
788 /* we might as well continue even if it fails... */
789 ptr = buf; /* switch pointer to use my buffer instead */
790 break;
791 default:
792 /* leave everything else as-is */
793 break;
794 }
795#endif /* CURL_DOES_CONVERSIONS */
796
797 if(data->set.fdebug)
798 rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
799 else {
800 switch(type) {
801 case CURLINFO_TEXT:
802 case CURLINFO_HEADER_OUT:
803 case CURLINFO_HEADER_IN:
804 fwrite(s_infotype[type], 2, 1, data->set.err);
805 fwrite(ptr, size, 1, data->set.err);
806#ifdef CURL_DOES_CONVERSIONS
807 if(size != conv_size) {
808 /* we had untranslated data so we need an explicit newline */
809 fwrite("\n", 1, 1, data->set.err);
810 }
811#endif
812 break;
813 default: /* nada */
814 break;
815 }
816 }
817#ifdef CURL_DOES_CONVERSIONS
818 free(buf);
819#endif
820 return rc;
821}
822
823int Curl_debug(struct Curl_easy *data, curl_infotype type,
824 char *ptr, size_t size,
825 struct connectdata *conn)
826{
827 int rc;
828 if(data->set.printhost && conn && conn->host.dispname) {
829 char buffer[160];
830 const char *t = NULL;
831 const char *w = "Data";
832 switch(type) {
833 case CURLINFO_HEADER_IN:
834 w = "Header";
835 /* FALLTHROUGH */
836 case CURLINFO_DATA_IN:
837 t = "from";
838 break;
839 case CURLINFO_HEADER_OUT:
840 w = "Header";
841 /* FALLTHROUGH */
842 case CURLINFO_DATA_OUT:
843 t = "to";
844 break;
845 default:
846 break;
847 }
848
849 if(t) {
850 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
851 conn->host.dispname);
852 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
853 if(rc)
854 return rc;
855 }
856 }
857 rc = showit(data, type, ptr, size);
858 return rc;
859}
Note: See TracBrowser for help on using the repository browser.