| /* |
| * Copyright 2012 The Emscripten Authors. All rights reserved. |
| * Emscripten is available under two separate licenses, the MIT license and the |
| * University of Illinois/NCSA Open Source License. Both these licenses can be |
| * found in the LICENSE file. |
| */ |
| |
| /** |
| @file win32.c |
| @brief ENet Win32 system specific functions |
| */ |
| #ifdef WIN32 |
| |
| #include <time.h> |
| #define ENET_BUILDING_LIB 1 |
| #include "enet/enet.h" |
| |
| static enet_uint32 timeBase = 0; |
| |
| int |
| enet_initialize (void) |
| { |
| WORD versionRequested = MAKEWORD (1, 1); |
| WSADATA wsaData; |
| |
| if (WSAStartup (versionRequested, & wsaData)) |
| return -1; |
| |
| if (LOBYTE (wsaData.wVersion) != 1|| |
| HIBYTE (wsaData.wVersion) != 1) |
| { |
| WSACleanup (); |
| |
| return -1; |
| } |
| |
| timeBeginPeriod (1); |
| |
| return 0; |
| } |
| |
| void |
| enet_deinitialize (void) |
| { |
| timeEndPeriod (1); |
| |
| WSACleanup (); |
| } |
| |
| enet_uint32 |
| enet_time_get (void) |
| { |
| return (enet_uint32) timeGetTime () - timeBase; |
| } |
| |
| void |
| enet_time_set (enet_uint32 newTimeBase) |
| { |
| timeBase = (enet_uint32) timeGetTime () - newTimeBase; |
| } |
| |
| int |
| enet_address_set_host (ENetAddress * address, const char * name) |
| { |
| struct hostent * hostEntry; |
| |
| hostEntry = gethostbyname (name); |
| if (hostEntry == NULL || |
| hostEntry -> h_addrtype != AF_INET) |
| { |
| unsigned long host = inet_addr (name); |
| if (host == INADDR_NONE) |
| return -1; |
| address -> host = host; |
| return 0; |
| } |
| |
| address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; |
| |
| return 0; |
| } |
| |
| int |
| enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) |
| { |
| char * addr = inet_ntoa (* (struct in_addr *) & address -> host); |
| if (addr == NULL) |
| return -1; |
| strncpy (name, addr, nameLength); |
| return 0; |
| } |
| |
| int |
| enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) |
| { |
| struct in_addr in; |
| struct hostent * hostEntry; |
| |
| in.s_addr = address -> host; |
| |
| hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); |
| if (hostEntry == NULL) |
| return enet_address_get_host_ip (address, name, nameLength); |
| |
| strncpy (name, hostEntry -> h_name, nameLength); |
| |
| return 0; |
| } |
| |
| int |
| enet_socket_bind (ENetSocket socket, const ENetAddress * address) |
| { |
| struct sockaddr_in sin; |
| |
| memset (& sin, 0, sizeof (struct sockaddr_in)); |
| |
| sin.sin_family = AF_INET; |
| |
| if (address != NULL) |
| { |
| sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); |
| sin.sin_addr.s_addr = address -> host; |
| } |
| else |
| { |
| sin.sin_port = 0; |
| sin.sin_addr.s_addr = INADDR_ANY; |
| } |
| |
| return bind (socket, |
| (struct sockaddr *) & sin, |
| sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; |
| } |
| |
| int |
| enet_socket_listen (ENetSocket socket, int backlog) |
| { |
| return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; |
| } |
| |
| ENetSocket |
| enet_socket_create (ENetSocketType type) |
| { |
| return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); |
| } |
| |
| int |
| enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) |
| { |
| int result = SOCKET_ERROR; |
| switch (option) |
| { |
| case ENET_SOCKOPT_NONBLOCK: |
| { |
| u_long nonBlocking = (u_long) value; |
| result = ioctlsocket (socket, FIONBIO, & nonBlocking); |
| break; |
| } |
| |
| case ENET_SOCKOPT_BROADCAST: |
| result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int)); |
| break; |
| |
| case ENET_SOCKOPT_REUSEADDR: |
| result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int)); |
| break; |
| |
| case ENET_SOCKOPT_RCVBUF: |
| result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int)); |
| break; |
| |
| case ENET_SOCKOPT_SNDBUF: |
| result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); |
| break; |
| |
| case ENET_SOCKOPT_RCVTIMEO: |
| result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); |
| break; |
| |
| case ENET_SOCKOPT_SNDTIMEO: |
| result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); |
| break; |
| |
| default: |
| break; |
| } |
| return result == SOCKET_ERROR ? -1 : 0; |
| } |
| |
| int |
| enet_socket_connect (ENetSocket socket, const ENetAddress * address) |
| { |
| struct sockaddr_in sin; |
| |
| memset (& sin, 0, sizeof (struct sockaddr_in)); |
| |
| sin.sin_family = AF_INET; |
| 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)) == SOCKET_ERROR ? -1 : 0; |
| } |
| |
| ENetSocket |
| enet_socket_accept (ENetSocket socket, ENetAddress * address) |
| { |
| SOCKET result; |
| struct sockaddr_in sin; |
| int sinLength = sizeof (struct sockaddr_in); |
| |
| result = accept (socket, |
| address != NULL ? (struct sockaddr *) & sin : NULL, |
| address != NULL ? & sinLength : NULL); |
| |
| if (result == INVALID_SOCKET) |
| return ENET_SOCKET_NULL; |
| |
| if (address != NULL) |
| { |
| address -> host = (enet_uint32) sin.sin_addr.s_addr; |
| address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); |
| } |
| |
| return result; |
| } |
| |
| void |
| enet_socket_destroy (ENetSocket socket) |
| { |
| closesocket (socket); |
| } |
| |
| int |
| enet_socket_send (ENetSocket socket, |
| const ENetAddress * address, |
| const ENetBuffer * buffers, |
| size_t bufferCount) |
| { |
| struct sockaddr_in sin; |
| DWORD sentLength; |
| |
| if (address != NULL) |
| { |
| memset (& sin, 0, sizeof (struct sockaddr_in)); |
| |
| sin.sin_family = AF_INET; |
| sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); |
| sin.sin_addr.s_addr = address -> host; |
| } |
| |
| if (WSASendTo (socket, |
| (LPWSABUF) buffers, |
| (DWORD) bufferCount, |
| & sentLength, |
| 0, |
| address != NULL ? (struct sockaddr *) & sin : NULL, |
| address != NULL ? sizeof (struct sockaddr_in) : 0, |
| NULL, |
| NULL) == SOCKET_ERROR) |
| { |
| if (WSAGetLastError () == WSAEWOULDBLOCK) |
| return 0; |
| |
| return -1; |
| } |
| |
| return (int) sentLength; |
| } |
| |
| int |
| enet_socket_receive (ENetSocket socket, |
| ENetAddress * address, |
| ENetBuffer * buffers, |
| size_t bufferCount) |
| { |
| INT sinLength = sizeof (struct sockaddr_in); |
| DWORD flags = 0, |
| recvLength; |
| struct sockaddr_in sin; |
| |
| if (WSARecvFrom (socket, |
| (LPWSABUF) buffers, |
| (DWORD) bufferCount, |
| & recvLength, |
| & flags, |
| address != NULL ? (struct sockaddr *) & sin : NULL, |
| address != NULL ? & sinLength : NULL, |
| NULL, |
| NULL) == SOCKET_ERROR) |
| { |
| switch (WSAGetLastError ()) |
| { |
| case WSAEWOULDBLOCK: |
| case WSAECONNRESET: |
| return 0; |
| } |
| |
| return -1; |
| } |
| |
| if (flags & MSG_PARTIAL) |
| return -1; |
| |
| if (address != NULL) |
| { |
| address -> host = (enet_uint32) sin.sin_addr.s_addr; |
| address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); |
| } |
| |
| return (int) recvLength; |
| } |
| |
| int |
| enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout) |
| { |
| struct timeval timeVal; |
| |
| timeVal.tv_sec = timeout / 1000; |
| timeVal.tv_usec = (timeout % 1000) * 1000; |
| |
| return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal); |
| } |
| |
| int |
| enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout) |
| { |
| fd_set readSet, writeSet; |
| struct timeval timeVal; |
| int selectCount; |
| |
| timeVal.tv_sec = timeout / 1000; |
| timeVal.tv_usec = (timeout % 1000) * 1000; |
| |
| FD_ZERO (& readSet); |
| FD_ZERO (& writeSet); |
| |
| if (* condition & ENET_SOCKET_WAIT_SEND) |
| FD_SET (socket, & writeSet); |
| |
| if (* condition & ENET_SOCKET_WAIT_RECEIVE) |
| FD_SET (socket, & readSet); |
| |
| selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); |
| |
| if (selectCount < 0) |
| return -1; |
| |
| * condition = ENET_SOCKET_WAIT_NONE; |
| |
| if (selectCount == 0) |
| return 0; |
| |
| if (FD_ISSET (socket, & writeSet)) |
| * condition |= ENET_SOCKET_WAIT_SEND; |
| |
| if (FD_ISSET (socket, & readSet)) |
| * condition |= ENET_SOCKET_WAIT_RECEIVE; |
| |
| return 0; |
| } |
| |
| #endif |
| |