Skip to content
transfer.c 91.2 KiB
Newer Older
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://curl.haxx.se/docs/copyright.html.
Daniel Stenberg's avatar
Daniel Stenberg committed
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
Daniel Stenberg's avatar
Daniel Stenberg committed
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
Daniel Stenberg's avatar
Daniel Stenberg committed
 * $Id$
 ***************************************************************************/
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>

#include "strtoofft.h"
#include "strequal.h"
#ifdef WIN32
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
Gisle Vanem's avatar
Gisle Vanem committed
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>

#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif

#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif

#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif


#include "urldata.h"
#include <curl/curl.h>
#include "netrc.h"

#include "content_encoding.h"
#include "transfer.h"
#include "sendf.h"
#include "speedcheck.h"
#include "progress.h"
#include "http.h"
#include "url.h"
#include "getinfo.h"
#include "http_digest.h"
#include "share.h"
#include "curl_memory.h"
#include "select.h"
#include "easyif.h" /* for Curl_convert_to_network prototype */

#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>

/* The last #include file should be: */
#include "memdebug.h"

#define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */

#ifndef CURL_DISABLE_HTTP
static CURLcode readwrite_http_headers(struct SessionHandle *data,
                                       struct connectdata *conn,
                                       struct SingleRequest *k,
                                       ssize_t *nread,
                                       bool *stop_reading);
#endif /* CURL_DISABLE_HTTP */
/*
 * This function will call the read callback to fill our buffer with data
 * to upload.
 */
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
  struct SessionHandle *data = conn->data;
  size_t buffersize = (size_t)bytes;
#ifdef CURL_DOES_CONVERSIONS
  if((conn->protocol&PROT_HTTP) &&
     (data->state.proto.http->sending == HTTPSEND_REQUEST)) {
    /* We're sending the HTTP request headers, not the data.
       Remember that so we don't re-translate them into garbage. */
    sending_http_headers = TRUE;
#endif

  if(data->req.upload_chunky) {
    /* if chunked Transfer-Encoding */
    buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
    data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
  }
  /* this function returns a size_t, so we typecast to int to prevent warnings
     with picky compilers */
  nread = (int)conn->fread_func(data->req.upload_fromhere, 1,
    failf(data, "operation aborted by callback");
  else if(nread == CURL_READFUNC_PAUSE) {
    struct SingleRequest *k = &data->req;
    /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
    k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
    if(data->req.upload_chunky) {
      /* Back out the preallocation done above */
      data->req.upload_fromhere -= (8 + 2);
    }
Yang Tse's avatar
Yang Tse committed
    return CURLE_OK; /* nothing was read */
  else if((size_t)nread > buffersize) {
    /* the read function returned a too large value */
    failf(data, "read function returned funny value");
  if(!data->req.forbidchunk && data->req.upload_chunky) {
     *    build chunk:
     *
     *        <HEX SIZE> CRLF
     *        <DATA> CRLF
     */
    /* On non-ASCII platforms the <DATA> may or may not be
       translated based on set.prefer_ascii while the protocol
       portion must always be translated to the network encoding.
       To further complicate matters, line end conversion might be
       done later on, so we need to prevent CRLFs from becoming
       CRCRLFs if that's the case.  To do this we use bare LFs
       here, knowing they'll become CRLFs later on.
     */

    const char *endofline_native;
    const char *endofline_network;
    int hexlen;
#ifdef CURL_DO_LINEEND_CONV
    if((data->set.crlf) || (data->set.prefer_ascii)) {
#else
Loading
Loading full blame…