Beispiel #1
0
/* Used within the multi interface. Try next IP address, return TRUE if no
   more address exists */
static bool trynextip(struct connectdata *conn,
                      int sockindex,
                      bool *connected)
{
  curl_socket_t sockfd;
  Curl_addrinfo *ai;

  /* first close the failed socket */
  sclose(conn->sock[sockindex]);
  conn->sock[sockindex] = CURL_SOCKET_BAD;
  *connected = FALSE;

  if(sockindex != FIRSTSOCKET)
    return TRUE; /* no next */

  /* try the next address */
  ai = conn->ip_addr->ai_next;

  while (ai) {
    sockfd = singleipconnect(conn, ai, 0L, connected);
    if(sockfd != CURL_SOCKET_BAD) {
      /* store the new socket descriptor */
      conn->sock[sockindex] = sockfd;
      conn->ip_addr = ai;

      Curl_store_ip_addr(conn);
      return FALSE;
    }
    ai = ai->ai_next;
  }
  return TRUE;
}
Beispiel #2
0
/* Used within the multi interface. Try next IP address, return TRUE if no
   more address exists or error */
static CURLcode trynextip(struct connectdata *conn,
                          int sockindex,
                          int tempindex)
{
  const int other = tempindex ^ 1;
  CURLcode result = CURLE_COULDNT_CONNECT;

  /* First clean up after the failed socket.
     Don't close it yet to ensure that the next IP's socket gets a different
     file descriptor, which can prevent bugs when the curl_multi_socket_action
     interface is used with certain select() replacements such as kqueue. */
  curl_socket_t fd_to_close = conn->tempsock[tempindex];
  conn->tempsock[tempindex] = CURL_SOCKET_BAD;

  if(sockindex == FIRSTSOCKET) {
    Curl_addrinfo *ai = NULL;
    int family = AF_UNSPEC;

    if(conn->tempaddr[tempindex]) {
      /* find next address in the same protocol family */
      family = conn->tempaddr[tempindex]->ai_family;
      ai = conn->tempaddr[tempindex]->ai_next;
    }
#ifdef ENABLE_IPV6
    else if(conn->tempaddr[0]) {
      /* happy eyeballs - try the other protocol family */
      int firstfamily = conn->tempaddr[0]->ai_family;
      family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
      ai = conn->tempaddr[0]->ai_next;
    }
#endif

    while(ai) {
      if(conn->tempaddr[other]) {
        /* we can safely skip addresses of the other protocol family */
        while(ai && ai->ai_family != family)
          ai = ai->ai_next;
      }

      if(ai) {
        result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
        if(result == CURLE_COULDNT_CONNECT) {
          ai = ai->ai_next;
          continue;
        }

        conn->tempaddr[tempindex] = ai;
      }
      break;
    }
  }

  if(fd_to_close != CURL_SOCKET_BAD)
    Curl_closesocket(conn, fd_to_close);

  return result;
}
Beispiel #3
0
/* Used within the multi interface. Try next IP address, return TRUE if no
   more address exists or error */
