Skip to content
url.c 67 KiB
Newer Older
    free(proxydup); /* free the duplicate pointer and not the modified */
  }

  /*************************************************************
   * Check the current list of connections to see if we can
   * re-use an already existing one or if we have to create a
   * new one.
   *************************************************************/

  /* reuse_fresh is set TRUE if we are told to use a fresh connection
     by force */
  if(!data->bits.reuse_fresh &&
     ConnectionExists(data, conn, &conn_temp)) {
    /*
     * We already have a connection for this, we got the former connection
     * in the conn_temp variable and thus we need to cleanup the one we
     * just allocated before we can move along and use the previously
     * existing one.
     */
    struct connectdata *old_conn = conn;
    char *path = old_conn->path; /* setup the current path pointer properly */
    if(old_conn->proxyhost)
      free(old_conn->proxyhost);
    conn = conn_temp;        /* use this connection from now on */

    /* we need these pointers if we speak over a proxy */
    conn->name = conn->gname;
    conn->hostname = old_conn->gname;
    conn->path = path;       /* use this one */

    /* The 'ppath' may have been advanced a few steps from the 'path' start
       point. We must also advance our new pointer as many steps as the
       previous one was! This was the cause of the multiple ftp file bug
       found on May 9 2001 libcurl 7.7.3 */
    conn->ppath = (old_conn->ppath - old_conn->path)+path;

    free(old_conn->path);    /* free the previous path pointer */
Daniel Stenberg's avatar
Daniel Stenberg committed
    conn->bits.reuse = TRUE; /* yes, we're re-using here */
    conn->bits.chunk = FALSE; /* always assume not chunked unless told otherwise */
    conn->maxdownload = -1;  /* might have been used previously! */
    free(old_conn);          /* we don't need this anymore */

    *in_connect = conn;      /* return this instead! */

    infof(data, "Re-using existing connection! (#%d)\n", conn->connectindex);
  }
  else {
    /*
     * This is a brand new connection, so let's store it in the connection
     * cache of ours!
     */
    ConnectionStore(data, conn);
  }

