diff --git a/src/c/profile/transport/ip/tcp/tcp_transport_posix.c b/src/c/profile/transport/ip/tcp/tcp_transport_posix.c index c81467410..71e98076c 100644 --- a/src/c/profile/transport/ip/tcp/tcp_transport_posix.c +++ b/src/c/profile/transport/ip/tcp/tcp_transport_posix.c @@ -1,4 +1,5 @@ #include +#include #include "tcp_transport_internal.h" #include @@ -24,6 +25,7 @@ bool uxr_init_tcp_platform( const char* port) { bool rv = false; + int errsv = errno; switch (ip_protocol) { @@ -60,7 +62,13 @@ bool uxr_init_tcp_platform( { for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { - if (0 == connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen)) + int connect_rv; + do + { + errno = errsv; + connect_rv = connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen); + } while (-1 == connect_rv && EINTR == errno); + if (0 == connect_rv) { platform->poll_fd.events = POLLIN; rv = true; @@ -86,7 +94,13 @@ size_t uxr_write_tcp_data_platform( uint8_t* errcode) { size_t rv = 0; - ssize_t bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0); + int errsv = errno; + ssize_t bytes_sent; + do + { + errno = errsv; + bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0); + } while (-1 == bytes_sent && EINTR == errno); if (-1 != bytes_sent) { rv = (size_t)bytes_sent; @@ -107,10 +121,25 @@ size_t uxr_read_tcp_data_platform( uint8_t* errcode) { size_t rv = 0; - int poll_rv = poll(&platform->poll_fd, 1, timeout); + int errsv = errno; + int64_t start_timestamp = uxr_millis(); + int remaining_time = timeout; + int poll_rv; + do + { + errno = errsv; + remaining_time = (remaining_time <= 0) ? 0 : remaining_time; + poll_rv = poll(&platform->poll_fd, 1, remaining_time); + remaining_time = timeout - (int)(uxr_millis() - start_timestamp); + } while (-1 == poll_rv && EINTR == errno); if (0 < poll_rv) { - ssize_t bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0); + ssize_t bytes_received; + do + { + errno = errsv; + bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0); + } while (-1 == bytes_received && EINTR == errno); if (-1 != bytes_received) { rv = (size_t)bytes_received; diff --git a/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c b/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c index bd0eae3b2..f7767b6ab 100644 --- a/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c +++ b/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c @@ -1,4 +1,5 @@ #include +#include #include "tcp_transport_internal.h" #include @@ -8,14 +9,25 @@ #include #include #include +#include + +#ifdef UCLIENT_PLATFORM_LINUX +static void sigpipe_handler( + int fd) +{ + (void)fd; +} + +#endif /* ifdef UCLIENT_PLATFORM_LINUX */ bool uxr_init_tcp_platform( - uxrTCPPlatform* platform, + struct uxrTCPPlatform* platform, uxrIpProtocol ip_protocol, const char* ip, const char* port) { bool rv = false; + int errsv = errno; switch (ip_protocol) { @@ -29,6 +41,9 @@ bool uxr_init_tcp_platform( if (-1 != platform->fd) { +#ifdef UCLIENT_PLATFORM_LINUX + signal(SIGPIPE, sigpipe_handler); +#endif /* ifdef UCLIENT_PLATFORM_LINUX */ struct addrinfo hints; struct addrinfo* result; struct addrinfo* ptr; @@ -43,13 +58,19 @@ bool uxr_init_tcp_platform( hints.ai_family = AF_INET6; break; } - hints.ai_socktype = SOCK_DGRAM; + hints.ai_socktype = SOCK_STREAM; if (0 == getaddrinfo(ip, port, &hints, &result)) { for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { - if (0 == connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen)) + int connect_rv; + do + { + errno = errsv; + connect_rv = connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen); + } while (-1 == connect_rv && EINTR == errno); + if (0 == connect_rv) { rv = true; break; @@ -62,19 +83,25 @@ bool uxr_init_tcp_platform( } bool uxr_close_tcp_platform( - uxrTCPPlatform* platform) + struct uxrTCPPlatform* platform) { return (-1 == platform->fd) ? true : (0 == close(platform->fd)); } size_t uxr_write_tcp_data_platform( - uxrTCPPlatform* platform, + struct uxrTCPPlatform* platform, const uint8_t* buf, size_t len, uint8_t* errcode) { size_t rv = 0; - ssize_t bytes_sent = send(platform->fd, (void*)buf, len, 0); + int errsv = errno; + ssize_t bytes_sent; + do + { + errno = errsv; + bytes_sent = send(platform->fd, (void*)buf, len, 0); + } while (-1 == bytes_sent && EINTR == errno); if (-1 != bytes_sent) { rv = (size_t)bytes_sent; @@ -88,27 +115,44 @@ size_t uxr_write_tcp_data_platform( } size_t uxr_read_tcp_data_platform( - uxrTCPPlatform* platform, + struct uxrTCPPlatform* platform, uint8_t* buf, size_t len, int timeout, uint8_t* errcode) { size_t rv = 0; + int errsv = errno; + + int64_t start_timestamp = uxr_millis(); + int remaining_time = timeout; - timeout = (timeout <= 0) ? 1 : timeout; + ssize_t bytes_received; + do + { + errno = errsv; + + remaining_time = (remaining_time <= 0) ? 1 : remaining_time; + + struct timeval tv; + tv.tv_sec = remaining_time / 1000; + tv.tv_usec = (remaining_time % 1000) * 1000; + + if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) + { + *errcode = 1; + return 0; + } - struct timeval tv; - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; + bytes_received = recv(platform->fd, (void*)buf, len, 0); - if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) + remaining_time = timeout - (int)(uxr_millis() - start_timestamp); + } while (-1 == bytes_received && EINTR == errno); + if (-1 == bytes_received && (EAGAIN == errno || EWOULDBLOCK == errno)) { - *errcode = 1; - return 0; + errno = errsv; + bytes_received = 0; } - - ssize_t bytes_received = recv(platform->fd, (void*)buf, len, 0); if (-1 != bytes_received) { rv = (size_t)bytes_received; diff --git a/src/c/profile/transport/ip/udp/udp_transport_posix.c b/src/c/profile/transport/ip/udp/udp_transport_posix.c index c9e331032..c311ff3ce 100644 --- a/src/c/profile/transport/ip/udp/udp_transport_posix.c +++ b/src/c/profile/transport/ip/udp/udp_transport_posix.c @@ -1,4 +1,5 @@ #include +#include #include "udp_transport_internal.h" #include @@ -14,6 +15,7 @@ bool uxr_init_udp_platform( const char* port) { bool rv = false; + int errsv = errno; switch (ip_protocol) { @@ -47,7 +49,13 @@ bool uxr_init_udp_platform( { for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { - if (0 == connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen)) + int connect_rv; + do + { + errno = errsv; + connect_rv = connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen); + } while (-1 == connect_rv && EINTR == errno); + if (0 == connect_rv) { platform->poll_fd.events = POLLIN; rv = true; @@ -73,7 +81,13 @@ size_t uxr_write_udp_data_platform( uint8_t* errcode) { size_t rv = 0; - ssize_t bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0); + int errsv = errno; + ssize_t bytes_sent; + do + { + errno = errsv; + bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0); + } while (-1 == bytes_sent && EINTR == errno); if (-1 != bytes_sent) { rv = (size_t)bytes_sent; @@ -94,10 +108,25 @@ size_t uxr_read_udp_data_platform( uint8_t* errcode) { size_t rv = 0; - int poll_rv = poll(&platform->poll_fd, 1, timeout); + int errsv = errno; + int64_t start_timestamp = uxr_millis(); + int remaining_time = timeout; + int poll_rv; + do + { + errno = errsv; + remaining_time = (remaining_time <= 0) ? 0 : remaining_time; + poll_rv = poll(&platform->poll_fd, 1, remaining_time); + remaining_time = timeout - (int)(uxr_millis() - start_timestamp); + } while (-1 == poll_rv && EINTR == errno); if (0 < poll_rv) { - ssize_t bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0); + ssize_t bytes_received; + do + { + errno = errsv; + bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0); + } while (-1 == bytes_received && EINTR == errno); if (-1 != bytes_received) { rv = (size_t)bytes_received; diff --git a/src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c b/src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c index b57211e0e..dfda6c3c4 100644 --- a/src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c +++ b/src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c @@ -1,4 +1,5 @@ #include +#include #include "udp_transport_internal.h" #include @@ -16,6 +17,7 @@ bool uxr_init_udp_platform( const char* port) { bool rv = false; + int errsv = errno; switch (ip_protocol) { @@ -49,7 +51,13 @@ bool uxr_init_udp_platform( { for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { - if (0 == connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen)) + int connect_rv; + do + { + errno = errsv; + connect_rv = connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen); + } while (-1 == connect_rv && EINTR == errno); + if (0 == connect_rv) { rv = true; break; @@ -74,7 +82,13 @@ size_t uxr_write_udp_data_platform( uint8_t* errcode) { size_t rv = 0; - ssize_t bytes_sent = send(platform->fd, (void*)buf, len, 0); + int errsv = errno; + ssize_t bytes_sent; + do + { + errno = errsv; + bytes_sent = send(platform->fd, (void*)buf, len, 0); + } while (-1 == bytes_sent && EINTR == errno); if (-1 != bytes_sent) { rv = (size_t)bytes_sent; @@ -95,20 +109,37 @@ size_t uxr_read_udp_data_platform( uint8_t* errcode) { size_t rv = 0; + int errsv = errno; + + int64_t start_timestamp = uxr_millis(); + int remaining_time = timeout; - timeout = (timeout <= 0) ? 1 : timeout; + ssize_t bytes_received; + do + { + errno = errsv; + + remaining_time = (remaining_time <= 0) ? 1 : remaining_time; - struct timeval tv; - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; + struct timeval tv; + tv.tv_sec = remaining_time / 1000; + tv.tv_usec = (remaining_time % 1000) * 1000; - if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) + if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) + { + *errcode = 1; + return 0; + } + + bytes_received = recv(platform->fd, (void*)buf, len, 0); + + remaining_time = timeout - (int)(uxr_millis() - start_timestamp); + } while (-1 == bytes_received && EINTR == errno); + if (-1 == bytes_received && (EAGAIN == errno || EWOULDBLOCK == errno)) { - *errcode = 1; - return 0; + errno = errsv; + bytes_received = 0; } - - ssize_t bytes_received = recv(platform->fd, (void*)buf, len, 0); if (-1 != bytes_received) { rv = (size_t)bytes_received;