static CURLcode trynextip(struct connectdata *conn,
                          int sockindex,
                          int tempindex,
                          bool *connected)
{
  curl_socket_t sockfd;
  Curl_addrinfo *ai;
  int family = tempindex ? AF_INET6 : AF_INET;

  /* First clean up after the failed socket.
     Don't close it yet to ensure that the next IP's socket gets a different
     file descriptor, which can prevent bugs when the curl_multi_socket_action
     interface is used with certain select() replacements such as kqueue. */
  curl_socket_t fd_to_close = conn->tempsock[tempindex];
  conn->tempsock[tempindex] = CURL_SOCKET_BAD;
  *connected = FALSE;

  if(sockindex != FIRSTSOCKET) {
    Curl_closesocket(conn, fd_to_close);
    return CURLE_COULDNT_CONNECT; /* no next */
  }

  /* try the next address with same family */
  ai = conn->tempaddr[tempindex]->ai_next;
  while(ai && ai->ai_family != family)
    ai = ai->ai_next;

  while(ai && ai->ai_family == family) {
    CURLcode res = singleipconnect(conn, ai, &sockfd, connected);
    if(res)
      return res;
    if(sockfd != CURL_SOCKET_BAD) {
      /* store the new socket descriptor */
      conn->tempsock[tempindex] = sockfd;
      conn->tempaddr[tempindex] = ai;
      Curl_closesocket(conn, fd_to_close);
      return CURLE_OK;
    }

    do {
      ai = ai->ai_next;
    } while(ai && ai->ai_family != family);
  }
  Curl_closesocket(conn, fd_to_close);
  return CURLE_COULDNT_CONNECT;
}
Beispiel #4
0
CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
                          const struct Curl_dns_entry *remotehost)
{
  struct SessionHandle *data = conn->data;
  struct timeval before = Curl_tvnow();
  CURLcode result = CURLE_COULDNT_CONNECT;

  long timeout_ms = Curl_timeleft(data, &before, TRUE);

  if(timeout_ms < 0) {
    /* a precaution, no need to continue if time already is up */
    failf(data, "Connection time-out");
    return CURLE_OPERATION_TIMEDOUT;
  }

  conn->num_addr = Curl_num_addresses(remotehost->addr);
  conn->tempaddr[0] = remotehost->addr;
  conn->tempaddr[1] = NULL;
  conn->tempsock[0] = CURL_SOCKET_BAD;
  conn->tempsock[1] = CURL_SOCKET_BAD;
  Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);

  /* Max time for the next connection attempt */
  conn->timeoutms_per_addr =
    conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;

  /* start connecting to first IP */
  while(conn->tempaddr[0]) {
    result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
    if(!result)
      break;
    conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
  }

  if(conn->tempsock[0] == CURL_SOCKET_BAD) {
    if(!result)
      result = CURLE_COULDNT_CONNECT;
    return result;
  }

  data->info.numconnects++; /* to track the number of connections made */

  return CURLE_OK;
}
Beispiel #5
0
/* Used within the multi interface. Try next IP address, return TRUE if no
   more address exists or error */
static CURLcode trynextip(struct connectdata *conn,
                          int sockindex,
                          int tempindex)
{
  CURLcode rc = CURLE_COULDNT_CONNECT;

  /* First clean up after the failed socket.
     Don't close it yet to ensure that the next IP's socket gets a different
     file descriptor, which can prevent bugs when the curl_multi_socket_action
     interface is used with certain select() replacements such as kqueue. */
  curl_socket_t fd_to_close = conn->tempsock[tempindex];
  conn->tempsock[tempindex] = CURL_SOCKET_BAD;

  if(sockindex == FIRSTSOCKET) {
    Curl_addrinfo *ai;
    int family;

    if(conn->tempaddr[tempindex]) {
      /* find next address in the same protocol family */
      family = conn->tempaddr[tempindex]->ai_family;
      ai = conn->tempaddr[tempindex]->ai_next;
    }
    else {
      /* happy eyeballs - try the other protocol family */
      int firstfamily = conn->tempaddr[0]->ai_family;
      family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
      ai = conn->tempaddr[0]->ai_next;
    }

    while(ai && ai->ai_family != family)
      ai = ai->ai_next;
    if(ai) {
      rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
      conn->tempaddr[tempindex] = ai;
    }
  }

  if(fd_to_close != CURL_SOCKET_BAD)
    Curl_closesocket(conn, fd_to_close);

  return rc;
}
Beispiel #6
0
/* Used within the multi interface. Try next IP address, return TRUE if no
   more address exists or error */
