Coverage Report

Created: 2022-12-01 06:42

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