Commit 56b7c87c authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

singleipconnect: simplify and clean up

Remove timeout argument that's never used.

Make the actual connection get detected on a single spot to reduce code
duplication.

Store the IPv6 state already when the connection is attempted.
parent 32e8467a
Loading
Loading
Loading
Loading
+49 −91
Original line number Diff line number Diff line
@@ -128,7 +128,6 @@ tcpkeepalive(struct SessionHandle *data,
static CURLcode
singleipconnect(struct connectdata *conn,
                const Curl_addrinfo *ai, /* start connecting to this */
                long timeout_ms,
                curl_socket_t *sock,
                bool *connected);

@@ -199,20 +198,19 @@ long Curl_timeleft(struct SessionHandle *data,
}

/*
 * waitconnect() waits for a TCP connect on the given socket for the specified
 * number if milliseconds. It returns:
 * checkconnect() checks for a TCP connect on the given socket.
 * It returns:
 */

#define WAITCONN_CONNECTED     0
#define WAITCONN_SELECT_ERROR -1
#define WAITCONN_TIMEOUT       1
#define WAITCONN_FDSET_ERROR   2
#define WAITCONN_ABORTED       3
enum chkconn_t {
  CHKCONN_SELECT_ERROR = -1,
  CHKCONN_CONNECTED    = 0,
  CHKCONN_IDLE         = 1,
  CHKCONN_FDSET_ERROR  = 2
};

static
int waitconnect(struct connectdata *conn,
                curl_socket_t sockfd, /* socket */
                long timeout_msec)
static enum chkconn_t
checkconnect(curl_socket_t sockfd)
{
  int rc;
#ifdef mpeix
@@ -222,34 +220,20 @@ int waitconnect(struct connectdata *conn,
  (void)verifyconnect(sockfd, NULL);
#endif

  for(;;) {

    /* now select() until we get connect or timeout */
    rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, timeout_msec>1000?
                           1000:timeout_msec);
    if(Curl_pgrsUpdate(conn))
      return WAITCONN_ABORTED;
  rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 0);

  if(-1 == rc)
    /* error, no connect here, try next */
      return WAITCONN_SELECT_ERROR;

    else if(0 == rc) {
      /* timeout */
      timeout_msec -= 1000;
      if(timeout_msec <= 0)
        return WAITCONN_TIMEOUT;
    return CHKCONN_SELECT_ERROR;

      continue;
    }

    if(rc & CURL_CSELECT_ERR)
  else if(rc & CURL_CSELECT_ERR)
    /* error condition caught */
      return WAITCONN_FDSET_ERROR;
    return CHKCONN_FDSET_ERROR;

    break;
  }
  return WAITCONN_CONNECTED;
  else if(rc)
    return CHKCONN_CONNECTED;

  return CHKCONN_IDLE;
}

