void WTConnection::disconnect(void) { if(!this->connecting && !this->connected) { return; }; this->connecting = false; this->connected = false; if(this->socket != 0) close_portable(this->socket); #ifndef NO_SSL if(this->ssl_socket != NULL) { if(BIO_reset(this->ssl_socket) != 0) warning_error("failed to reset socket"); BIO_free_all(this->ssl_socket); this->ssl_socket = NULL; this->ssl = NULL; }; if(this->ssl_ctx != NULL) { SSL_CTX_free(this->ssl_ctx); this->ssl_ctx = NULL; }; #endif delegate_status(WTHTTP_Closed); if(this->addr_info != NULL) { freeaddrinfo(this->addr_info); this->addr_info = NULL; }; if(this->uri != NULL) { free(this->uri); this->uri = NULL; }; if(this->domain != NULL) { free(this->domain); this->domain = NULL; }; if(this->protocol != NULL) { free(this->protocol); this->protocol = NULL; }; }
socket_t uplink_connect(char *uplink, uint16_t port, char *vhost) { socket_t sock; int error, flags; unsigned int optval; struct addrinfo *res = NULL, hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; StartWSA(); if ((error = getaddrinfo(uplink, NULL, &hints, &res))) sigyn_fatal("Cannot resolve hostname(%s): %s", uplink, gai_strerror(error)); if (res->ai_addr == NULL) { freeaddrinfo(res); sigyn_fatal("Cannot resolve hostname (%s)."); } logger(LOG_STATUS, "Attempting to connect to %s:%d", uplink, port); if (!(sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol))) { freeaddrinfo(res); sigyn_fatal("Unable to create socket."); } if (sock > me.maxfd) me.maxfd = sock; if (vhost != NULL) { struct addrinfo *bindres = NULL; if ((error = getaddrinfo(vhost, NULL, &hints, &bindres))) { freeaddrinfo(res); close_portable(sock); sigyn_fatal("Cannot resolve vhost (%s): %s", vhost, gai_strerror(error)); } if (bindres->ai_addr == NULL) { freeaddrinfo(res); freeaddrinfo(bindres); sigyn_fatal("Cannot resolve vhost (%s)."); } optval = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); if (bind(sock, bindres->ai_addr, bindres->ai_addrlen) < 0) { freeaddrinfo(res); freeaddrinfo(bindres); close_portable(sock); sigyn_fatal("Unable to bind to vhost (%s): %s", vhost, strerror(errno)); } freeaddrinfo(bindres); } logger(LOG_DEBUG, "Setting file descriptor %d as non-blocking.", sock); #ifdef _WIN32 ioctlsocket(sock, FIONBIO, 1); #else flags = fcntl(sock, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(sock, F_SETFL, flags); #endif switch(res->ai_family) { case AF_INET: ((struct sockaddr_in *) res->ai_addr)->sin_port = htons(port); break; case AF_INET6: ((struct sockaddr_in6 *) res->ai_addr)->sin6_port = htons(port); break; } if ((connect(sock, res->ai_addr, res->ai_addrlen) == -1) && errno != EINPROGRESS && errno != EINTR) { close_portable(sock); freeaddrinfo(res); if (vhost) sigyn_fatal("Failed to connect to %s (Using vhost %s): %s", uplink, vhost, strerror(errno)); else sigyn_fatal("Failed to connect to %s: %s", uplink, strerror(errno)); } freeaddrinfo(res); return sock; }
void uplink_disconnect(void) { if(me.uplink.connected == true) close_portable(me.uplink.sock); }
bool WTConnection::connect(const char *url) { int addr_result; struct addrinfo hint; #ifdef _WIN32 DWORD timeout_msec; #else struct timeval tv; #endif char ports[6]; if(this->connecting) { return false; }; if(this->connected) { this->disconnect(); }; this->connecting = true; if(!this->parse_url(url)) { fprintf(stderr, "can't parse URL %s\n", url); last_error = "unparsable URL"; delegate_status(WTHTTP_Error); this->connecting = false; return false; }; if(strcmp("https", this->protocol) == 0) { return connect_https(); }; /* Ensure cleanliness */ memset(&hint, 0, sizeof(struct addrinfo)); hint.ai_family = AF_UNSPEC; hint.ai_socktype = SOCK_STREAM; delegate_status(WTHTTP_Resolving); snprintf(ports, 6, "%d", this->port); if( (addr_result = getaddrinfo(this->domain, ports, &hint, &(this->addr_info))) != 0) { last_error = gai_strerror(addr_result); fprintf(stderr, "can't resolve %s: %s\n", this->domain, last_error); delegate_status(WTHTTP_Error); free(this->uri); free(this->domain); free(this->protocol); this->connecting = false; return false; }; delegate_status(WTHTTP_Connecting); this->socket = ::socket(this->addr_info->ai_family, this->addr_info->ai_socktype, this->addr_info->ai_protocol); #ifdef _WIN32 timeout_msec = 30000; if(::setsockopt(this->socket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char *>(&timeout_msec), sizeof(DWORD)) == -1) #else tv.tv_sec = 30; tv.tv_usec = 0; if(::setsockopt(this->socket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char *>(&tv), sizeof(tv)) == -1) #endif { warning_error("couldn't set recv timeout -- expect delays"); } if(::connect(this->socket, this->addr_info->ai_addr, this->addr_info->ai_addrlen) == -1) { last_error = strerror(errno); fprintf(stderr, "can't connect to %s: %s\n", this->domain, last_error); delegate_status(WTHTTP_Error); close_portable(this->socket); freeaddrinfo(this->addr_info); free(this->uri); free(this->domain); free(this->protocol); this->connecting = false; return false; }; this->connected = true; this->connecting = false; delegate_status(WTHTTP_Connected); return true; }