ftl_status_t _init_control_connection()

in libftl/handshake.c [37:135]


ftl_status_t _init_control_connection(ftl_stream_configuration_private_t *ftl) {
  int err = 0;
  SOCKET sock = 0;
  struct addrinfo hints;
  memset(&hints, 0, sizeof(hints));
  ftl_status_t retval = FTL_SUCCESS;

  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = 0;

  char ingest_ip[IPVX_ADDR_ASCII_LEN];

  struct addrinfo* resolved_names = 0;
  struct addrinfo* p = 0;

  int ingest_port = INGEST_PORT;
  char ingest_port_str[10];

  if (ftl_get_state(ftl, FTL_CONNECTED)) {
    return FTL_ALREADY_CONNECTED;
  }

  snprintf(ingest_port_str, 10, "%d", ingest_port);

  if ((retval = _set_ingest_hostname(ftl)) != FTL_SUCCESS) {
    return retval;
  }

  err = getaddrinfo(ftl->ingest_hostname, ingest_port_str, &hints, &resolved_names);
  if (err != 0) {
    FTL_LOG(ftl, FTL_LOG_ERROR, "getaddrinfo failed to look up ingest address %s.", ftl->ingest_hostname);
    FTL_LOG(ftl, FTL_LOG_ERROR, "gai error was: %s", gai_strerror(err));
    return FTL_DNS_FAILURE;
  }

  /* Open a socket to the control port */
  for (p = resolved_names; p != NULL; p = p->ai_next) {
    sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if (sock == -1) {
      /* try the next candidate */
      FTL_LOG(ftl, FTL_LOG_DEBUG, "failed to create socket. error: %s", get_socket_error());
      continue;
    }
    
    if (p->ai_family == AF_INET) {
      struct sockaddr_in *ipv4_addr = (struct sockaddr_in *)p->ai_addr;
      inet_ntop(p->ai_family, &ipv4_addr->sin_addr, ingest_ip, sizeof(ingest_ip));
    }
    else if (p->ai_family == AF_INET6) {
      struct sockaddr_in6 *ipv6_addr = (struct sockaddr_in6 *)p->ai_addr;
      inet_ntop(p->ai_family, &ipv6_addr->sin6_addr, ingest_ip, sizeof(ingest_ip));
    }
    else {
      continue;
    }

    FTL_LOG(ftl, FTL_LOG_DEBUG, "Got IP: %s\n", ingest_ip);
    ftl->ingest_ip = _strdup(ingest_ip);
    ftl->socket_family = p->ai_family;

    /* Go for broke */
    if (connect(sock, p->ai_addr, (int)p->ai_addrlen) == -1) {
      FTL_LOG(ftl, FTL_LOG_DEBUG, "failed to connect on candidate, error: %s", get_socket_error());
      close_socket(sock);
      sock = 0;
      continue;
    }

    /* If we got here, we successfully connected */
    if (set_socket_enable_keepalive(sock) != 0) {
      FTL_LOG(ftl, FTL_LOG_DEBUG, "failed to enable keep alives.  error: %s", get_socket_error());
    }

    if (set_socket_recv_timeout(sock, SOCKET_RECV_TIMEOUT_MS) != 0) {
      FTL_LOG(ftl, FTL_LOG_DEBUG, "failed to set recv timeout.  error: %s", get_socket_error());
    }

    if (set_socket_send_timeout(sock, SOCKET_SEND_TIMEOUT_MS) != 0) {
      FTL_LOG(ftl, FTL_LOG_DEBUG, "failed to set send timeout.  error: %s", get_socket_error());
    }

    break;
  }

  /* Free the resolved name struct */
  freeaddrinfo(resolved_names);

  /* Check to see if we actually connected */
  if (sock <= 0) {
    FTL_LOG(ftl, FTL_LOG_ERROR, "failed to connect to ingest. Last error was: %s",
      get_socket_error());
    return FTL_CONNECT_ERROR;
  }

  ftl->ingest_socket = sock;
  
  return FTL_SUCCESS;
}