static CURLcode bindlocal(struct connectdata *conn,
@@ -548,7 +532,7 @@ static CURLcode trynextip(struct connectdata *conn,
  ai = conn->ip_addr->ai_next;

  while(ai) {
    CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected);
    CURLcode res = singleipconnect(conn, ai, &sockfd, connected);
    if(res)
      return res;
    if(sockfd != CURL_SOCKET_BAD) {
@@ -676,21 +660,20 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
}

/*
 * Curl_is_connected() is used from the multi interface to check if the
 * firstsocket has connected.
 * Curl_is_connected() checks if the socket has connected.
 */

CURLcode Curl_is_connected(struct connectdata *conn,
                           int sockindex,
                           bool *connected)
{
  int rc;
  struct SessionHandle *data = conn->data;
  CURLcode code = CURLE_OK;
  curl_socket_t sockfd = conn->sock[sockindex];
  long allow = DEFAULT_CONNECT_TIMEOUT;
  int error = 0;
  struct timeval now;
  enum chkconn_t chk;

  DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);

@@ -713,9 +696,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
    return CURLE_OPERATION_TIMEDOUT;
  }

  /* check for connect without timeout as we want to return immediately */
  rc = waitconnect(conn, sockfd, 0);
  if(WAITCONN_TIMEOUT == rc) {
  /* check socket for connect */
  chk = checkconnect(sockfd);
  if(CHKCONN_IDLE == chk) {
    if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
      infof(data, "After %ldms connect time, move on!\n",
            conn->timeoutms_per_addr);
@@ -726,7 +709,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
    return code;
  }

  if(WAITCONN_CONNECTED == rc) {
  if(CHKCONN_CONNECTED == chk) {
    if(verifyconnect(sockfd, &error)) {
      /* we are connected with TCP, awesome! */

@@ -736,6 +719,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
        return code;

      conn->bits.tcpconnect[sockindex] = TRUE;

      *connected = TRUE;
      if(sockindex == FIRSTSOCKET)
        Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
@@ -748,7 +732,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
  }
  else {
    /* nope, not connected  */
    if(WAITCONN_FDSET_ERROR == rc) {
    if(CHKCONN_FDSET_ERROR == chk) {
      (void)verifyconnect(sockfd, &error);
      infof(data, "%s\n",Curl_strerror(conn, error));
    }
@@ -864,12 +848,11 @@ void Curl_sndbufset(curl_socket_t sockfd)
 * CURL_SOCKET_BAD. Other errors will however return proper errors.
 *
 * singleipconnect() connects to the given IP only, and it may return without
 * having connected if used from the multi interface.
 * having connected.
 */
static CURLcode
singleipconnect(struct connectdata *conn,
                const Curl_addrinfo *ai,
                long timeout_ms,
                curl_socket_t *sockp,
                bool *connected)
{
@@ -940,17 +923,25 @@ singleipconnect(struct connectdata *conn,
  /* set socket non-blocking */
  curlx_nonblock(sockfd, TRUE);

  conn->connecttime = Curl_tvnow();
  if(conn->num_addr > 1)
    Curl_expire(data, conn->timeoutms_per_addr);

  /* Connect TCP sockets, bind UDP */
  if(!isconnected && (conn->socktype == SOCK_STREAM)) {
    rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
    if(-1 == rc)
      error = SOCKERRNO;
    conn->connecttime = Curl_tvnow();
    if(conn->num_addr > 1)
      Curl_expire(data, conn->timeoutms_per_addr);
  }
  else
  else {
    rc = 0;
    *sockp = sockfd;
    return CURLE_OK;
  }

#ifdef ENABLE_IPV6
  conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
#endif

  if(-1 == rc) {
    switch (error) {
@@ -965,54 +956,22 @@ singleipconnect(struct connectdata *conn,
    case EAGAIN:
#endif
#endif
      rc = waitconnect(conn, sockfd, timeout_ms);
      if(WAITCONN_ABORTED == rc) {
        Curl_closesocket(conn, sockfd);
        return CURLE_ABORTED_BY_CALLBACK;
      }
      break;
      *sockp = sockfd;
      return CURLE_OK;

    default:
      /* unknown error, fallthrough and try another address! */
      failf(data, "Failed to connect to %s: %s",
            conn->ip_addr_str, Curl_strerror(conn,error));
      data->state.os_errno = error;
      break;
    }
  }

  /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
     connect(). We can be sure of this since connect() cannot return 1. */
  if(WAITCONN_TIMEOUT == rc) {
    /* Timeout when running the multi interface */
    *sockp = sockfd;
    return CURLE_OK;
  }

  if(!isconnected)
    isconnected = verifyconnect(sockfd, &error);

  if(!rc && isconnected) {
    /* we are connected, awesome! */
    *connected = TRUE; /* this is a true connect */
    infof(data, "connected\n");
#ifdef ENABLE_IPV6
    conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
#endif
      /* connect failed */
      Curl_closesocket(conn, sockfd);

    Curl_updateconninfo(conn, sockfd);
    *sockp = sockfd;
    return CURLE_OK;
      break;
    }
  else if(WAITCONN_TIMEOUT == rc)
    infof(data, "Timeout\n");
  else {
    data->state.os_errno = error;
    infof(data, "%s\n", Curl_strerror(conn, error));
  }

  /* connect failed or timed out */
  Curl_closesocket(conn, sockfd);

  return CURLE_OK;
}

@@ -1073,7 +1032,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */

    /* start connecting to the IP curr_addr points to */
    res = singleipconnect(conn, curr_addr,
                          0, /* don't hang when doing multi */
                          &sockfd, connected);
    if(res)
      return res;