-void iohandler_set_timeout(struct IODescriptor *descriptor, struct timeval *timeout) {
- if(descriptor->prev)
- descriptor->prev->next = descriptor->next;
- else
- first_descriptor = descriptor->next;
- if(descriptor->next)
- descriptor->next->prev = descriptor->prev;
- if(descriptor == timer_priority)
- timer_priority = descriptor->next;
- if(timeout)
- descriptor->timeout = *timeout;
- else {
- descriptor->timeout.tv_sec = 0;
- descriptor->timeout.tv_usec = 0;
- }
- iohandler_append(descriptor);
-}
-
-static void iohandler_increase_iobuf(struct IOBuffer *iobuf, size_t required) {
- if(iobuf->buflen >= required) return;
- char *new_buf = realloc(iobuf->buffer, required + 2);
- if(new_buf) {
- iobuf->buffer = new_buf;
- iobuf->buflen = required;
- }
-}
-
-struct IODescriptor *iohandler_timer(struct timeval timeout, iohandler_callback *callback) {
- struct IODescriptor *descriptor;
- descriptor = iohandler_add(-1, IOTYPE_TIMER, &timeout, callback);
- if(!descriptor) {
- iohandler_log(IOLOG_ERROR, "could not allocate memory for IODescriptor in %s:%d", __FILE__, __LINE__);
- return NULL;
- }
- iohandler_log(IOLOG_DEBUG, "added timer descriptor (sec: %d; usec: %d)", timeout.tv_sec, timeout.tv_usec);
- return descriptor;
-}
-
-struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, int ssl, const char *bindhost, iohandler_callback *callback) {
- //non-blocking connect
- int sockfd, result;
- struct addrinfo hints, *res;
- struct sockaddr_in *ip4 = NULL;
- struct sockaddr_in6 *ip6 = NULL;
- size_t dstaddrlen;
- struct sockaddr *dstaddr = NULL;
- struct IODescriptor *descriptor;
-
- if(!engine) {
- iohandler_init_engine();
- if(!engine) return NULL;
- }
- memset (&hints, 0, sizeof (hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags |= AI_CANONNAME;
- if ((result = getaddrinfo (hostname, NULL, &hints, &res))) {
- iohandler_log(IOLOG_ERROR, "could not resolve %s to an IP address (%d)", hostname, result);
- return NULL;
- }
- while (res) {
- switch (res->ai_family) {
- case AF_INET:
- ip4 = (struct sockaddr_in *) res->ai_addr;
- break;
- case AF_INET6:
- ip6 = (struct sockaddr_in6 *) res->ai_addr;
- break;
- }
- res = res->ai_next;
- freeaddrinfo(res);
- }
-
- if(ip6) {
- sockfd = socket(AF_INET6, SOCK_STREAM, 0);
- if(sockfd == -1) {
- iohandler_log(IOLOG_ERROR, "could not create socket in %s:%d", __FILE__, __LINE__);
- return NULL;
- }
-
- ip6->sin6_family = AF_INET6;
- ip6->sin6_port = htons(port);
-
- struct sockaddr_in6 *ip6vhost = NULL;
- if (bindhost && !getaddrinfo(bindhost, NULL, &hints, &res)) {
- while (res) {
- switch (res->ai_family) {
- case AF_INET6:
- ip6vhost = (struct sockaddr_in6 *) res->ai_addr;
- break;
- }
- res = res->ai_next;
- freeaddrinfo(res);
- }
- }
- if(ip6vhost) {
- ip6vhost->sin6_family = AF_INET6;
- ip6vhost->sin6_port = htons(0);
- bind(sockfd, (struct sockaddr*)ip6vhost, sizeof(*ip6vhost));
- }
- dstaddr = (struct sockaddr*)ip6;
- dstaddrlen = sizeof(*ip6);
- } else if(ip4) {
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if(sockfd == -1) {
- iohandler_log(IOLOG_ERROR, "could not create socket in %s:%d", __FILE__, __LINE__);
- return NULL;
- }
-
- ip4->sin_family = AF_INET;
- ip4->sin_port = htons(port);
-
- struct sockaddr_in *ip4vhost = NULL;
- if (bindhost && !getaddrinfo(bindhost, NULL, &hints, &res)) {
- while (res) {
- switch (res->ai_family) {
- case AF_INET:
- ip4vhost = (struct sockaddr_in *) res->ai_addr;
- break;
- }
- res = res->ai_next;
- freeaddrinfo(res);
- }
- }
- if(ip4vhost) {
- ip4vhost->sin_family = AF_INET;
- ip4vhost->sin_port = htons(0);
- bind(sockfd, (struct sockaddr*)ip4vhost, sizeof(*ip4vhost));
- }
- dstaddr = (struct sockaddr*)ip4;
- dstaddrlen = sizeof(*ip4);
- } else
- return NULL;
- //make sockfd unblocking
-#if defined(F_GETFL)
- {
- int flags;
- flags = fcntl(sockfd, F_GETFL);
- fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
- flags = fcntl(sockfd, F_GETFD);
- fcntl(sockfd, F_SETFD, flags|FD_CLOEXEC);
- }