Annotation of embedaddon/curl/lib/transfer.c, revision 1.1

1.1     ! misho       1: /***************************************************************************
        !             2:  *                                  _   _ ____  _
        !             3:  *  Project                     ___| | | |  _ \| |
        !             4:  *                             / __| | | | |_) | |
        !             5:  *                            | (__| |_| |  _ <| |___
        !             6:  *                             \___|\___/|_| \_\_____|
        !             7:  *
        !             8:  * Copyright (C) 1998 - 2020, 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: #include "strtoofft.h"
        !            25: 
        !            26: #ifdef HAVE_NETINET_IN_H
        !            27: #include <netinet/in.h>
        !            28: #endif
        !            29: #ifdef HAVE_NETDB_H
        !            30: #include <netdb.h>
        !            31: #endif
        !            32: #ifdef HAVE_ARPA_INET_H
        !            33: #include <arpa/inet.h>
        !            34: #endif
        !            35: #ifdef HAVE_NET_IF_H
        !            36: #include <net/if.h>
        !            37: #endif
        !            38: #ifdef HAVE_SYS_IOCTL_H
        !            39: #include <sys/ioctl.h>
        !            40: #endif
        !            41: #ifdef HAVE_SIGNAL_H
        !            42: #include <signal.h>
        !            43: #endif
        !            44: 
        !            45: #ifdef HAVE_SYS_PARAM_H
        !            46: #include <sys/param.h>
        !            47: #endif
        !            48: 
        !            49: #ifdef HAVE_SYS_SELECT_H
        !            50: #include <sys/select.h>
        !            51: #elif defined(HAVE_UNISTD_H)
        !            52: #include <unistd.h>
        !            53: #endif
        !            54: 
        !            55: #ifndef HAVE_SOCKET
        !            56: #error "We can't compile without socket() support!"
        !            57: #endif
        !            58: 
        !            59: #include "urldata.h"
        !            60: #include <curl/curl.h>
        !            61: #include "netrc.h"
        !            62: 
        !            63: #include "content_encoding.h"
        !            64: #include "hostip.h"
        !            65: #include "transfer.h"
        !            66: #include "sendf.h"
        !            67: #include "speedcheck.h"
        !            68: #include "progress.h"
        !            69: #include "http.h"
        !            70: #include "url.h"
        !            71: #include "getinfo.h"
        !            72: #include "vtls/vtls.h"
        !            73: #include "select.h"
        !            74: #include "multiif.h"
        !            75: #include "connect.h"
        !            76: #include "non-ascii.h"
        !            77: #include "http2.h"
        !            78: #include "mime.h"
        !            79: #include "strcase.h"
        !            80: #include "urlapi-int.h"
        !            81: 
        !            82: /* The last 3 #include files should be in this order */
        !            83: #include "curl_printf.h"
        !            84: #include "curl_memory.h"
        !            85: #include "memdebug.h"
        !            86: 
        !            87: #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
        !            88:     !defined(CURL_DISABLE_IMAP)
        !            89: /*
        !            90:  * checkheaders() checks the linked list of custom headers for a
        !            91:  * particular header (prefix). Provide the prefix without colon!
        !            92:  *
        !            93:  * Returns a pointer to the first matching header or NULL if none matched.
        !            94:  */
        !            95: char *Curl_checkheaders(const struct connectdata *conn,
        !            96:                         const char *thisheader)
        !            97: {
        !            98:   struct curl_slist *head;
        !            99:   size_t thislen = strlen(thisheader);
        !           100:   struct Curl_easy *data = conn->data;
        !           101: 
        !           102:   for(head = data->set.headers; head; head = head->next) {
        !           103:     if(strncasecompare(head->data, thisheader, thislen) &&
        !           104:        Curl_headersep(head->data[thislen]) )
        !           105:       return head->data;
        !           106:   }
        !           107: 
        !           108:   return NULL;
        !           109: }
        !           110: #endif
        !           111: 
        !           112: CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
        !           113: {
        !           114:   if(!data->state.ulbuf) {
        !           115:     data->state.ulbuf = malloc(data->set.upload_buffer_size);
        !           116:     if(!data->state.ulbuf)
        !           117:       return CURLE_OUT_OF_MEMORY;
        !           118:   }
        !           119:   return CURLE_OK;
        !           120: }
        !           121: 
        !           122: #ifndef CURL_DISABLE_HTTP
        !           123: /*
        !           124:  * This function will be called to loop through the trailers buffer
        !           125:  * until no more data is available for sending.
        !           126:  */
        !           127: static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
        !           128:                                  void *raw)
        !           129: {
        !           130:   struct Curl_easy *data = (struct Curl_easy *)raw;
        !           131:   Curl_send_buffer *trailers_buf = data->state.trailers_buf;
        !           132:   size_t bytes_left = trailers_buf->size_used-data->state.trailers_bytes_sent;
        !           133:   size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
        !           134:   if(to_copy) {
        !           135:     memcpy(buffer,
        !           136:            &trailers_buf->buffer[data->state.trailers_bytes_sent],
        !           137:            to_copy);
        !           138:     data->state.trailers_bytes_sent += to_copy;
        !           139:   }
        !           140:   return to_copy;
        !           141: }
        !           142: 
        !           143: static size_t Curl_trailers_left(void *raw)
        !           144: {
        !           145:   struct Curl_easy *data = (struct Curl_easy *)raw;
        !           146:   Curl_send_buffer *trailers_buf = data->state.trailers_buf;
        !           147:   return trailers_buf->size_used - data->state.trailers_bytes_sent;
        !           148: }
        !           149: #endif
        !           150: 
        !           151: /*
        !           152:  * This function will call the read callback to fill our buffer with data
        !           153:  * to upload.
        !           154:  */
        !           155: CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
        !           156:                              size_t *nreadp)
        !           157: {
        !           158:   struct Curl_easy *data = conn->data;
        !           159:   size_t buffersize = bytes;
        !           160:   size_t nread;
        !           161: 
        !           162:   curl_read_callback readfunc = NULL;
        !           163:   void *extra_data = NULL;
        !           164: 
        !           165: #ifdef CURL_DOES_CONVERSIONS
        !           166:   bool sending_http_headers = FALSE;
        !           167: 
        !           168:   if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
        !           169:     const struct HTTP *http = data->req.protop;
        !           170: 
        !           171:     if(http->sending == HTTPSEND_REQUEST)
        !           172:       /* We're sending the HTTP request headers, not the data.
        !           173:          Remember that so we don't re-translate them into garbage. */
        !           174:       sending_http_headers = TRUE;
        !           175:   }
        !           176: #endif
        !           177: 
        !           178: #ifndef CURL_DISABLE_HTTP
        !           179:   if(data->state.trailers_state == TRAILERS_INITIALIZED) {
        !           180:     struct curl_slist *trailers = NULL;
        !           181:     CURLcode result;
        !           182:     int trailers_ret_code;
        !           183: 
        !           184:     /* at this point we already verified that the callback exists
        !           185:        so we compile and store the trailers buffer, then proceed */
        !           186:     infof(data,
        !           187:           "Moving trailers state machine from initialized to sending.\n");
        !           188:     data->state.trailers_state = TRAILERS_SENDING;
        !           189:     data->state.trailers_buf = Curl_add_buffer_init();
        !           190:     if(!data->state.trailers_buf) {
        !           191:       failf(data, "Unable to allocate trailing headers buffer !");
        !           192:       return CURLE_OUT_OF_MEMORY;
        !           193:     }
        !           194:     data->state.trailers_bytes_sent = 0;
        !           195:     Curl_set_in_callback(data, true);
        !           196:     trailers_ret_code = data->set.trailer_callback(&trailers,
        !           197:                                                    data->set.trailer_data);
        !           198:     Curl_set_in_callback(data, false);
        !           199:     if(trailers_ret_code == CURL_TRAILERFUNC_OK) {
        !           200:       result = Curl_http_compile_trailers(trailers, &data->state.trailers_buf,
        !           201:                                           data);
        !           202:     }
        !           203:     else {
        !           204:       failf(data, "operation aborted by trailing headers callback");
        !           205:       *nreadp = 0;
        !           206:       result = CURLE_ABORTED_BY_CALLBACK;
        !           207:     }
        !           208:     if(result) {
        !           209:       Curl_add_buffer_free(&data->state.trailers_buf);
        !           210:       curl_slist_free_all(trailers);
        !           211:       return result;
        !           212:     }
        !           213:     infof(data, "Successfully compiled trailers.\r\n");
        !           214:     curl_slist_free_all(trailers);
        !           215:   }
        !           216: #endif
        !           217: 
        !           218:   /* if we are transmitting trailing data, we don't need to write
        !           219:      a chunk size so we skip this */
        !           220:   if(data->req.upload_chunky &&
        !           221:      data->state.trailers_state == TRAILERS_NONE) {
        !           222:     /* if chunked Transfer-Encoding */
        !           223:     buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
        !           224:     data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
        !           225:   }
        !           226: 
        !           227: #ifndef CURL_DISABLE_HTTP
        !           228:   if(data->state.trailers_state == TRAILERS_SENDING) {
        !           229:     /* if we're here then that means that we already sent the last empty chunk
        !           230:        but we didn't send a final CR LF, so we sent 0 CR LF. We then start
        !           231:        pulling trailing data until we have no more at which point we
        !           232:        simply return to the previous point in the state machine as if
        !           233:        nothing happened.
        !           234:        */
        !           235:     readfunc = Curl_trailers_read;
        !           236:     extra_data = (void *)data;
        !           237:   }
        !           238:   else
        !           239: #endif
        !           240:   {
        !           241:     readfunc = data->state.fread_func;
        !           242:     extra_data = data->state.in;
        !           243:   }
        !           244: 
        !           245:   Curl_set_in_callback(data, true);
        !           246:   nread = readfunc(data->req.upload_fromhere, 1,
        !           247:                    buffersize, extra_data);
        !           248:   Curl_set_in_callback(data, false);
        !           249: 
        !           250:   if(nread == CURL_READFUNC_ABORT) {
        !           251:     failf(data, "operation aborted by callback");
        !           252:     *nreadp = 0;
        !           253:     return CURLE_ABORTED_BY_CALLBACK;
        !           254:   }
        !           255:   if(nread == CURL_READFUNC_PAUSE) {
        !           256:     struct SingleRequest *k = &data->req;
        !           257: 
        !           258:     if(conn->handler->flags & PROTOPT_NONETWORK) {
        !           259:       /* protocols that work without network cannot be paused. This is
        !           260:          actually only FILE:// just now, and it can't pause since the transfer
        !           261:          isn't done using the "normal" procedure. */
        !           262:       failf(data, "Read callback asked for PAUSE when not supported!");
        !           263:       return CURLE_READ_ERROR;
        !           264:     }
        !           265: 
        !           266:     /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
        !           267:     k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
        !           268:     if(data->req.upload_chunky) {
        !           269:         /* Back out the preallocation done above */
        !           270:       data->req.upload_fromhere -= (8 + 2);
        !           271:     }
        !           272:     *nreadp = 0;
        !           273: 
        !           274:     return CURLE_OK; /* nothing was read */
        !           275:   }
        !           276:   else if(nread > buffersize) {
        !           277:     /* the read function returned a too large value */
        !           278:     *nreadp = 0;
        !           279:     failf(data, "read function returned funny value");
        !           280:     return CURLE_READ_ERROR;
        !           281:   }
        !           282: 
        !           283:   if(!data->req.forbidchunk && data->req.upload_chunky) {
        !           284:     /* if chunked Transfer-Encoding
        !           285:      *    build chunk:
        !           286:      *
        !           287:      *        <HEX SIZE> CRLF
        !           288:      *        <DATA> CRLF
        !           289:      */
        !           290:     /* On non-ASCII platforms the <DATA> may or may not be
        !           291:        translated based on set.prefer_ascii while the protocol
        !           292:        portion must always be translated to the network encoding.
        !           293:        To further complicate matters, line end conversion might be
        !           294:        done later on, so we need to prevent CRLFs from becoming
        !           295:        CRCRLFs if that's the case.  To do this we use bare LFs
        !           296:        here, knowing they'll become CRLFs later on.
        !           297:      */
        !           298: 
        !           299:     bool added_crlf = FALSE;
        !           300:     int hexlen = 0;
        !           301:     const char *endofline_native;
        !           302:     const char *endofline_network;
        !           303: 
        !           304:     if(
        !           305: #ifdef CURL_DO_LINEEND_CONV
        !           306:        (data->set.prefer_ascii) ||
        !           307: #endif
        !           308:        (data->set.crlf)) {
        !           309:       /* \n will become \r\n later on */
        !           310:       endofline_native  = "\n";
        !           311:       endofline_network = "\x0a";
        !           312:     }
        !           313:     else {
        !           314:       endofline_native  = "\r\n";
        !           315:       endofline_network = "\x0d\x0a";
        !           316:     }
        !           317: 
        !           318:     /* if we're not handling trailing data, proceed as usual */
        !           319:     if(data->state.trailers_state != TRAILERS_SENDING) {
        !           320:       char hexbuffer[11] = "";
        !           321:       hexlen = msnprintf(hexbuffer, sizeof(hexbuffer),
        !           322:                          "%zx%s", nread, endofline_native);
        !           323: 
        !           324:       /* move buffer pointer */
        !           325:       data->req.upload_fromhere -= hexlen;
        !           326:       nread += hexlen;
        !           327: 
        !           328:       /* copy the prefix to the buffer, leaving out the NUL */
        !           329:       memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
        !           330: 
        !           331:       /* always append ASCII CRLF to the data unless
        !           332:          we have a valid trailer callback */
        !           333: #ifndef CURL_DISABLE_HTTP
        !           334:       if((nread-hexlen) == 0 &&
        !           335:           data->set.trailer_callback != NULL &&
        !           336:           data->state.trailers_state == TRAILERS_NONE) {
        !           337:         data->state.trailers_state = TRAILERS_INITIALIZED;
        !           338:       }
        !           339:       else
        !           340: #endif
        !           341:       {
        !           342:         memcpy(data->req.upload_fromhere + nread,
        !           343:                endofline_network,
        !           344:                strlen(endofline_network));
        !           345:         added_crlf = TRUE;
        !           346:       }
        !           347:     }
        !           348: 
        !           349: #ifdef CURL_DOES_CONVERSIONS
        !           350:     {
        !           351:       CURLcode result;
        !           352:       size_t length;
        !           353:       if(data->set.prefer_ascii)
        !           354:         /* translate the protocol and data */
        !           355:         length = nread;
        !           356:       else
        !           357:         /* just translate the protocol portion */
        !           358:         length = hexlen;
        !           359:       if(length) {
        !           360:         result = Curl_convert_to_network(data, data->req.upload_fromhere,
        !           361:                                          length);
        !           362:         /* Curl_convert_to_network calls failf if unsuccessful */
        !           363:         if(result)
        !           364:           return result;
        !           365:       }
        !           366:     }
        !           367: #endif /* CURL_DOES_CONVERSIONS */
        !           368: 
        !           369: #ifndef CURL_DISABLE_HTTP
        !           370:     if(data->state.trailers_state == TRAILERS_SENDING &&
        !           371:        !Curl_trailers_left(data)) {
        !           372:       Curl_add_buffer_free(&data->state.trailers_buf);
        !           373:       data->state.trailers_state = TRAILERS_DONE;
        !           374:       data->set.trailer_data = NULL;
        !           375:       data->set.trailer_callback = NULL;
        !           376:       /* mark the transfer as done */
        !           377:       data->req.upload_done = TRUE;
        !           378:       infof(data, "Signaling end of chunked upload after trailers.\n");
        !           379:     }
        !           380:     else
        !           381: #endif
        !           382:       if((nread - hexlen) == 0 &&
        !           383:          data->state.trailers_state != TRAILERS_INITIALIZED) {
        !           384:         /* mark this as done once this chunk is transferred */
        !           385:         data->req.upload_done = TRUE;
        !           386:         infof(data,
        !           387:               "Signaling end of chunked upload via terminating chunk.\n");
        !           388:       }
        !           389: 
        !           390:     if(added_crlf)
        !           391:       nread += strlen(endofline_network); /* for the added end of line */
        !           392:   }
        !           393: #ifdef CURL_DOES_CONVERSIONS
        !           394:   else if((data->set.prefer_ascii) && (!sending_http_headers)) {
        !           395:     CURLcode result;
        !           396:     result = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
        !           397:     /* Curl_convert_to_network calls failf if unsuccessful */
        !           398:     if(result)
        !           399:       return result;
        !           400:   }
        !           401: #endif /* CURL_DOES_CONVERSIONS */
        !           402: 
        !           403:   *nreadp = nread;
        !           404: 
        !           405:   return CURLE_OK;
        !           406: }
        !           407: 
        !           408: 
        !           409: /*
        !           410:  * Curl_readrewind() rewinds the read stream. This is typically used for HTTP
        !           411:  * POST/PUT with multi-pass authentication when a sending was denied and a
        !           412:  * resend is necessary.
        !           413:  */
        !           414: CURLcode Curl_readrewind(struct connectdata *conn)
        !           415: {
        !           416:   struct Curl_easy *data = conn->data;
        !           417:   curl_mimepart *mimepart = &data->set.mimepost;
        !           418: 
        !           419:   conn->bits.rewindaftersend = FALSE; /* we rewind now */
        !           420: 
        !           421:   /* explicitly switch off sending data on this connection now since we are
        !           422:      about to restart a new transfer and thus we want to avoid inadvertently
        !           423:      sending more data on the existing connection until the next transfer
        !           424:      starts */
        !           425:   data->req.keepon &= ~KEEP_SEND;
        !           426: 
        !           427:   /* We have sent away data. If not using CURLOPT_POSTFIELDS or
        !           428:      CURLOPT_HTTPPOST, call app to rewind
        !           429:   */
        !           430:   if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
        !           431:     struct HTTP *http = data->req.protop;
        !           432: 
        !           433:     if(http->sendit)
        !           434:       mimepart = http->sendit;
        !           435:   }
        !           436:   if(data->set.postfields)
        !           437:     ; /* do nothing */
        !           438:   else if(data->set.httpreq == HTTPREQ_POST_MIME ||
        !           439:           data->set.httpreq == HTTPREQ_POST_FORM) {
        !           440:     if(Curl_mime_rewind(mimepart)) {
        !           441:       failf(data, "Cannot rewind mime/post data");
        !           442:       return CURLE_SEND_FAIL_REWIND;
        !           443:     }
        !           444:   }
        !           445:   else {
        !           446:     if(data->set.seek_func) {
        !           447:       int err;
        !           448: 
        !           449:       Curl_set_in_callback(data, true);
        !           450:       err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
        !           451:       Curl_set_in_callback(data, false);
        !           452:       if(err) {
        !           453:         failf(data, "seek callback returned error %d", (int)err);
        !           454:         return CURLE_SEND_FAIL_REWIND;
        !           455:       }
        !           456:     }
        !           457:     else if(data->set.ioctl_func) {
        !           458:       curlioerr err;
        !           459: 
        !           460:       Curl_set_in_callback(data, true);
        !           461:       err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
        !           462:                                    data->set.ioctl_client);
        !           463:       Curl_set_in_callback(data, false);
        !           464:       infof(data, "the ioctl callback returned %d\n", (int)err);
        !           465: 
        !           466:       if(err) {
        !           467:         failf(data, "ioctl callback returned error %d", (int)err);
        !           468:         return CURLE_SEND_FAIL_REWIND;
        !           469:       }
        !           470:     }
        !           471:     else {
        !           472:       /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
        !           473:          given FILE * stream and we can actually attempt to rewind that
        !           474:          ourselves with fseek() */
        !           475:       if(data->state.fread_func == (curl_read_callback)fread) {
        !           476:         if(-1 != fseek(data->state.in, 0, SEEK_SET))
        !           477:           /* successful rewind */
        !           478:           return CURLE_OK;
        !           479:       }
        !           480: 
        !           481:       /* no callback set or failure above, makes us fail at once */
        !           482:       failf(data, "necessary data rewind wasn't possible");
        !           483:       return CURLE_SEND_FAIL_REWIND;
        !           484:     }
        !           485:   }
        !           486:   return CURLE_OK;
        !           487: }
        !           488: 
        !           489: static int data_pending(const struct Curl_easy *data)
        !           490: {
        !           491:   struct connectdata *conn = data->conn;
        !           492:   /* in the case of libssh2, we can never be really sure that we have emptied
        !           493:      its internal buffers so we MUST always try until we get EAGAIN back */
        !           494:   return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
        !           495: #if defined(USE_NGHTTP2)
        !           496:     Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
        !           497:     /* For HTTP/2, we may read up everything including response body
        !           498:        with header fields in Curl_http_readwrite_headers. If no
        !           499:        content-length is provided, curl waits for the connection
        !           500:        close, which we emulate it using conn->proto.httpc.closed =
        !           501:        TRUE. The thing is if we read everything, then http2_recv won't
        !           502:        be called and we cannot signal the HTTP/2 stream has closed. As
        !           503:        a workaround, we return nonzero here to call http2_recv. */
        !           504:     ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20);
        !           505: #elif defined(ENABLE_QUIC)
        !           506:     Curl_ssl_data_pending(conn, FIRSTSOCKET) || Curl_quic_data_pending(data);
        !           507: #else
        !           508:     Curl_ssl_data_pending(conn, FIRSTSOCKET);
        !           509: #endif
        !           510: }
        !           511: 
        !           512: /*
        !           513:  * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
        !           514:  * remote document with the time provided by CURLOPT_TIMEVAL
        !           515:  */
        !           516: bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
        !           517: {
        !           518:   if((timeofdoc == 0) || (data->set.timevalue == 0))
        !           519:     return TRUE;
        !           520: 
        !           521:   switch(data->set.timecondition) {
        !           522:   case CURL_TIMECOND_IFMODSINCE:
        !           523:   default:
        !           524:     if(timeofdoc <= data->set.timevalue) {
        !           525:       infof(data,
        !           526:             "The requested document is not new enough\n");
        !           527:       data->info.timecond = TRUE;
        !           528:       return FALSE;
        !           529:     }
        !           530:     break;
        !           531:   case CURL_TIMECOND_IFUNMODSINCE:
        !           532:     if(timeofdoc >= data->set.timevalue) {
        !           533:       infof(data,
        !           534:             "The requested document is not old enough\n");
        !           535:       data->info.timecond = TRUE;
        !           536:       return FALSE;
        !           537:     }
        !           538:     break;
        !           539:   }
        !           540: 
        !           541:   return TRUE;
        !           542: }
        !           543: 
        !           544: /*
        !           545:  * Go ahead and do a read if we have a readable socket or if
        !           546:  * the stream was rewound (in which case we have data in a
        !           547:  * buffer)
        !           548:  *
        !           549:  * return '*comeback' TRUE if we didn't properly drain the socket so this
        !           550:  * function should get called again without select() or similar in between!
        !           551:  */
        !           552: static CURLcode readwrite_data(struct Curl_easy *data,
        !           553:                                struct connectdata *conn,
        !           554:                                struct SingleRequest *k,
        !           555:                                int *didwhat, bool *done,
        !           556:                                bool *comeback)
        !           557: {
        !           558:   CURLcode result = CURLE_OK;
        !           559:   ssize_t nread; /* number of bytes read */
        !           560:   size_t excess = 0; /* excess bytes read */
        !           561:   bool readmore = FALSE; /* used by RTP to signal for more data */
        !           562:   int maxloops = 100;
        !           563: 
        !           564:   *done = FALSE;
        !           565:   *comeback = FALSE;
        !           566: 
        !           567:   /* This is where we loop until we have read everything there is to
        !           568:      read or we get a CURLE_AGAIN */
        !           569:   do {
        !           570:     bool is_empty_data = FALSE;
        !           571:     size_t buffersize = data->set.buffer_size;
        !           572:     size_t bytestoread = buffersize;
        !           573: #ifdef USE_NGHTTP2
        !           574:     bool is_http2 = ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
        !           575:                      (conn->httpversion == 20));
        !           576: #endif
        !           577: 
        !           578:     if(
        !           579: #ifdef USE_NGHTTP2
        !           580:        /* For HTTP/2, read data without caring about the content
        !           581:           length. This is safe because body in HTTP/2 is always
        !           582:           segmented thanks to its framing layer. Meanwhile, we have to
        !           583:           call Curl_read to ensure that http2_handle_stream_close is
        !           584:           called when we read all incoming bytes for a particular
        !           585:           stream. */
        !           586:        !is_http2 &&
        !           587: #endif
        !           588:        k->size != -1 && !k->header) {
        !           589:       /* make sure we don't read too much */
        !           590:       curl_off_t totalleft = k->size - k->bytecount;
        !           591:       if(totalleft < (curl_off_t)bytestoread)
        !           592:         bytestoread = (size_t)totalleft;
        !           593:     }
        !           594: 
        !           595:     if(bytestoread) {
        !           596:       /* receive data from the network! */
        !           597:       result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread);
        !           598: 
        !           599:       /* read would've blocked */
        !           600:       if(CURLE_AGAIN == result)
        !           601:         break; /* get out of loop */
        !           602: 
        !           603:       if(result>0)
        !           604:         return result;
        !           605:     }
        !           606:     else {
        !           607:       /* read nothing but since we wanted nothing we consider this an OK
        !           608:          situation to proceed from */
        !           609:       DEBUGF(infof(data, "readwrite_data: we're done!\n"));
        !           610:       nread = 0;
        !           611:     }
        !           612: 
        !           613:     if(!k->bytecount) {
        !           614:       Curl_pgrsTime(data, TIMER_STARTTRANSFER);
        !           615:       if(k->exp100 > EXP100_SEND_DATA)
        !           616:         /* set time stamp to compare with when waiting for the 100 */
        !           617:         k->start100 = Curl_now();
        !           618:     }
        !           619: 
        !           620:     *didwhat |= KEEP_RECV;
        !           621:     /* indicates data of zero size, i.e. empty file */
        !           622:     is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
        !           623: 
        !           624:     /* NUL terminate, allowing string ops to be used */
        !           625:     if(0 < nread || is_empty_data) {
        !           626:       k->buf[nread] = 0;
        !           627:     }
        !           628:     else {
        !           629:       /* if we receive 0 or less here, either the http2 stream is closed or the
        !           630:          server closed the connection and we bail out from this! */
        !           631: #ifdef USE_NGHTTP2
        !           632:       if(is_http2 && !nread)
        !           633:         DEBUGF(infof(data, "nread == 0, stream closed, bailing\n"));
        !           634:       else
        !           635: #endif
        !           636:         DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n"));
        !           637:       k->keepon &= ~KEEP_RECV;
        !           638:       break;
        !           639:     }
        !           640: 
        !           641:     /* Default buffer to use when we write the buffer, it may be changed
        !           642:        in the flow below before the actual storing is done. */
        !           643:     k->str = k->buf;
        !           644: 
        !           645:     if(conn->handler->readwrite) {
        !           646:       result = conn->handler->readwrite(data, conn, &nread, &readmore);
        !           647:       if(result)
        !           648:         return result;
        !           649:       if(readmore)
        !           650:         break;
        !           651:     }
        !           652: 
        !           653: #ifndef CURL_DISABLE_HTTP
        !           654:     /* Since this is a two-state thing, we check if we are parsing
        !           655:        headers at the moment or not. */
        !           656:     if(k->header) {
        !           657:       /* we are in parse-the-header-mode */
        !           658:       bool stop_reading = FALSE;
        !           659:       result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
        !           660:       if(result)
        !           661:         return result;
        !           662: 
        !           663:       if(conn->handler->readwrite &&
        !           664:          (k->maxdownload <= 0 && nread > 0)) {
        !           665:         result = conn->handler->readwrite(data, conn, &nread, &readmore);
        !           666:         if(result)
        !           667:           return result;
        !           668:         if(readmore)
        !           669:           break;
        !           670:       }
        !           671: 
        !           672:       if(stop_reading) {
        !           673:         /* We've stopped dealing with input, get out of the do-while loop */
        !           674: 
        !           675:         if(nread > 0) {
        !           676:           infof(data,
        !           677:                 "Excess found:"
        !           678:                 " excess = %zd"
        !           679:                 " url = %s (zero-length body)\n",
        !           680:                 nread, data->state.up.path);
        !           681:         }
        !           682: 
        !           683:         break;
        !           684:       }
        !           685:     }
        !           686: #endif /* CURL_DISABLE_HTTP */
        !           687: 
        !           688: 
        !           689:     /* This is not an 'else if' since it may be a rest from the header
        !           690:        parsing, where the beginning of the buffer is headers and the end
        !           691:        is non-headers. */
        !           692:     if(k->str && !k->header && (nread > 0 || is_empty_data)) {
        !           693: 
        !           694:       if(data->set.opt_no_body) {
        !           695:         /* data arrives although we want none, bail out */
        !           696:         streamclose(conn, "ignoring body");
        !           697:         *done = TRUE;
        !           698:         return CURLE_WEIRD_SERVER_REPLY;
        !           699:       }
        !           700: 
        !           701: #ifndef CURL_DISABLE_HTTP
        !           702:       if(0 == k->bodywrites && !is_empty_data) {
        !           703:         /* These checks are only made the first time we are about to
        !           704:            write a piece of the body */
        !           705:         if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
        !           706:           /* HTTP-only checks */
        !           707: 
        !           708:           if(data->req.newurl) {
        !           709:             if(conn->bits.close) {
        !           710:               /* Abort after the headers if "follow Location" is set
        !           711:                  and we're set to close anyway. */
        !           712:               k->keepon &= ~KEEP_RECV;
        !           713:               *done = TRUE;
        !           714:               return CURLE_OK;
        !           715:             }
        !           716:             /* We have a new url to load, but since we want to be able
        !           717:                to re-use this connection properly, we read the full
        !           718:                response in "ignore more" */
        !           719:             k->ignorebody = TRUE;
        !           720:             infof(data, "Ignoring the response-body\n");
        !           721:           }
        !           722:           if(data->state.resume_from && !k->content_range &&
        !           723:              (data->set.httpreq == HTTPREQ_GET) &&
        !           724:              !k->ignorebody) {
        !           725: 
        !           726:             if(k->size == data->state.resume_from) {
        !           727:               /* The resume point is at the end of file, consider this fine
        !           728:                  even if it doesn't allow resume from here. */
        !           729:               infof(data, "The entire document is already downloaded");
        !           730:               connclose(conn, "already downloaded");
        !           731:               /* Abort download */
        !           732:               k->keepon &= ~KEEP_RECV;
        !           733:               *done = TRUE;
        !           734:               return CURLE_OK;
        !           735:             }
        !           736: 
        !           737:             /* we wanted to resume a download, although the server doesn't
        !           738:              * seem to support this and we did this with a GET (if it
        !           739:              * wasn't a GET we did a POST or PUT resume) */
        !           740:             failf(data, "HTTP server doesn't seem to support "
        !           741:                   "byte ranges. Cannot resume.");
        !           742:             return CURLE_RANGE_ERROR;
        !           743:           }
        !           744: 
        !           745:           if(data->set.timecondition && !data->state.range) {
        !           746:             /* A time condition has been set AND no ranges have been
        !           747:                requested. This seems to be what chapter 13.3.4 of
        !           748:                RFC 2616 defines to be the correct action for a
        !           749:                HTTP/1.1 client */
        !           750: 
        !           751:             if(!Curl_meets_timecondition(data, k->timeofdoc)) {
        !           752:               *done = TRUE;
        !           753:               /* We're simulating a http 304 from server so we return
        !           754:                  what should have been returned from the server */
        !           755:               data->info.httpcode = 304;
        !           756:               infof(data, "Simulate a HTTP 304 response!\n");
        !           757:               /* we abort the transfer before it is completed == we ruin the
        !           758:                  re-use ability. Close the connection */
        !           759:               connclose(conn, "Simulated 304 handling");
        !           760:               return CURLE_OK;
        !           761:             }
        !           762:           } /* we have a time condition */
        !           763: 
        !           764:         } /* this is HTTP or RTSP */
        !           765:       } /* this is the first time we write a body part */
        !           766: #endif /* CURL_DISABLE_HTTP */
        !           767: 
        !           768:       k->bodywrites++;
        !           769: 
        !           770:       /* pass data to the debug function before it gets "dechunked" */
        !           771:       if(data->set.verbose) {
        !           772:         if(k->badheader) {
        !           773:           Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
        !           774:                      (size_t)k->hbuflen);
        !           775:           if(k->badheader == HEADER_PARTHEADER)
        !           776:             Curl_debug(data, CURLINFO_DATA_IN,
        !           777:                        k->str, (size_t)nread);
        !           778:         }
        !           779:         else
        !           780:           Curl_debug(data, CURLINFO_DATA_IN,
        !           781:                      k->str, (size_t)nread);
        !           782:       }
        !           783: 
        !           784: #ifndef CURL_DISABLE_HTTP
        !           785:       if(k->chunk) {
        !           786:         /*
        !           787:          * Here comes a chunked transfer flying and we need to decode this
        !           788:          * properly.  While the name says read, this function both reads
        !           789:          * and writes away the data. The returned 'nread' holds the number
        !           790:          * of actual data it wrote to the client.
        !           791:          */
        !           792:         CURLcode extra;
        !           793:         CHUNKcode res =
        !           794:           Curl_httpchunk_read(conn, k->str, nread, &nread, &extra);
        !           795: 
        !           796:         if(CHUNKE_OK < res) {
        !           797:           if(CHUNKE_PASSTHRU_ERROR == res) {
        !           798:             failf(data, "Failed reading the chunked-encoded stream");
        !           799:             return extra;
        !           800:           }
        !           801:           failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
        !           802:           return CURLE_RECV_ERROR;
        !           803:         }
        !           804:         if(CHUNKE_STOP == res) {
        !           805:           size_t dataleft;
        !           806:           /* we're done reading chunks! */
        !           807:           k->keepon &= ~KEEP_RECV; /* read no more */
        !           808: 
        !           809:           /* There are now possibly N number of bytes at the end of the
        !           810:              str buffer that weren't written to the client.
        !           811:              Push it back to be read on the next pass. */
        !           812: 
        !           813:           dataleft = conn->chunk.dataleft;
        !           814:           if(dataleft != 0) {
        !           815:             infof(conn->data, "Leftovers after chunking: %zu bytes\n",
        !           816:                   dataleft);
        !           817:           }
        !           818:         }
        !           819:         /* If it returned OK, we just keep going */
        !           820:       }
        !           821: #endif   /* CURL_DISABLE_HTTP */
        !           822: 
        !           823:       /* Account for body content stored in the header buffer */
        !           824:       if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
        !           825:         DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
        !           826:                      k->hbuflen));
        !           827:         k->bytecount += k->hbuflen;
        !           828:       }
        !           829: 
        !           830:       if((-1 != k->maxdownload) &&
        !           831:          (k->bytecount + nread >= k->maxdownload)) {
        !           832: 
        !           833:         excess = (size_t)(k->bytecount + nread - k->maxdownload);
        !           834:         if(excess > 0 && !k->ignorebody) {
        !           835:           infof(data,
        !           836:                 "Excess found in a read:"
        !           837:                 " excess = %zu"
        !           838:                 ", size = %" CURL_FORMAT_CURL_OFF_T
        !           839:                 ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
        !           840:                 ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
        !           841:                 excess, k->size, k->maxdownload, k->bytecount);
        !           842:         }
        !           843: 
        !           844:         nread = (ssize_t) (k->maxdownload - k->bytecount);
        !           845:         if(nread < 0) /* this should be unusual */
        !           846:           nread = 0;
        !           847: 
        !           848:         k->keepon &= ~KEEP_RECV; /* we're done reading */
        !           849:       }
        !           850: 
        !           851:       k->bytecount += nread;
        !           852: 
        !           853:       Curl_pgrsSetDownloadCounter(data, k->bytecount);
        !           854: 
        !           855:       if(!k->chunk && (nread || k->badheader || is_empty_data)) {
        !           856:         /* If this is chunky transfer, it was already written */
        !           857: 
        !           858:         if(k->badheader && !k->ignorebody) {
        !           859:           /* we parsed a piece of data wrongly assuming it was a header
        !           860:              and now we output it as body instead */
        !           861: 
        !           862:           /* Don't let excess data pollute body writes */
        !           863:           if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload)
        !           864:             result = Curl_client_write(conn, CLIENTWRITE_BODY,
        !           865:                                        data->state.headerbuff,
        !           866:                                        k->hbuflen);
        !           867:           else
        !           868:             result = Curl_client_write(conn, CLIENTWRITE_BODY,
        !           869:                                        data->state.headerbuff,
        !           870:                                        (size_t)k->maxdownload);
        !           871: 
        !           872:           if(result)
        !           873:             return result;
        !           874:         }
        !           875:         if(k->badheader < HEADER_ALLBAD) {
        !           876:           /* This switch handles various content encodings. If there's an
        !           877:              error here, be sure to check over the almost identical code
        !           878:              in http_chunks.c.
        !           879:              Make sure that ALL_CONTENT_ENCODINGS contains all the
        !           880:              encodings handled here. */
        !           881:           if(conn->data->set.http_ce_skip || !k->writer_stack) {
        !           882:             if(!k->ignorebody) {
        !           883: #ifndef CURL_DISABLE_POP3
        !           884:               if(conn->handler->protocol & PROTO_FAMILY_POP3)
        !           885:                 result = Curl_pop3_write(conn, k->str, nread);
        !           886:               else
        !           887: #endif /* CURL_DISABLE_POP3 */
        !           888:                 result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
        !           889:                                            nread);
        !           890:             }
        !           891:           }
        !           892:           else if(!k->ignorebody)
        !           893:             result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
        !           894:         }
        !           895:         k->badheader = HEADER_NORMAL; /* taken care of now */
        !           896: 
        !           897:         if(result)
        !           898:           return result;
        !           899:       }
        !           900: 
        !           901:     } /* if(!header and data to read) */
        !           902: 
        !           903:     if(conn->handler->readwrite && excess) {
        !           904:       /* Parse the excess data */
        !           905:       k->str += nread;
        !           906: 
        !           907:       if(&k->str[excess] > &k->buf[data->set.buffer_size]) {
        !           908:         /* the excess amount was too excessive(!), make sure
        !           909:            it doesn't read out of buffer */
        !           910:         excess = &k->buf[data->set.buffer_size] - k->str;
        !           911:       }
        !           912:       nread = (ssize_t)excess;
        !           913: 
        !           914:       result = conn->handler->readwrite(data, conn, &nread, &readmore);
        !           915:       if(result)
        !           916:         return result;
        !           917: 
        !           918:       if(readmore)
        !           919:         k->keepon |= KEEP_RECV; /* we're not done reading */
        !           920:       break;
        !           921:     }
        !           922: 
        !           923:     if(is_empty_data) {
        !           924:       /* if we received nothing, the server closed the connection and we
        !           925:          are done */
        !           926:       k->keepon &= ~KEEP_RECV;
        !           927:     }
        !           928: 
        !           929:     if(k->keepon & KEEP_RECV_PAUSE) {
        !           930:       /* this is a paused transfer */
        !           931:       break;
        !           932:     }
        !           933: 
        !           934:   } while(data_pending(data) && maxloops--);
        !           935: 
        !           936:   if(maxloops <= 0) {
        !           937:     /* we mark it as read-again-please */
        !           938:     conn->cselect_bits = CURL_CSELECT_IN;
        !           939:     *comeback = TRUE;
        !           940:   }
        !           941: 
        !           942:   if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
        !           943:      conn->bits.close) {
        !           944:     /* When we've read the entire thing and the close bit is set, the server
        !           945:        may now close the connection. If there's now any kind of sending going
        !           946:        on from our side, we need to stop that immediately. */
        !           947:     infof(data, "we are done reading and this is set to close, stop send\n");
        !           948:     k->keepon &= ~KEEP_SEND; /* no writing anymore either */
        !           949:   }
        !           950: 
        !           951:   return CURLE_OK;
        !           952: }
        !           953: 
        !           954: CURLcode Curl_done_sending(struct connectdata *conn,
        !           955:                            struct SingleRequest *k)
        !           956: {
        !           957:   k->keepon &= ~KEEP_SEND; /* we're done writing */
        !           958: 
        !           959:   /* These functions should be moved into the handler struct! */
        !           960:   Curl_http2_done_sending(conn);
        !           961:   Curl_quic_done_sending(conn);
        !           962: 
        !           963:   if(conn->bits.rewindaftersend) {
        !           964:     CURLcode result = Curl_readrewind(conn);
        !           965:     if(result)
        !           966:       return result;
        !           967:   }
        !           968:   return CURLE_OK;
        !           969: }
        !           970: 
        !           971: #if defined(WIN32) && !defined(USE_LWIPSOCK)
        !           972: #ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
        !           973: #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
        !           974: #endif
        !           975: 
        !           976: static void win_update_buffer_size(curl_socket_t sockfd)
        !           977: {
        !           978:   int result;
        !           979:   ULONG ideal;
        !           980:   DWORD ideallen;
        !           981:   result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
        !           982:                     &ideal, sizeof(ideal), &ideallen, 0, 0);
        !           983:   if(result == 0) {
        !           984:     setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
        !           985:                (const char *)&ideal, sizeof(ideal));
        !           986:   }
        !           987: }
        !           988: #else
        !           989: #define win_update_buffer_size(x)
        !           990: #endif
        !           991: 
        !           992: /*
        !           993:  * Send data to upload to the server, when the socket is writable.
        !           994:  */
        !           995: static CURLcode readwrite_upload(struct Curl_easy *data,
        !           996:                                  struct connectdata *conn,
        !           997:                                  int *didwhat)
        !           998: {
        !           999:   ssize_t i, si;
        !          1000:   ssize_t bytes_written;
        !          1001:   CURLcode result;
        !          1002:   ssize_t nread; /* number of bytes read */
        !          1003:   bool sending_http_headers = FALSE;
        !          1004:   struct SingleRequest *k = &data->req;
        !          1005: 
        !          1006:   if((k->bytecount == 0) && (k->writebytecount == 0))
        !          1007:     Curl_pgrsTime(data, TIMER_STARTTRANSFER);
        !          1008: 
        !          1009:   *didwhat |= KEEP_SEND;
        !          1010: 
        !          1011:   do {
        !          1012:     /* only read more data if there's no upload data already
        !          1013:        present in the upload buffer */
        !          1014:     if(0 == k->upload_present) {
        !          1015:       result = Curl_get_upload_buffer(data);
        !          1016:       if(result)
        !          1017:         return result;
        !          1018:       /* init the "upload from here" pointer */
        !          1019:       k->upload_fromhere = data->state.ulbuf;
        !          1020: 
        !          1021:       if(!k->upload_done) {
        !          1022:         /* HTTP pollution, this should be written nicer to become more
        !          1023:            protocol agnostic. */
        !          1024:         size_t fillcount;
        !          1025:         struct HTTP *http = k->protop;
        !          1026: 
        !          1027:         if((k->exp100 == EXP100_SENDING_REQUEST) &&
        !          1028:            (http->sending == HTTPSEND_BODY)) {
        !          1029:           /* If this call is to send body data, we must take some action:
        !          1030:              We have sent off the full HTTP 1.1 request, and we shall now
        !          1031:              go into the Expect: 100 state and await such a header */
        !          1032:           k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */
        !          1033:           k->keepon &= ~KEEP_SEND;         /* disable writing */
        !          1034:           k->start100 = Curl_now();       /* timeout count starts now */
        !          1035:           *didwhat &= ~KEEP_SEND;  /* we didn't write anything actually */
        !          1036:           /* set a timeout for the multi interface */
        !          1037:           Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
        !          1038:           break;
        !          1039:         }
        !          1040: 
        !          1041:         if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
        !          1042:           if(http->sending == HTTPSEND_REQUEST)
        !          1043:             /* We're sending the HTTP request headers, not the data.
        !          1044:                Remember that so we don't change the line endings. */
        !          1045:             sending_http_headers = TRUE;
        !          1046:           else
        !          1047:             sending_http_headers = FALSE;
        !          1048:         }
        !          1049: 
        !          1050:         result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size,
        !          1051:                                      &fillcount);
        !          1052:         if(result)
        !          1053:           return result;
        !          1054: 
        !          1055:         nread = fillcount;
        !          1056:       }
        !          1057:       else
        !          1058:         nread = 0; /* we're done uploading/reading */
        !          1059: 
        !          1060:       if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
        !          1061:         /* this is a paused transfer */
        !          1062:         break;
        !          1063:       }
        !          1064:       if(nread <= 0) {
        !          1065:         result = Curl_done_sending(conn, k);
        !          1066:         if(result)
        !          1067:           return result;
        !          1068:         break;
        !          1069:       }
        !          1070: 
        !          1071:       /* store number of bytes available for upload */
        !          1072:       k->upload_present = nread;
        !          1073: 
        !          1074:       /* convert LF to CRLF if so asked */
        !          1075:       if((!sending_http_headers) && (
        !          1076: #ifdef CURL_DO_LINEEND_CONV
        !          1077:          /* always convert if we're FTPing in ASCII mode */
        !          1078:          (data->set.prefer_ascii) ||
        !          1079: #endif
        !          1080:          (data->set.crlf))) {
        !          1081:         /* Do we need to allocate a scratch buffer? */
        !          1082:         if(!data->state.scratch) {
        !          1083:           data->state.scratch = malloc(2 * data->set.upload_buffer_size);
        !          1084:           if(!data->state.scratch) {
        !          1085:             failf(data, "Failed to alloc scratch buffer!");
        !          1086: 
        !          1087:             return CURLE_OUT_OF_MEMORY;
        !          1088:           }
        !          1089:         }
        !          1090: 
        !          1091:         /*
        !          1092:          * ASCII/EBCDIC Note: This is presumably a text (not binary)
        !          1093:          * transfer so the data should already be in ASCII.
        !          1094:          * That means the hex values for ASCII CR (0x0d) & LF (0x0a)
        !          1095:          * must be used instead of the escape sequences \r & \n.
        !          1096:          */
        !          1097:         for(i = 0, si = 0; i < nread; i++, si++) {
        !          1098:           if(k->upload_fromhere[i] == 0x0a) {
        !          1099:             data->state.scratch[si++] = 0x0d;
        !          1100:             data->state.scratch[si] = 0x0a;
        !          1101:             if(!data->set.crlf) {
        !          1102:               /* we're here only because FTP is in ASCII mode...
        !          1103:                  bump infilesize for the LF we just added */
        !          1104:               if(data->state.infilesize != -1)
        !          1105:                 data->state.infilesize++;
        !          1106:             }
        !          1107:           }
        !          1108:           else
        !          1109:             data->state.scratch[si] = k->upload_fromhere[i];
        !          1110:         }
        !          1111: 
        !          1112:         if(si != nread) {
        !          1113:           /* only perform the special operation if we really did replace
        !          1114:              anything */
        !          1115:           nread = si;
        !          1116: 
        !          1117:           /* upload from the new (replaced) buffer instead */
        !          1118:           k->upload_fromhere = data->state.scratch;
        !          1119: 
        !          1120:           /* set the new amount too */
        !          1121:           k->upload_present = nread;
        !          1122:         }
        !          1123:       }
        !          1124: 
        !          1125: #ifndef CURL_DISABLE_SMTP
        !          1126:       if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
        !          1127:         result = Curl_smtp_escape_eob(conn, nread);
        !          1128:         if(result)
        !          1129:           return result;
        !          1130:       }
        !          1131: #endif /* CURL_DISABLE_SMTP */
        !          1132:     } /* if 0 == k->upload_present */
        !          1133:     else {
        !          1134:       /* We have a partial buffer left from a previous "round". Use
        !          1135:          that instead of reading more data */
        !          1136:     }
        !          1137: 
        !          1138:     /* write to socket (send away data) */
        !          1139:     result = Curl_write(conn,
        !          1140:                         conn->writesockfd,  /* socket to send to */
        !          1141:                         k->upload_fromhere, /* buffer pointer */
        !          1142:                         k->upload_present,  /* buffer size */
        !          1143:                         &bytes_written);    /* actually sent */
        !          1144:     if(result)
        !          1145:       return result;
        !          1146: 
        !          1147:     win_update_buffer_size(conn->writesockfd);
        !          1148: 
        !          1149:     if(data->set.verbose)
        !          1150:       /* show the data before we change the pointer upload_fromhere */
        !          1151:       Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
        !          1152:                  (size_t)bytes_written);
        !          1153: 
        !          1154:     k->writebytecount += bytes_written;
        !          1155:     Curl_pgrsSetUploadCounter(data, k->writebytecount);
        !          1156: 
        !          1157:     if((!k->upload_chunky || k->forbidchunk) &&
        !          1158:        (k->writebytecount == data->state.infilesize)) {
        !          1159:       /* we have sent all data we were supposed to */
        !          1160:       k->upload_done = TRUE;
        !          1161:       infof(data, "We are completely uploaded and fine\n");
        !          1162:     }
        !          1163: 
        !          1164:     if(k->upload_present != bytes_written) {
        !          1165:       /* we only wrote a part of the buffer (if anything), deal with it! */
        !          1166: 
        !          1167:       /* store the amount of bytes left in the buffer to write */
        !          1168:       k->upload_present -= bytes_written;
        !          1169: 
        !          1170:       /* advance the pointer where to find the buffer when the next send
        !          1171:          is to happen */
        !          1172:       k->upload_fromhere += bytes_written;
        !          1173:     }
        !          1174:     else {
        !          1175:       /* we've uploaded that buffer now */
        !          1176:       result = Curl_get_upload_buffer(data);
        !          1177:       if(result)
        !          1178:         return result;
        !          1179:       k->upload_fromhere = data->state.ulbuf;
        !          1180:       k->upload_present = 0; /* no more bytes left */
        !          1181: 
        !          1182:       if(k->upload_done) {
        !          1183:         result = Curl_done_sending(conn, k);
        !          1184:         if(result)
        !          1185:           return result;
        !          1186:       }
        !          1187:     }
        !          1188: 
        !          1189: 
        !          1190:   } while(0); /* just to break out from! */
        !          1191: 
        !          1192:   return CURLE_OK;
        !          1193: }
        !          1194: 
        !          1195: /*
        !          1196:  * Curl_readwrite() is the low-level function to be called when data is to
        !          1197:  * be read and written to/from the connection.
        !          1198:  *
        !          1199:  * return '*comeback' TRUE if we didn't properly drain the socket so this
        !          1200:  * function should get called again without select() or similar in between!
        !          1201:  */
        !          1202: CURLcode Curl_readwrite(struct connectdata *conn,
        !          1203:                         struct Curl_easy *data,
        !          1204:                         bool *done,
        !          1205:                         bool *comeback)
        !          1206: {
        !          1207:   struct SingleRequest *k = &data->req;
        !          1208:   CURLcode result;
        !          1209:   int didwhat = 0;
        !          1210: 
        !          1211:   curl_socket_t fd_read;
        !          1212:   curl_socket_t fd_write;
        !          1213:   int select_res = conn->cselect_bits;
        !          1214: 
        !          1215:   conn->cselect_bits = 0;
        !          1216: 
        !          1217:   /* only use the proper socket if the *_HOLD bit is not set simultaneously as
        !          1218:      then we are in rate limiting state in that transfer direction */
        !          1219: 
        !          1220:   if((k->keepon & KEEP_RECVBITS) == KEEP_RECV)
        !          1221:     fd_read = conn->sockfd;
        !          1222:   else
        !          1223:     fd_read = CURL_SOCKET_BAD;
        !          1224: 
        !          1225:   if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
        !          1226:     fd_write = conn->writesockfd;
        !          1227:   else
        !          1228:     fd_write = CURL_SOCKET_BAD;
        !          1229: 
        !          1230:   if(conn->data->state.drain) {
        !          1231:     select_res |= CURL_CSELECT_IN;
        !          1232:     DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n"));
        !          1233:   }
        !          1234: 
        !          1235:   if(!select_res) /* Call for select()/poll() only, if read/write/error
        !          1236:                      status is not known. */
        !          1237:     select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);
        !          1238: 
        !          1239:   if(select_res == CURL_CSELECT_ERR) {
        !          1240:     failf(data, "select/poll returned error");
        !          1241:     return CURLE_SEND_ERROR;
        !          1242:   }
        !          1243: 
        !          1244:   /* We go ahead and do a read if we have a readable socket or if
        !          1245:      the stream was rewound (in which case we have data in a
        !          1246:      buffer) */
        !          1247:   if((k->keepon & KEEP_RECV) && (select_res & CURL_CSELECT_IN)) {
        !          1248:     result = readwrite_data(data, conn, k, &didwhat, done, comeback);
        !          1249:     if(result || *done)
        !          1250:       return result;
        !          1251:   }
        !          1252: 
        !          1253:   /* If we still have writing to do, we check if we have a writable socket. */
        !          1254:   if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
        !          1255:     /* write */
        !          1256: 
        !          1257:     result = readwrite_upload(data, conn, &didwhat);
        !          1258:     if(result)
        !          1259:       return result;
        !          1260:   }
        !          1261: 
        !          1262:   k->now = Curl_now();
        !          1263:   if(didwhat) {
        !          1264:     ;
        !          1265:   }
        !          1266:   else {
        !          1267:     /* no read no write, this is a timeout? */
        !          1268:     if(k->exp100 == EXP100_AWAITING_CONTINUE) {
        !          1269:       /* This should allow some time for the header to arrive, but only a
        !          1270:          very short time as otherwise it'll be too much wasted time too
        !          1271:          often. */
        !          1272: 
        !          1273:       /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status":
        !          1274: 
        !          1275:          Therefore, when a client sends this header field to an origin server
        !          1276:          (possibly via a proxy) from which it has never seen a 100 (Continue)
        !          1277:          status, the client SHOULD NOT wait for an indefinite period before
        !          1278:          sending the request body.
        !          1279: 
        !          1280:       */
        !          1281: 
        !          1282:       timediff_t ms = Curl_timediff(k->now, k->start100);
        !          1283:       if(ms >= data->set.expect_100_timeout) {
        !          1284:         /* we've waited long enough, continue anyway */
        !          1285:         k->exp100 = EXP100_SEND_DATA;
        !          1286:         k->keepon |= KEEP_SEND;
        !          1287:         Curl_expire_done(data, EXPIRE_100_TIMEOUT);
        !          1288:         infof(data, "Done waiting for 100-continue\n");
        !          1289:       }
        !          1290:     }
        !          1291:   }
        !          1292: 
        !          1293:   if(Curl_pgrsUpdate(conn))
        !          1294:     result = CURLE_ABORTED_BY_CALLBACK;
        !          1295:   else
        !          1296:     result = Curl_speedcheck(data, k->now);
        !          1297:   if(result)
        !          1298:     return result;
        !          1299: 
        !          1300:   if(k->keepon) {
        !          1301:     if(0 > Curl_timeleft(data, &k->now, FALSE)) {
        !          1302:       if(k->size != -1) {
        !          1303:         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
        !          1304:               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
        !          1305:               CURL_FORMAT_CURL_OFF_T " bytes received",
        !          1306:               Curl_timediff(k->now, data->progress.t_startsingle),
        !          1307:               k->bytecount, k->size);
        !          1308:       }
        !          1309:       else {
        !          1310:         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
        !          1311:               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " bytes received",
        !          1312:               Curl_timediff(k->now, data->progress.t_startsingle),
        !          1313:               k->bytecount);
        !          1314:       }
        !          1315:       return CURLE_OPERATION_TIMEDOUT;
        !          1316:     }
        !          1317:   }
        !          1318:   else {
        !          1319:     /*
        !          1320:      * The transfer has been performed. Just make some general checks before
        !          1321:      * returning.
        !          1322:      */
        !          1323: 
        !          1324:     if(!(data->set.opt_no_body) && (k->size != -1) &&
        !          1325:        (k->bytecount != k->size) &&
        !          1326: #ifdef CURL_DO_LINEEND_CONV
        !          1327:        /* Most FTP servers don't adjust their file SIZE response for CRLFs,
        !          1328:           so we'll check to see if the discrepancy can be explained
        !          1329:           by the number of CRLFs we've changed to LFs.
        !          1330:        */
        !          1331:        (k->bytecount != (k->size + data->state.crlf_conversions)) &&
        !          1332: #endif /* CURL_DO_LINEEND_CONV */
        !          1333:        !k->newurl) {
        !          1334:       failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
        !          1335:             " bytes remaining to read", k->size - k->bytecount);
        !          1336:       return CURLE_PARTIAL_FILE;
        !          1337:     }
        !          1338:     if(!(data->set.opt_no_body) && k->chunk &&
        !          1339:        (conn->chunk.state != CHUNK_STOP)) {
        !          1340:       /*
        !          1341:        * In chunked mode, return an error if the connection is closed prior to
        !          1342:        * the empty (terminating) chunk is read.
        !          1343:        *
        !          1344:        * The condition above used to check for
        !          1345:        * conn->proto.http->chunk.datasize != 0 which is true after reading
        !          1346:        * *any* chunk, not just the empty chunk.
        !          1347:        *
        !          1348:        */
        !          1349:       failf(data, "transfer closed with outstanding read data remaining");
        !          1350:       return CURLE_PARTIAL_FILE;
        !          1351:     }
        !          1352:     if(Curl_pgrsUpdate(conn))
        !          1353:       return CURLE_ABORTED_BY_CALLBACK;
        !          1354:   }
        !          1355: 
        !          1356:   /* Now update the "done" boolean we return */
        !          1357:   *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
        !          1358:                             KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
        !          1359: 
        !          1360:   return CURLE_OK;
        !          1361: }
        !          1362: 
        !          1363: /*
        !          1364:  * Curl_single_getsock() gets called by the multi interface code when the app
        !          1365:  * has requested to get the sockets for the current connection. This function
        !          1366:  * will then be called once for every connection that the multi interface
        !          1367:  * keeps track of. This function will only be called for connections that are
        !          1368:  * in the proper state to have this information available.
        !          1369:  */
        !          1370: int Curl_single_getsock(const struct connectdata *conn,
        !          1371:                         curl_socket_t *sock)
        !          1372: {
        !          1373:   const struct Curl_easy *data = conn->data;
        !          1374:   int bitmap = GETSOCK_BLANK;
        !          1375:   unsigned sockindex = 0;
        !          1376: 
        !          1377:   if(conn->handler->perform_getsock)
        !          1378:     return conn->handler->perform_getsock(conn, sock);
        !          1379: 
        !          1380:   /* don't include HOLD and PAUSE connections */
        !          1381:   if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
        !          1382: 
        !          1383:     DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
        !          1384: 
        !          1385:     bitmap |= GETSOCK_READSOCK(sockindex);
        !          1386:     sock[sockindex] = conn->sockfd;
        !          1387:   }
        !          1388: 
        !          1389:   /* don't include HOLD and PAUSE connections */
        !          1390:   if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
        !          1391: 
        !          1392:     if((conn->sockfd != conn->writesockfd) ||
        !          1393:        bitmap == GETSOCK_BLANK) {
        !          1394:       /* only if they are not the same socket and we have a readable
        !          1395:          one, we increase index */
        !          1396:       if(bitmap != GETSOCK_BLANK)
        !          1397:         sockindex++; /* increase index if we need two entries */
        !          1398: 
        !          1399:       DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
        !          1400: 
        !          1401:       sock[sockindex] = conn->writesockfd;
        !          1402:     }
        !          1403: 
        !          1404:     bitmap |= GETSOCK_WRITESOCK(sockindex);
        !          1405:   }
        !          1406: 
        !          1407:   return bitmap;
        !          1408: }
        !          1409: 
        !          1410: /* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
        !          1411:    which means this gets called once for each subsequent redirect etc */
        !          1412: void Curl_init_CONNECT(struct Curl_easy *data)
        !          1413: {
        !          1414:   data->state.fread_func = data->set.fread_func_set;
        !          1415:   data->state.in = data->set.in_set;
        !          1416: }
        !          1417: 
        !          1418: /*
        !          1419:  * Curl_pretransfer() is called immediately before a transfer starts, and only
        !          1420:  * once for one transfer no matter if it has redirects or do multi-pass
        !          1421:  * authentication etc.
        !          1422:  */
        !          1423: CURLcode Curl_pretransfer(struct Curl_easy *data)
        !          1424: {
        !          1425:   CURLcode result;
        !          1426: 
        !          1427:   if(!data->change.url && !data->set.uh) {
        !          1428:     /* we can't do anything without URL */
        !          1429:     failf(data, "No URL set!");
        !          1430:     return CURLE_URL_MALFORMAT;
        !          1431:   }
        !          1432: 
        !          1433:   /* since the URL may have been redirected in a previous use of this handle */
        !          1434:   if(data->change.url_alloc) {
        !          1435:     /* the already set URL is allocated, free it first! */
        !          1436:     Curl_safefree(data->change.url);
        !          1437:     data->change.url_alloc = FALSE;
        !          1438:   }
        !          1439: 
        !          1440:   if(!data->change.url && data->set.uh) {
        !          1441:     CURLUcode uc;
        !          1442:     uc = curl_url_get(data->set.uh,
        !          1443:                         CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
        !          1444:     if(uc) {
        !          1445:       failf(data, "No URL set!");
        !          1446:       return CURLE_URL_MALFORMAT;
        !          1447:     }
        !          1448:   }
        !          1449: 
        !          1450:   data->change.url = data->set.str[STRING_SET_URL];
        !          1451: 
        !          1452:   /* Init the SSL session ID cache here. We do it here since we want to do it
        !          1453:      after the *_setopt() calls (that could specify the size of the cache) but
        !          1454:      before any transfer takes place. */
        !          1455:   result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
        !          1456:   if(result)
        !          1457:     return result;
        !          1458: 
        !          1459:   data->state.wildcardmatch = data->set.wildcard_enabled;
        !          1460:   data->set.followlocation = 0; /* reset the location-follow counter */
        !          1461:   data->state.this_is_a_follow = FALSE; /* reset this */
        !          1462:   data->state.errorbuf = FALSE; /* no error has occurred */
        !          1463:   data->state.httpversion = 0; /* don't assume any particular server version */
        !          1464: 
        !          1465:   data->state.authproblem = FALSE;
        !          1466:   data->state.authhost.want = data->set.httpauth;
        !          1467:   data->state.authproxy.want = data->set.proxyauth;
        !          1468:   Curl_safefree(data->info.wouldredirect);
        !          1469:   data->info.wouldredirect = NULL;
        !          1470: 
        !          1471:   if(data->set.httpreq == HTTPREQ_PUT)
        !          1472:     data->state.infilesize = data->set.filesize;
        !          1473:   else if((data->set.httpreq != HTTPREQ_GET) &&
        !          1474:           (data->set.httpreq != HTTPREQ_HEAD)) {
        !          1475:     data->state.infilesize = data->set.postfieldsize;
        !          1476:     if(data->set.postfields && (data->state.infilesize == -1))
        !          1477:       data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
        !          1478:   }
        !          1479:   else
        !          1480:     data->state.infilesize = 0;
        !          1481: 
        !          1482:   /* If there is a list of cookie files to read, do it now! */
        !          1483:   if(data->change.cookielist)
        !          1484:     Curl_cookie_loadfiles(data);
        !          1485: 
        !          1486:   /* If there is a list of host pairs to deal with */
        !          1487:   if(data->change.resolve)
        !          1488:     result = Curl_loadhostpairs(data);
        !          1489: 
        !          1490:   if(!result) {
        !          1491:     /* Allow data->set.use_port to set which port to use. This needs to be
        !          1492:      * disabled for example when we follow Location: headers to URLs using
        !          1493:      * different ports! */
        !          1494:     data->state.allow_port = TRUE;
        !          1495: 
        !          1496: #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
        !          1497:     /*************************************************************
        !          1498:      * Tell signal handler to ignore SIGPIPE
        !          1499:      *************************************************************/
        !          1500:     if(!data->set.no_signal)
        !          1501:       data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
        !          1502: #endif
        !          1503: 
        !          1504:     Curl_initinfo(data); /* reset session-specific information "variables" */
        !          1505:     Curl_pgrsResetTransferSizes(data);
        !          1506:     Curl_pgrsStartNow(data);
        !          1507: 
        !          1508:     /* In case the handle is re-used and an authentication method was picked
        !          1509:        in the session we need to make sure we only use the one(s) we now
        !          1510:        consider to be fine */
        !          1511:     data->state.authhost.picked &= data->state.authhost.want;
        !          1512:     data->state.authproxy.picked &= data->state.authproxy.want;
        !          1513: 
        !          1514: #ifndef CURL_DISABLE_FTP
        !          1515:     if(data->state.wildcardmatch) {
        !          1516:       struct WildcardData *wc = &data->wildcard;
        !          1517:       if(wc->state < CURLWC_INIT) {
        !          1518:         result = Curl_wildcard_init(wc); /* init wildcard structures */
        !          1519:         if(result)
        !          1520:           return CURLE_OUT_OF_MEMORY;
        !          1521:       }
        !          1522:     }
        !          1523: #endif
        !          1524:     Curl_http2_init_state(&data->state);
        !          1525:   }
        !          1526: 
        !          1527:   return result;
        !          1528: }
        !          1529: 
        !          1530: /*
        !          1531:  * Curl_posttransfer() is called immediately after a transfer ends
        !          1532:  */
        !          1533: CURLcode Curl_posttransfer(struct Curl_easy *data)
        !          1534: {
        !          1535: #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
        !          1536:   /* restore the signal handler for SIGPIPE before we get back */
        !          1537:   if(!data->set.no_signal)
        !          1538:     signal(SIGPIPE, data->state.prev_signal);
        !          1539: #else
        !          1540:   (void)data; /* unused parameter */
        !          1541: #endif
        !          1542: 
        !          1543:   return CURLE_OK;
        !          1544: }
        !          1545: 
        !          1546: /*
        !          1547:  * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
        !          1548:  * as given by the remote server and set up the new URL to request.
        !          1549:  *
        !          1550:  * This function DOES NOT FREE the given url.
        !          1551:  */
        !          1552: CURLcode Curl_follow(struct Curl_easy *data,
        !          1553:                      char *newurl,    /* the Location: string */
        !          1554:                      followtype type) /* see transfer.h */
        !          1555: {
        !          1556: #ifdef CURL_DISABLE_HTTP
        !          1557:   (void)data;
        !          1558:   (void)newurl;
        !          1559:   (void)type;
        !          1560:   /* Location: following will not happen when HTTP is disabled */
        !          1561:   return CURLE_TOO_MANY_REDIRECTS;
        !          1562: #else
        !          1563: 
        !          1564:   /* Location: redirect */
        !          1565:   bool disallowport = FALSE;
        !          1566:   bool reachedmax = FALSE;
        !          1567:   CURLUcode uc;
        !          1568: 
        !          1569:   if(type == FOLLOW_REDIR) {
        !          1570:     if((data->set.maxredirs != -1) &&
        !          1571:        (data->set.followlocation >= data->set.maxredirs)) {
        !          1572:       reachedmax = TRUE;
        !          1573:       type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
        !          1574:                              to URL */
        !          1575:     }
        !          1576:     else {
        !          1577:       /* mark the next request as a followed location: */
        !          1578:       data->state.this_is_a_follow = TRUE;
        !          1579: 
        !          1580:       data->set.followlocation++; /* count location-followers */
        !          1581: 
        !          1582:       if(data->set.http_auto_referer) {
        !          1583:         /* We are asked to automatically set the previous URL as the referer
        !          1584:            when we get the next URL. We pick the ->url field, which may or may
        !          1585:            not be 100% correct */
        !          1586: 
        !          1587:         if(data->change.referer_alloc) {
        !          1588:           Curl_safefree(data->change.referer);
        !          1589:           data->change.referer_alloc = FALSE;
        !          1590:         }
        !          1591: 
        !          1592:         data->change.referer = strdup(data->change.url);
        !          1593:         if(!data->change.referer)
        !          1594:           return CURLE_OUT_OF_MEMORY;
        !          1595:         data->change.referer_alloc = TRUE; /* yes, free this later */
        !          1596:       }
        !          1597:     }
        !          1598:   }
        !          1599: 
        !          1600:   if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
        !          1601:     /* This is an absolute URL, don't allow the custom port number */
        !          1602:     disallowport = TRUE;
        !          1603: 
        !          1604:   DEBUGASSERT(data->state.uh);
        !          1605:   uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
        !          1606:                     (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
        !          1607:                     ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) );
        !          1608:   if(uc) {
        !          1609:     if(type != FOLLOW_FAKE)
        !          1610:       return Curl_uc_to_curlcode(uc);
        !          1611: 
        !          1612:     /* the URL could not be parsed for some reason, but since this is FAKE
        !          1613:        mode, just duplicate the field as-is */
        !          1614:     newurl = strdup(newurl);
        !          1615:     if(!newurl)
        !          1616:       return CURLE_OUT_OF_MEMORY;
        !          1617:   }
        !          1618:   else {
        !          1619: 
        !          1620:     uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
        !          1621:     if(uc)
        !          1622:       return Curl_uc_to_curlcode(uc);
        !          1623:   }
        !          1624: 
        !          1625:   if(type == FOLLOW_FAKE) {
        !          1626:     /* we're only figuring out the new url if we would've followed locations
        !          1627:        but now we're done so we can get out! */
        !          1628:     data->info.wouldredirect = newurl;
        !          1629: 
        !          1630:     if(reachedmax) {
        !          1631:       failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
        !          1632:       return CURLE_TOO_MANY_REDIRECTS;
        !          1633:     }
        !          1634:     return CURLE_OK;
        !          1635:   }
        !          1636: 
        !          1637:   if(disallowport)
        !          1638:     data->state.allow_port = FALSE;
        !          1639: 
        !          1640:   if(data->change.url_alloc)
        !          1641:     Curl_safefree(data->change.url);
        !          1642: 
        !          1643:   data->change.url = newurl;
        !          1644:   data->change.url_alloc = TRUE;
        !          1645: 
        !          1646:   infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
        !          1647: 
        !          1648:   /*
        !          1649:    * We get here when the HTTP code is 300-399 (and 401). We need to perform
        !          1650:    * differently based on exactly what return code there was.
        !          1651:    *
        !          1652:    * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
        !          1653:    * a HTTP (proxy-) authentication scheme other than Basic.
        !          1654:    */
        !          1655:   switch(data->info.httpcode) {
        !          1656:     /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
        !          1657:        Authorization: XXXX header in the HTTP request code snippet */
        !          1658:     /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
        !          1659:        Proxy-Authorization: XXXX header in the HTTP request code snippet */
        !          1660:     /* 300 - Multiple Choices */
        !          1661:     /* 306 - Not used */
        !          1662:     /* 307 - Temporary Redirect */
        !          1663:   default:  /* for all above (and the unknown ones) */
        !          1664:     /* Some codes are explicitly mentioned since I've checked RFC2616 and they
        !          1665:      * seem to be OK to POST to.
        !          1666:      */
        !          1667:     break;
        !          1668:   case 301: /* Moved Permanently */
        !          1669:     /* (quote from RFC7231, section 6.4.2)
        !          1670:      *
        !          1671:      * Note: For historical reasons, a user agent MAY change the request
        !          1672:      * method from POST to GET for the subsequent request.  If this
        !          1673:      * behavior is undesired, the 307 (Temporary Redirect) status code
        !          1674:      * can be used instead.
        !          1675:      *
        !          1676:      * ----
        !          1677:      *
        !          1678:      * Many webservers expect this, so these servers often answers to a POST
        !          1679:      * request with an error page. To be sure that libcurl gets the page that
        !          1680:      * most user agents would get, libcurl has to force GET.
        !          1681:      *
        !          1682:      * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
        !          1683:      * can be overridden with CURLOPT_POSTREDIR.
        !          1684:      */
        !          1685:     if((data->set.httpreq == HTTPREQ_POST
        !          1686:         || data->set.httpreq == HTTPREQ_POST_FORM
        !          1687:         || data->set.httpreq == HTTPREQ_POST_MIME)
        !          1688:        && !(data->set.keep_post & CURL_REDIR_POST_301)) {
        !          1689:       infof(data, "Switch from POST to GET\n");
        !          1690:       data->set.httpreq = HTTPREQ_GET;
        !          1691:     }
        !          1692:     break;
        !          1693:   case 302: /* Found */
        !          1694:     /* (quote from RFC7231, section 6.4.3)
        !          1695:      *
        !          1696:      * Note: For historical reasons, a user agent MAY change the request
        !          1697:      * method from POST to GET for the subsequent request.  If this
        !          1698:      * behavior is undesired, the 307 (Temporary Redirect) status code
        !          1699:      * can be used instead.
        !          1700:      *
        !          1701:      * ----
        !          1702:      *
        !          1703:      * Many webservers expect this, so these servers often answers to a POST
        !          1704:      * request with an error page. To be sure that libcurl gets the page that
        !          1705:      * most user agents would get, libcurl has to force GET.
        !          1706:      *
        !          1707:      * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
        !          1708:      * can be overridden with CURLOPT_POSTREDIR.
        !          1709:      */
        !          1710:     if((data->set.httpreq == HTTPREQ_POST
        !          1711:         || data->set.httpreq == HTTPREQ_POST_FORM
        !          1712:         || data->set.httpreq == HTTPREQ_POST_MIME)
        !          1713:        && !(data->set.keep_post & CURL_REDIR_POST_302)) {
        !          1714:       infof(data, "Switch from POST to GET\n");
        !          1715:       data->set.httpreq = HTTPREQ_GET;
        !          1716:     }
        !          1717:     break;
        !          1718: 
        !          1719:   case 303: /* See Other */
        !          1720:     /* 'See Other' location is not the resource but a substitute for the
        !          1721:      * resource. In this case we switch the method to GET/HEAD, unless the
        !          1722:      * method is POST and the user specified to keep it as POST.
        !          1723:      * https://github.com/curl/curl/issues/5237#issuecomment-614641049
        !          1724:      */
        !          1725:     if(data->set.httpreq != HTTPREQ_GET &&
        !          1726:        ((data->set.httpreq != HTTPREQ_POST &&
        !          1727:          data->set.httpreq != HTTPREQ_POST_FORM &&
        !          1728:          data->set.httpreq != HTTPREQ_POST_MIME) ||
        !          1729:         !(data->set.keep_post & CURL_REDIR_POST_303))) {
        !          1730:       data->set.httpreq = HTTPREQ_GET;
        !          1731:       data->set.upload = false;
        !          1732:       infof(data, "Switch to %s\n",
        !          1733:             data->set.opt_no_body?"HEAD":"GET");
        !          1734:     }
        !          1735:     break;
        !          1736:   case 304: /* Not Modified */
        !          1737:     /* 304 means we did a conditional request and it was "Not modified".
        !          1738:      * We shouldn't get any Location: header in this response!
        !          1739:      */
        !          1740:     break;
        !          1741:   case 305: /* Use Proxy */
        !          1742:     /* (quote from RFC2616, section 10.3.6):
        !          1743:      * "The requested resource MUST be accessed through the proxy given
        !          1744:      * by the Location field. The Location field gives the URI of the
        !          1745:      * proxy.  The recipient is expected to repeat this single request
        !          1746:      * via the proxy. 305 responses MUST only be generated by origin
        !          1747:      * servers."
        !          1748:      */
        !          1749:     break;
        !          1750:   }
        !          1751:   Curl_pgrsTime(data, TIMER_REDIRECT);
        !          1752:   Curl_pgrsResetTransferSizes(data);
        !          1753: 
        !          1754:   return CURLE_OK;
        !          1755: #endif /* CURL_DISABLE_HTTP */
        !          1756: }
        !          1757: 
        !          1758: /* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
        !          1759: 
        !          1760:    NOTE: that the *url is malloc()ed. */
        !          1761: CURLcode Curl_retry_request(struct connectdata *conn,
        !          1762:                             char **url)
        !          1763: {
        !          1764:   struct Curl_easy *data = conn->data;
        !          1765:   bool retry = FALSE;
        !          1766:   *url = NULL;
        !          1767: 
        !          1768:   /* if we're talking upload, we can't do the checks below, unless the protocol
        !          1769:      is HTTP as when uploading over HTTP we will still get a response */
        !          1770:   if(data->set.upload &&
        !          1771:      !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
        !          1772:     return CURLE_OK;
        !          1773: 
        !          1774:   if((data->req.bytecount + data->req.headerbytecount == 0) &&
        !          1775:       conn->bits.reuse &&
        !          1776:       (!data->set.opt_no_body
        !          1777:         || (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
        !          1778:       (data->set.rtspreq != RTSPREQ_RECEIVE))
        !          1779:     /* We got no data, we attempted to re-use a connection. For HTTP this
        !          1780:        can be a retry so we try again regardless if we expected a body.
        !          1781:        For other protocols we only try again only if we expected a body.
        !          1782: 
        !          1783:        This might happen if the connection was left alive when we were
        !          1784:        done using it before, but that was closed when we wanted to read from
        !          1785:        it again. Bad luck. Retry the same request on a fresh connect! */
        !          1786:     retry = TRUE;
        !          1787:   else if(data->state.refused_stream &&
        !          1788:           (data->req.bytecount + data->req.headerbytecount == 0) ) {
        !          1789:     /* This was sent on a refused stream, safe to rerun. A refused stream
        !          1790:        error can typically only happen on HTTP/2 level if the stream is safe
        !          1791:        to issue again, but the nghttp2 API can deliver the message to other
        !          1792:        streams as well, which is why this adds the check the data counters
        !          1793:        too. */
        !          1794:     infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
        !          1795:     data->state.refused_stream = FALSE; /* clear again */
        !          1796:     retry = TRUE;
        !          1797:   }
        !          1798:   if(retry) {
        !          1799: #define CONN_MAX_RETRIES 5
        !          1800:     if(conn->retrycount++ >= CONN_MAX_RETRIES) {
        !          1801:       failf(data, "Connection died, tried %d times before giving up",
        !          1802:             CONN_MAX_RETRIES);
        !          1803:       return CURLE_SEND_ERROR;
        !          1804:     }
        !          1805:     infof(conn->data, "Connection died, retrying a fresh connect\n");
        !          1806:     *url = strdup(conn->data->change.url);
        !          1807:     if(!*url)
        !          1808:       return CURLE_OUT_OF_MEMORY;
        !          1809: 
        !          1810:     connclose(conn, "retry"); /* close this connection */
        !          1811:     conn->bits.retry = TRUE; /* mark this as a connection we're about
        !          1812:                                 to retry. Marking it this way should
        !          1813:                                 prevent i.e HTTP transfers to return
        !          1814:                                 error just because nothing has been
        !          1815:                                 transferred! */
        !          1816: 
        !          1817: 
        !          1818:     if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
        !          1819:       if(data->req.writebytecount) {
        !          1820:         CURLcode result = Curl_readrewind(conn);
        !          1821:         if(result) {
        !          1822:           Curl_safefree(*url);
        !          1823:           return result;
        !          1824:         }
        !          1825:       }
        !          1826:     }
        !          1827:   }
        !          1828:   return CURLE_OK;
        !          1829: }
        !          1830: 
        !          1831: /*
        !          1832:  * Curl_setup_transfer() is called to setup some basic properties for the
        !          1833:  * upcoming transfer.
        !          1834:  */
        !          1835: void
        !          1836: Curl_setup_transfer(
        !          1837:   struct Curl_easy *data,   /* transfer */
        !          1838:   int sockindex,            /* socket index to read from or -1 */
        !          1839:   curl_off_t size,          /* -1 if unknown at this point */
        !          1840:   bool getheader,           /* TRUE if header parsing is wanted */
        !          1841:   int writesockindex        /* socket index to write to, it may very well be
        !          1842:                                the same we read from. -1 disables */
        !          1843:   )
        !          1844: {
        !          1845:   struct SingleRequest *k = &data->req;
        !          1846:   struct connectdata *conn = data->conn;
        !          1847:   struct HTTP *http = data->req.protop;
        !          1848:   bool httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
        !          1849:                       (http->sending == HTTPSEND_REQUEST));
        !          1850:   DEBUGASSERT(conn != NULL);
        !          1851:   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
        !          1852: 
        !          1853:   if(conn->bits.multiplex || conn->httpversion == 20 || httpsending) {
        !          1854:     /* when multiplexing, the read/write sockets need to be the same! */
        !          1855:     conn->sockfd = sockindex == -1 ?
        !          1856:       ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
        !          1857:       conn->sock[sockindex];
        !          1858:     conn->writesockfd = conn->sockfd;
        !          1859:     if(httpsending)
        !          1860:       /* special and very HTTP-specific */
        !          1861:       writesockindex = FIRSTSOCKET;
        !          1862:   }
        !          1863:   else {
        !          1864:     conn->sockfd = sockindex == -1 ?
        !          1865:       CURL_SOCKET_BAD : conn->sock[sockindex];
        !          1866:     conn->writesockfd = writesockindex == -1 ?
        !          1867:       CURL_SOCKET_BAD:conn->sock[writesockindex];
        !          1868:   }
        !          1869:   k->getheader = getheader;
        !          1870: 
        !          1871:   k->size = size;
        !          1872: 
        !          1873:   /* The code sequence below is placed in this function just because all
        !          1874:      necessary input is not always known in do_complete() as this function may
        !          1875:      be called after that */
        !          1876: 
        !          1877:   if(!k->getheader) {
        !          1878:     k->header = FALSE;
        !          1879:     if(size > 0)
        !          1880:       Curl_pgrsSetDownloadSize(data, size);
        !          1881:   }
        !          1882:   /* we want header and/or body, if neither then don't do this! */
        !          1883:   if(k->getheader || !data->set.opt_no_body) {
        !          1884: 
        !          1885:     if(sockindex != -1)
        !          1886:       k->keepon |= KEEP_RECV;
        !          1887: 
        !          1888:     if(writesockindex != -1) {
        !          1889:       /* HTTP 1.1 magic:
        !          1890: 
        !          1891:          Even if we require a 100-return code before uploading data, we might
        !          1892:          need to write data before that since the REQUEST may not have been
        !          1893:          finished sent off just yet.
        !          1894: 
        !          1895:          Thus, we must check if the request has been sent before we set the
        !          1896:          state info where we wait for the 100-return code
        !          1897:       */
        !          1898:       if((data->state.expect100header) &&
        !          1899:          (conn->handler->protocol&PROTO_FAMILY_HTTP) &&
        !          1900:          (http->sending == HTTPSEND_BODY)) {
        !          1901:         /* wait with write until we either got 100-continue or a timeout */
        !          1902:         k->exp100 = EXP100_AWAITING_CONTINUE;
        !          1903:         k->start100 = Curl_now();
        !          1904: 
        !          1905:         /* Set a timeout for the multi interface. Add the inaccuracy margin so
        !          1906:            that we don't fire slightly too early and get denied to run. */
        !          1907:         Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
        !          1908:       }
        !          1909:       else {
        !          1910:         if(data->state.expect100header)
        !          1911:           /* when we've sent off the rest of the headers, we must await a
        !          1912:              100-continue but first finish sending the request */
        !          1913:           k->exp100 = EXP100_SENDING_REQUEST;
        !          1914: 
        !          1915:         /* enable the write bit when we're not waiting for continue */
        !          1916:         k->keepon |= KEEP_SEND;
        !          1917:       }
        !          1918:     } /* if(writesockindex != -1) */
        !          1919:   } /* if(k->getheader || !data->set.opt_no_body) */
        !          1920: 
        !          1921: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>