diff options
Diffstat (limited to 'src/rexmpp_tcp.c')
-rw-r--r-- | src/rexmpp_tcp.c | 87 |
1 files changed, 46 insertions, 41 deletions
diff --git a/src/rexmpp_tcp.c b/src/rexmpp_tcp.c index 3022182..c6a53a5 100644 --- a/src/rexmpp_tcp.c +++ b/src/rexmpp_tcp.c @@ -50,10 +50,10 @@ void rexmpp_tcp_dns_a_cb (rexmpp_t *s, conn->addr_cur_v4 = -1; if (conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { /* Wait for 50 ms for IPv6. */ - gettimeofday(&(conn->next_connection_time), NULL); - conn->next_connection_time.tv_usec += REXMPP_TCP_IPV6_DELAY_MS * 1000; - if (conn->next_connection_time.tv_usec >= 1000000) { - conn->next_connection_time.tv_usec -= 1000000; + clock_gettime(CLOCK_MONOTONIC, &(conn->next_connection_time)); + conn->next_connection_time.tv_nsec += REXMPP_TCP_IPV6_DELAY_MS * 1000000; + if (conn->next_connection_time.tv_nsec >= 1000000000) { + conn->next_connection_time.tv_nsec -= 1000000000; conn->next_connection_time.tv_sec++; } } @@ -99,6 +99,21 @@ rexmpp_tcp_connected (rexmpp_tcp_conn_t *conn, int fd) { return REXMPP_CONN_DONE; } +int rexmpp_tcp_socket(rexmpp_t *s, int domain) { + int sock = socket(domain, SOCK_STREAM, 0); + + /* Make it non-blocking */ + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + /* Call the socket creation callback, if provided */ + if (s->socket_cb != NULL) { + s->socket_cb(s, sock); + } + + return sock; +} + rexmpp_tcp_conn_error_t rexmpp_tcp_conn_init (rexmpp_t *s, rexmpp_tcp_conn_t *conn, @@ -116,20 +131,16 @@ rexmpp_tcp_conn_init (rexmpp_t *s, conn->fd = -1; conn->dns_secure = 0; conn->next_connection_time.tv_sec = 0; - conn->next_connection_time.tv_usec = 0; + conn->next_connection_time.tv_nsec = 0; conn->resolution_v4 = REXMPP_CONN_RESOLUTION_INACTIVE; conn->resolution_v6 = REXMPP_CONN_RESOLUTION_INACTIVE; struct sockaddr_in addr_v4; - int flags; - if (inet_pton(AF_INET, host, &addr_v4)) { + if (inet_pton(AF_INET, host, &(addr_v4.sin_addr))) { addr_v4.sin_family = AF_INET; addr_v4.sin_port = htons(port); - conn->sockets[conn->connection_attempts] = - socket(AF_INET, SOCK_STREAM, 0); - flags = fcntl(conn->sockets[conn->connection_attempts], F_GETFL, 0); - fcntl(conn->sockets[conn->connection_attempts], F_SETFL, flags | O_NONBLOCK); + conn->sockets[conn->connection_attempts] = rexmpp_tcp_socket(s, AF_INET); if (connect(conn->sockets[conn->connection_attempts], (struct sockaddr*)&addr_v4, sizeof(addr_v4))) { @@ -144,15 +155,12 @@ rexmpp_tcp_conn_init (rexmpp_t *s, return REXMPP_CONN_IN_PROGRESS; } struct sockaddr_in6 addr_v6; - if (inet_pton(AF_INET6, host, &addr_v6)) { + if (inet_pton(AF_INET6, host, &(addr_v6.sin6_addr))) { addr_v6.sin6_family = AF_INET6; addr_v6.sin6_port = htons(port); addr_v6.sin6_flowinfo = 0; addr_v6.sin6_scope_id = 0; - conn->sockets[conn->connection_attempts] = - socket(AF_INET6, SOCK_STREAM, 0); - flags = fcntl(conn->sockets[conn->connection_attempts], F_GETFL, 0); - fcntl(conn->sockets[conn->connection_attempts], F_SETFL, flags | O_NONBLOCK); + conn->sockets[conn->connection_attempts] = rexmpp_tcp_socket(s, AF_INET6); if (connect(conn->sockets[conn->connection_attempts], (struct sockaddr*)&addr_v6, sizeof(addr_v6))) { @@ -201,7 +209,7 @@ rexmpp_tcp_conn_proceed (rexmpp_t *s, fd_set *write_fds) { (void)read_fds; /* Not checking any read FDs at the moment. */ - struct timeval now; + struct timespec now; int i; /* Check for successful connections. */ @@ -241,10 +249,10 @@ rexmpp_tcp_conn_proceed (rexmpp_t *s, if (conn->connection_attempts < REXMPP_TCP_MAX_CONNECTION_ATTEMPTS && (rexmpp_tcp_conn_ipv4_available(conn) || rexmpp_tcp_conn_ipv6_available(conn))) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); if (now.tv_sec > conn->next_connection_time.tv_sec || (now.tv_sec == conn->next_connection_time.tv_sec && - now.tv_usec >= conn->next_connection_time.tv_usec)) { + now.tv_nsec >= conn->next_connection_time.tv_nsec)) { /* Time to attempt a new connection. */ int use_ipv6 = 0; if (rexmpp_tcp_conn_ipv4_available(conn) && @@ -295,16 +303,13 @@ rexmpp_tcp_conn_proceed (rexmpp_t *s, addrlen = sizeof(addr_v4); } - conn->sockets[conn->connection_attempts] = - socket(domain, SOCK_STREAM, 0); - int flags = fcntl(conn->sockets[conn->connection_attempts], F_GETFL, 0); - fcntl(conn->sockets[conn->connection_attempts], F_SETFL, flags | O_NONBLOCK); + conn->sockets[conn->connection_attempts] = rexmpp_tcp_socket(s, domain); if (connect(conn->sockets[conn->connection_attempts], addr, addrlen)) { if (errno == EINPROGRESS) { - gettimeofday(&(conn->next_connection_time), NULL); - conn->next_connection_time.tv_usec += REXMPP_TCP_CONN_DELAY_MS * 1000; - if (conn->next_connection_time.tv_usec >= 1000000) { - conn->next_connection_time.tv_usec -= 1000000; + clock_gettime(CLOCK_MONOTONIC, &(conn->next_connection_time)); + conn->next_connection_time.tv_nsec += REXMPP_TCP_CONN_DELAY_MS * 1000000; + if (conn->next_connection_time.tv_nsec >= 1000000000) { + conn->next_connection_time.tv_nsec -= 1000000000; conn->next_connection_time.tv_sec++; } conn->connection_attempts++; @@ -333,14 +338,14 @@ rexmpp_tcp_conn_proceed (rexmpp_t *s, } } - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); if (active_connections || conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING || (conn->next_connection_time.tv_sec > now.tv_sec || (conn->next_connection_time.tv_sec == now.tv_sec && - conn->next_connection_time.tv_usec > now.tv_usec))) { + conn->next_connection_time.tv_nsec > now.tv_nsec))) { return REXMPP_CONN_IN_PROGRESS; } else { return REXMPP_CONN_FAILURE; @@ -368,13 +373,13 @@ int rexmpp_tcp_conn_fds (rexmpp_t *s, return max_fd; } -struct timeval *rexmpp_tcp_conn_timeout (rexmpp_t *s, - rexmpp_tcp_conn_t *conn, - struct timeval *max_tv, - struct timeval *tv) +struct timespec *rexmpp_tcp_conn_timeout (rexmpp_t *s, + rexmpp_tcp_conn_t *conn, + struct timespec *max_tv, + struct timespec *tv) { - struct timeval now; - struct timeval *ret = max_tv; + struct timespec now; + struct timespec *ret = max_tv; if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING || conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) { ret = rexmpp_dns_timeout(s, max_tv, tv); @@ -383,20 +388,20 @@ struct timeval *rexmpp_tcp_conn_timeout (rexmpp_t *s, conn->resolution_v6 == REXMPP_CONN_RESOLUTION_SUCCESS || (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_INACTIVE && conn->resolution_v6 == REXMPP_CONN_RESOLUTION_INACTIVE)) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); if (now.tv_sec < conn->next_connection_time.tv_sec || (now.tv_sec == conn->next_connection_time.tv_sec && - now.tv_usec <= conn->next_connection_time.tv_usec)) { + now.tv_nsec <= conn->next_connection_time.tv_nsec)) { if (ret == NULL || ret->tv_sec > conn->next_connection_time.tv_sec - now.tv_sec || (ret->tv_sec == conn->next_connection_time.tv_sec - now.tv_sec && - ret->tv_usec > conn->next_connection_time.tv_usec - now.tv_usec)) { + ret->tv_nsec > conn->next_connection_time.tv_nsec - now.tv_nsec)) { ret = tv; tv->tv_sec = conn->next_connection_time.tv_sec - now.tv_sec; - if (conn->next_connection_time.tv_usec > now.tv_usec) { - tv->tv_usec = conn->next_connection_time.tv_usec - now.tv_usec; + if (conn->next_connection_time.tv_nsec > now.tv_nsec) { + tv->tv_nsec = conn->next_connection_time.tv_nsec - now.tv_nsec; } else { - tv->tv_usec = conn->next_connection_time.tv_usec + 1000000 - now.tv_usec; + tv->tv_nsec = conn->next_connection_time.tv_nsec + 1000000000 - now.tv_nsec; tv->tv_sec--; } } |