summaryrefslogtreecommitdiff
path: root/libs/enet/unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/enet/unix.c')
-rw-r--r--libs/enet/unix.c149
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;