diff options
Diffstat (limited to 'libs/enet/unix.c')
-rw-r--r-- | libs/enet/unix.c | 149 |
1 files changed, 134 insertions, 15 deletions
diff --git a/libs/enet/unix.c b/libs/enet/unix.c index 69715413..19ee76f3 100644 --- a/libs/enet/unix.c +++ b/libs/enet/unix.c @@ -2,13 +2,14 @@ @file unix.c @brief ENet Unix system specific functions */ -#ifndef WIN32 +#ifndef _WIN32 #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/time.h> #include <arpa/inet.h> +#include <netinet/tcp.h> #include <netdb.h> #include <unistd.h> #include <string.h> @@ -18,13 +19,30 @@ #define ENET_BUILDING_LIB 1 #include "enet/enet.h" -#ifdef HAS_FCNTL -#include <fcntl.h> -#endif - #ifdef __APPLE__ +#ifdef HAS_POLL #undef HAS_POLL #endif +#ifndef HAS_FCNTL +#define HAS_FCNTL 1 +#endif +#ifndef HAS_INET_PTON +#define HAS_INET_PTON 1 +#endif +#ifndef HAS_INET_NTOP +#define HAS_INET_NTOP 1 +#endif +#ifndef HAS_MSGHDR_FLAGS +#define HAS_MSGHDR_FLAGS 1 +#endif +#ifndef HAS_SOCKLEN_T +#define HAS_SOCKLEN_T 1 +#endif +#endif + +#ifdef HAS_FCNTL +#include <fcntl.h> +#endif #ifdef HAS_POLL #include <sys/poll.h> @@ -52,6 +70,12 @@ enet_deinitialize (void) } enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) time (NULL); +} + +enet_uint32 enet_time_get (void) { struct timeval timeVal; @@ -80,7 +104,7 @@ enet_address_set_host (ENetAddress * address, const char * name) char buffer [2048]; int errnum; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum); @@ -114,7 +138,12 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL #else char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr != NULL) - strncpy (name, addr, nameLength); + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } else #endif return -1; @@ -133,7 +162,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng in.s_addr = address -> host; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum); @@ -146,8 +175,13 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng if (hostEntry == NULL) return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } return 0; } @@ -177,6 +211,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) sizeof (struct sockaddr_in)); } +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + socklen_t sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + int enet_socket_listen (ENetSocket socket, int backlog) { @@ -197,7 +246,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) { case ENET_SOCKOPT_NONBLOCK: #ifdef HAS_FCNTL - result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL)); + result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK)); #else result = ioctl (socket, FIONBIO, & value); #endif @@ -219,6 +268,46 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_SNDTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == -1 ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = -1; + socklen_t len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof (int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len); + break; + default: break; } @@ -229,6 +318,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -236,7 +326,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == -1 && errno == EINPROGRESS) + return 0; + + return result; } ENetSocket @@ -262,10 +356,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how); +} + void enet_socket_destroy (ENetSocket socket) { - close (socket); + if (socket != -1) + close (socket); } int @@ -383,7 +484,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou pollCount = poll (& pollSocket, 1, timeout); if (pollCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; @@ -417,7 +527,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); if (selectCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; |