Skip to content
url.c 65.9 KiB
Newer Older
  /* 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 */
    free(conn->path);        /* free the previous path pointer */

    /* we need these pointers if we speak over a proxy */
    conn->name = old_conn->name;
    conn->hostname = old_conn->hostname;

    conn->path = path;       /* use this one */
    conn->ppath = path;      /* set this too */
Daniel Stenberg's avatar
Daniel Stenberg committed
    conn->maxdownload = 0;   /* might have been used previously! */
    conn->bits.reuse = TRUE; /* yes, we're re-using here */
    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;

  /* this calls the protocol-specific function pointer previously set */
  if(conn->curl_done)
    result = conn->curl_done(conn);
  else
    result = CURLE_OK;

  Curl_pgrsDone(data); /* 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);