static CURLcode trynextip(struct connectdata *conn,
                          int sockindex,
                          bool *connected)
{
  curl_socket_t sockfd;
  Curl_addrinfo *ai;

  /* First clean up after the failed socket.
     Don't close it yet to ensure that the next IP's socket gets a different
     file descriptor, which can prevent bugs when the curl_multi_socket_action
     interface is used with certain select() replacements such as kqueue. */
  curl_socket_t fd_to_close = conn->sock[sockindex];
  conn->sock[sockindex] = CURL_SOCKET_BAD;
  *connected = FALSE;

  if(sockindex != FIRSTSOCKET) {
    sclose(fd_to_close);
    return CURLE_COULDNT_CONNECT; /* no next */
  }

  /* try the next address */
  ai = conn->ip_addr->ai_next;

  while(ai) {
    CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected);
    if(res)
      return res;
    if(sockfd != CURL_SOCKET_BAD) {
      /* store the new socket descriptor */
      conn->sock[sockindex] = sockfd;
      conn->ip_addr = ai;
      sclose(fd_to_close);
      return CURLE_OK;
    }
    ai = ai->ai_next;
  }
  sclose(fd_to_close);
  return CURLE_COULDNT_CONNECT;
}
Beispiel #7
0
CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
                          const struct Curl_dns_entry *remotehost, /* use this one */
                          curl_socket_t *sockconn,   /* the connected socket */
                          Curl_addrinfo **addr,      /* the one we used */
                          bool *connected)           /* really connected? */
{
  struct SessionHandle *data = conn->data;
  curl_socket_t sockfd = CURL_SOCKET_BAD;
  int aliasindex;
  int num_addr;
  Curl_addrinfo *ai;
  Curl_addrinfo *curr_addr;

  struct timeval after;
  struct timeval before = Curl_tvnow();

  /*************************************************************
   * Figure out what maximum time we have left
   *************************************************************/
  long timeout_ms= DEFAULT_CONNECT_TIMEOUT;
  long timeout_per_addr;

  *connected = FALSE; /* default to not connected */

  if(data->set.timeout || data->set.connecttimeout) {
    long has_passed;

    /* Evaluate in milliseconds how much time that has passed */
    has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);

#ifndef min
#define min(a, b)   ((a) < (b) ? (a) : (b))
#endif

    /* get the most strict timeout of the ones converted to milliseconds */
    if(data->set.timeout && data->set.connecttimeout) {
      if (data->set.timeout < data->set.connecttimeout)
        timeout_ms = data->set.timeout*1000;
      else
        timeout_ms = data->set.connecttimeout*1000;
    }
    else if(data->set.timeout)
      timeout_ms = data->set.timeout*1000;
    else
      timeout_ms = data->set.connecttimeout*1000;

    /* subtract the passed time */
    timeout_ms -= has_passed;

    if(timeout_ms < 0) {
      /* a precaution, no need to continue if time already is up */
      failf(data, "Connection time-out");
      return CURLE_OPERATION_TIMEOUTED;
    }
  }
  Curl_expire(data, timeout_ms);

  /* Max time for each address */
  num_addr = Curl_num_addresses(remotehost->addr);
  timeout_per_addr = timeout_ms / num_addr;

  ai = remotehost->addr;

  /* Below is the loop that attempts to connect to all IP-addresses we
   * know for the given host. One by one until one IP succeeds.
   */

  if(data->state.used_interface == Curl_if_multi)
    /* don't hang when doing multi */
    timeout_per_addr = 0;

  /*
   * Connecting with a Curl_addrinfo chain
   */
  for (curr_addr = ai, aliasindex=0; curr_addr;
       curr_addr = curr_addr->ai_next, aliasindex++) {

    /* start connecting to the IP curr_addr points to */
    sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected);

    if(sockfd != CURL_SOCKET_BAD)
      break;

    /* get a new timeout for next attempt */
    after = Curl_tvnow();
    timeout_ms -= Curl_tvdiff(after, before);
    if(timeout_ms < 0) {
      failf(data, "connect() timed out!");
      return CURLE_OPERATION_TIMEOUTED;
    }
    before = after;
  }  /* end of connect-to-each-address loop */

  if (sockfd == CURL_SOCKET_BAD) {
    /* no good connect was made */
    *sockconn = CURL_SOCKET_BAD;
    failf(data, "couldn't connect to host");
    return CURLE_COULDNT_CONNECT;
  }

  /* leave the socket in non-blocking mode */

  /* store the address we use */
  if(addr)
    *addr = curr_addr;

  /* allow NULL-pointers to get passed in */
  if(sockconn)
    *sockconn = sockfd;    /* the socket descriptor we've connected */

  data->info.numconnects++; /* to track the number of connections made */

  return CURLE_OK;
}
Beispiel #8
0
CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
                          const struct Curl_dns_entry *remotehost,
                          curl_socket_t *sockconn,   /* the connected socket */
                          Curl_addrinfo **addr,      /* the one we used */
                          bool *connected)           /* really connected? */
{
    struct SessionHandle *data = conn->data;
    curl_socket_t sockfd = CURL_SOCKET_BAD;
    int aliasindex;
    int num_addr;
    Curl_addrinfo *ai;
    Curl_addrinfo *curr_addr;

    struct timeval after;
    struct timeval before = Curl_tvnow();

    /*************************************************************
     * Figure out what maximum time we have left
     *************************************************************/
    long timeout_ms;
    long timeout_per_addr;

    DEBUGASSERT(sockconn);
    *connected = FALSE; /* default to not connected */

    /* get the timeout left */
    timeout_ms = Curl_timeleft(conn, &before, TRUE);

    if(timeout_ms < 0) {
        /* a precaution, no need to continue if time already is up */
        failf(data, "Connection time-out");
        return CURLE_OPERATION_TIMEDOUT;
    }
    Curl_expire(data, timeout_ms);

    /* Max time for each address */
    num_addr = Curl_num_addresses(remotehost->addr);
    timeout_per_addr = timeout_ms / num_addr;

    ai = remotehost->addr;

    /* Below is the loop that attempts to connect to all IP-addresses we
     * know for the given host. One by one until one IP succeeds.
     */

    if(data->state.used_interface == Curl_if_multi)
        /* don't hang when doing multi */
        timeout_per_addr = 0;

    /*
     * Connecting with a Curl_addrinfo chain
     */
    for (curr_addr = ai, aliasindex=0; curr_addr;
            curr_addr = curr_addr->ai_next, aliasindex++) {

        /* start connecting to the IP curr_addr points to */
        sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected);

        if(sockfd != CURL_SOCKET_BAD)
            break;

        /* get a new timeout for next attempt */
        after = Curl_tvnow();
        timeout_ms -= Curl_tvdiff(after, before);
        if(timeout_ms < 0) {
            failf(data, "connect() timed out!");
            return CURLE_OPERATION_TIMEDOUT;
        }
        before = after;
    }  /* end of connect-to-each-address loop */

    *sockconn = sockfd;    /* the socket descriptor we've connected */

    if(sockfd == CURL_SOCKET_BAD) {
        /* no good connect was made */
        failf(data, "couldn't connect to host");
        return CURLE_COULDNT_CONNECT;
    }

    /* leave the socket in non-blocking mode */

    /* store the address we use */
    if(addr)
        *addr = curr_addr;

    data->info.numconnects++; /* to track the number of connections made */

    return CURLE_OK;
}
Beispiel #9
0
CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
                          const struct Curl_dns_entry *remotehost,
                          bool *connected)           /* really connected? */
{
  struct SessionHandle *data = conn->data;
  struct timeval after;
  struct timeval before = Curl_tvnow();
  int i;

  /*************************************************************
   * Figure out what maximum time we have left
   *************************************************************/
  long timeout_ms;

  *connected = FALSE; /* default to not connected */

  /* get the timeout left */
  timeout_ms = Curl_timeleft(data, &before, TRUE);

  if(timeout_ms < 0) {
    /* a precaution, no need to continue if time already is up */
    failf(data, "Connection time-out");
    return CURLE_OPERATION_TIMEDOUT;
  }

  conn->num_addr = Curl_num_addresses(remotehost->addr);
  conn->tempaddr[0] = remotehost->addr;
  conn->tempaddr[1] = remotehost->addr;

  /* Below is the loop that attempts to connect to all IP-addresses we
   * know for the given host.
   * One by one, for each protocol, until one IP succeeds.
   */

  for(i=0; i<2; i++) {
    curl_socket_t sockfd = CURL_SOCKET_BAD;
    Curl_addrinfo *ai = conn->tempaddr[i];
    int family = i ? AF_INET6 : AF_INET;

    /* find first address for this address family, if any */
    while(ai && ai->ai_family != family)
      ai = ai->ai_next;

    /*
     * Connecting with a Curl_addrinfo chain
     */
    while(ai) {
      CURLcode res;

      /* Max time for the next connection attempt */
      conn->timeoutms_per_addr = ai->ai_next == NULL ?
                                 timeout_ms : timeout_ms / 2;

      /* start connecting to the IP curr_addr points to */
      res = singleipconnect(conn, ai, &sockfd, connected);
      if(res)
        return res;

      if(sockfd != CURL_SOCKET_BAD)
        break;

      /* get a new timeout for next attempt */
      after = Curl_tvnow();
      timeout_ms -= Curl_tvdiff(after, before);
      if(timeout_ms < 0) {
        failf(data, "connect() timed out!");
        return CURLE_OPERATION_TIMEDOUT;
      }
      before = after;

      /* next addresses */
      do {
        ai = ai->ai_next;
      } while(ai && ai->ai_family != family);
    }  /* end of connect-to-each-address loop */

    conn->tempsock[i] = sockfd;
    conn->tempaddr[i] = ai;
  }

  if((conn->tempsock[0] == CURL_SOCKET_BAD) &&
     (conn->tempsock[1] == CURL_SOCKET_BAD)) {
    /* no good connect was made */
    failf(data, "couldn't connect to %s at %s:%ld",
          conn->bits.proxy?"proxy":"host",
          conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port);
    return CURLE_COULDNT_CONNECT;
  }

  /* leave the socket in non-blocking mode */

  data->info.numconnects++; /* to track the number of connections made */

  return CURLE_OK;
}