Skip to content
url.c 154 KiB
Newer Older
/*
 * do_init() inits the readwrite session. This is inited each time (in the DO
 * function before the protocol-specific DO functions are invoked) for a
 * transfer, sometimes multiple times on the same SessionHandle. Make sure
 * nothing in here depends on stuff that are setup dynamically for the
 * transfer.
 */

static CURLcode do_init(struct connectdata *conn)
{
  struct SessionHandle *data = conn->data;

  conn->bits.done = FALSE; /* Curl_done() is not called yet */
  conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
  data->state.expect100header = FALSE;
  if(data->set.opt_no_body)
    /* in HTTP lingo, no body means using the HEAD request... */
    data->set.httpreq = HTTPREQ_HEAD;
  else if(HTTPREQ_HEAD == data->set.httpreq)
    /* ... but if unset there really is no perfect method that is the
       "opposite" of HEAD but in reality most people probably think GET
       then. The important thing is that we can't let it remain HEAD if the
       opt_no_body is set FALSE since then we'll behave wrong when getting
       HTTP. */
    data->set.httpreq = HTTPREQ_GET;

  /* NB: the content encoding software depends on this initialization */
  Curl_easy_initHandleData(data);

  k->start = Curl_tvnow(); /* start time */
  k->now = k->start;   /* current time is now */
  k->header = TRUE; /* assume header */

  k->bytecount = 0;

  k->buf = data->state.buffer;
  k->uploadbuf = data->state.uploadbuffer;
  k->hbufp = data->state.headerbuff;
  k->ignorebody=FALSE;

  Curl_pgrsTime(data, TIMER_PRETRANSFER);
  Curl_speedinit(data);

  Curl_pgrsSetUploadCounter(data, 0);
  Curl_pgrsSetDownloadCounter(data, 0);

  return CURLE_OK;
}

/*
 * do_complete is called when the DO actions are complete.
 *
 * We init chunking and trailer bits to their default values here immediately
 * before receiving any header data for the current request in the pipeline.
 */
static void do_complete(struct connectdata *conn)
{
  conn->data->req.chunk=FALSE;
  conn->data->req.trailerhdrpresent=FALSE;
  conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
                               conn->sockfd:conn->writesockfd)+1;
CURLcode Curl_do(struct connectdata **connp, bool *done)
  CURLcode result=CURLE_OK;
  struct connectdata *conn = *connp;
  struct SessionHandle *data = conn->data;
  /* setup and init stuff before DO starts, in preparing for the transfer */
  do_init(conn);
    /* generic protocol-specific function pointer set in curl_connect() */
    result = conn->handler->do_it(conn, done);
    /* This was formerly done in transfer.c, but we better do it here */
    if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
        /*
         * If the connection is using an easy handle, call reconnect
         * to re-establish the connection.  Otherwise, let the multi logic
         * figure out how to re-establish the connection.
         */
        if(!data->multi) {
          result = Curl_reconnect_request(connp);
          if(result == CURLE_OK) {
            /* ... finally back to actually retry the DO phase */
            result = conn->handler->do_it(conn, done);
    if((result == CURLE_OK) && *done)
      /* do_complete must be called after the protocol-specific DO function */
CURLcode Curl_do_more(struct connectdata *conn)
{
  CURLcode result=CURLE_OK;

  if(conn->handler->do_more)
    result = conn->handler->do_more(conn);
  if(result == CURLE_OK)
    /* do_complete must be called after the protocol-specific DO function */
    do_complete(conn);


/* Called on connect, and if there's already a protocol-specific struct
   allocated for a different connection, this frees it that it can be setup
   properly later on. */
void Curl_reset_reqproto(struct connectdata *conn)
{
  struct SessionHandle *data = conn->data;
  if(data->state.proto.generic && data->state.current_conn != conn) {
    free(data->state.proto.generic);
    data->state.proto.generic = NULL;