Daniel Stenberg's avatar
Daniel Stenberg committed
  /*************************************************************
   * Resolve the name of the server or proxy
   *************************************************************/
  if(!data->bits.httpproxy) {
Daniel Stenberg's avatar
Daniel Stenberg committed
    /* If not connecting via a proxy, extract the port from the URL, if it is
     * there, thus overriding any defaults that might have been set above. */
    conn->port =  conn->remote_port; /* it is the same port */
    /* Resolve target host right on */
Daniel Stenberg's avatar
Daniel Stenberg committed
    if(!conn->hp) {
#ifdef ENABLE_IPV6
      /* it might already be set if reusing a connection */
      conn->hp = Curl_getaddrinfo(data, conn->name, conn->port);
      /* it might already be set if reusing a connection */
      conn->hp = Curl_gethost(data, conn->name, &conn->hostent_buf);
Daniel Stenberg's avatar
Daniel Stenberg committed
    }
    if(!conn->hp)
      failf(data, "Couldn't resolve host '%s'", conn->name);
      return CURLE_COULDNT_RESOLVE_HOST;
  else if(!conn->hp) {
    /* This is a proxy that hasn't been resolved yet. It may be resolved
       if we're reusing an existing connection. */
Daniel Stenberg's avatar
Daniel Stenberg committed

    /* resolve proxy */
#ifdef ENABLE_IPV6
      /* it might already be set if reusing a connection */
    conn->hp = Curl_getaddrinfo(data, conn->proxyhost, conn->port);
#else
    conn->hp = Curl_gethost(data, conn->proxyhost, &conn->hostent_buf);
Daniel Stenberg's avatar
Daniel Stenberg committed
    if(!conn->hp) {
      failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
      return CURLE_COULDNT_RESOLVE_PROXY;
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);
Daniel Stenberg's avatar
Daniel Stenberg committed

Daniel Stenberg's avatar
Daniel Stenberg committed
  /*************************************************************
   * Proxy authentication
   *************************************************************/
Daniel Stenberg's avatar
Daniel Stenberg committed
    char *authorization;
Daniel Stenberg's avatar
Daniel Stenberg committed
    snprintf(data->buffer, BUFSIZE, "%s:%s",
             data->proxyuser, data->proxypasswd);
    if(Curl_base64_encode(data->buffer, strlen(data->buffer),
                          &authorization) >= 0) {
      if(conn->allocptr.proxyuserpwd)
        free(conn->allocptr.proxyuserpwd);
      conn->allocptr.proxyuserpwd =
        aprintf("Proxy-authorization: Basic %s\015\012", authorization);
Daniel Stenberg's avatar
Daniel Stenberg committed
      free(authorization);
    }
Daniel Stenberg's avatar
Daniel Stenberg committed
  }
Daniel Stenberg's avatar
Daniel Stenberg committed

  /*************************************************************
   * Send user-agent to HTTP proxies even if the target protocol
   * isn't HTTP.
   *************************************************************/
  if((conn->protocol&PROT_HTTP) || data->bits.httpproxy) {
Daniel Stenberg's avatar
Daniel Stenberg committed
    if(data->useragent) {
      if(conn->allocptr.uagent)
        free(conn->allocptr.uagent);
      conn->allocptr.uagent =
        aprintf("User-Agent: %s\015\012", data->useragent);
Daniel Stenberg's avatar
Daniel Stenberg committed
  if(-1 == conn->firstsocket) {
    /* Connect only if not already connected! */
    result = ConnectPlease(data, conn);
    if(CURLE_OK != result)
      return result;

    if(conn->curl_connect) {
      /* is there a connect() procedure? */
Daniel Stenberg's avatar
Daniel Stenberg committed
      /* set start time here for timeout purposes in the
       * connect procedure, it is later set again for the
       * progress meter purpose */
      conn->now = Curl_tvnow();
Daniel Stenberg's avatar
Daniel Stenberg committed
      /* Call the protocol-specific connect function */
      result = conn->curl_connect(conn);
      if(result != CURLE_OK)
        return result; /* pass back errors */
    }
Daniel Stenberg's avatar
Daniel Stenberg committed
  }
  Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected */
Daniel Stenberg's avatar
Daniel Stenberg committed

  conn->now = Curl_tvnow(); /* time this *after* the connect is done */
  conn->bytecount = 0;
Daniel Stenberg's avatar
Daniel Stenberg committed
  
Daniel Stenberg's avatar
Daniel Stenberg committed
  /* Figure out the ip-number and display the first host name it shows: */
#ifdef ENABLE_IPV6
  {
    char hbuf[NI_MAXHOST];
#ifdef NI_WITHSCOPEID
    const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
#else
    const int niflags = NI_NUMERICHOST;
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed
    struct addrinfo *ai = conn->ai;

    if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
	niflags)) {
      snprintf(hbuf, sizeof(hbuf), "?");
    }
    if (ai->ai_canonname) {
      infof(data, "Connected to %s (%s)\n", ai->ai_canonname, hbuf);
    } else {
      infof(data, "Connected to %s\n", hbuf);
    }
  }
#else
Daniel Stenberg's avatar
Daniel Stenberg committed
  {
    struct in_addr in;
    (void) memcpy(&in.s_addr, *conn->hp->h_addr_list, sizeof (in.s_addr));
    infof(data, "Connected to %s (%s)\n", conn->hp->h_name, inet_ntoa(in));
Daniel Stenberg's avatar
Daniel Stenberg committed
  }
Daniel Stenberg's avatar
Daniel Stenberg committed

#ifdef __EMX__
  /* 20000330 mgs
   * the check is quite a hack...
   * we're calling _fsetmode to fix the problem with fwrite converting newline
   * characters (you get mangled text files, and corrupted binary files when
   * you download to stdout and redirect it to a file). */

  if ((data->out)->_handle == NULL) {
    _fsetmode(stdout, "b");
  }
#endif

CURLcode Curl_connect(struct UrlData *data,
                      struct connectdata **in_connect,
{
  CURLcode code;
  struct connectdata *conn;

  /* call the stuff that needs to be called */
  code = Connect(data, in_connect, allow_port);

  if(CURLE_OK != code) {
    /* We're not allowed to return failure with memory left allocated
       in the connectdata struct, free those here */
    conn = (struct connectdata *)*in_connect;
      Curl_disconnect(conn);      /* close the connection */
CURLcode Curl_done(struct connectdata *conn)
  CURLcode result;

  /* cleanups done even if the connection is re-used */

  if(conn->bits.rangestringalloc) {
    free(conn->range);
    conn->bits.rangestringalloc = FALSE;
  }

  /* Cleanup possible redirect junk */
  if(conn->newurl) {
    free(conn->newurl);
    conn->newurl = NULL;
  }
 
  /* this calls the protocol-specific function pointer previously set */
  if(conn->curl_done)
    result = conn->curl_done(conn);
  else
    result = CURLE_OK;

  Curl_pgrsDone(conn); /* done with the operation */
  /* if data->bits.reuse_forbid is TRUE, it means the libcurl client has
     forced us to close this no matter what we think.
    
     if conn->bits.close is TRUE, it means that the connection should be
     closed in spite of all our efforts to be nice, due to protocol
     restrictions in our or the server's end */
  if(data->bits.reuse_forbid ||
     ((CURLE_OK == result) && conn->bits.close))
    result = Curl_disconnect(conn); /* close the connection */
  else
    infof(data, "Connection (#%d) left alive\n", conn->connectindex);
CURLcode Curl_do(struct connectdata *conn)
  CURLcode result=CURLE_OK;
    /* generic protocol-specific function pointer set in curl_connect() */
    result = conn->curl_do(conn);