diff --git a/examples/network/network_test.c b/examples/network/network_test.c index e3107f66c..e843d454b 100644 --- a/examples/network/network_test.c +++ b/examples/network/network_test.c @@ -71,7 +71,8 @@ void test_resolve_host() const char * address = "localhost"; const char * port = "80"; AddressInformation *addr = AllocAddressList(3); - int count = ResolveHost(address, port, addr); + int count = ResolveHost(address, port, ADDRESS_TYPE_IPV4, 0, addr); + assert(GetAddressFamily(addr[0]) == ADDRESS_TYPE_IPV6); assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4); assert(GetAddressSocketType(addr[0]) == 0); diff --git a/projects/VS2017/examples/core_basic_window.vcxproj b/projects/VS2017/examples/core_basic_window.vcxproj index f49ced0fb..83e790db0 100644 --- a/projects/VS2017/examples/core_basic_window.vcxproj +++ b/projects/VS2017/examples/core_basic_window.vcxproj @@ -22,33 +22,33 @@ {0981CA98-E4A5-4DF1-987F-A41D09131EFC} Win32Proj core_basic_window - 10.0.17763.0 + 10.0 core_basic_window Application true - v141 + v142 Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/core_basic_window_cpp.vcxproj b/projects/VS2017/examples/core_basic_window_cpp.vcxproj index 6387e80c1..949253fcf 100644 --- a/projects/VS2017/examples/core_basic_window_cpp.vcxproj +++ b/projects/VS2017/examples/core_basic_window_cpp.vcxproj @@ -22,33 +22,33 @@ {B655E850-3322-42F7-941D-6AC18FD66CA1} Win32Proj raylib_example_cpp - 10.0.17763.0 + 10.0 core_basic_window_cpp Application true - v141 + v142 Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_chat_client.vcxproj b/projects/VS2017/examples/network_chat_client.vcxproj index 2c111213f..c02320f5e 100644 --- a/projects/VS2017/examples/network_chat_client.vcxproj +++ b/projects/VS2017/examples/network_chat_client.vcxproj @@ -31,33 +31,33 @@ {80AE5E50-FAC7-434F-A898-2878568E7D79} Win32Proj network_chat_client - 10.0.17763.0 + 10.0 network_chat_client Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_chat_server.vcxproj b/projects/VS2017/examples/network_chat_server.vcxproj index 8269e2086..e92f60321 100644 --- a/projects/VS2017/examples/network_chat_server.vcxproj +++ b/projects/VS2017/examples/network_chat_server.vcxproj @@ -31,33 +31,33 @@ {BC49AAF0-E8C2-4F94-A60A-C56993023C6D} Win32Proj network_chat_server - 10.0.17763.0 + 10.0 network_chat_server Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_ping_pong.vcxproj b/projects/VS2017/examples/network_ping_pong.vcxproj index 6d62e01d2..9e1a92130 100644 --- a/projects/VS2017/examples/network_ping_pong.vcxproj +++ b/projects/VS2017/examples/network_ping_pong.vcxproj @@ -31,32 +31,32 @@ {56EB485C-00A9-459E-B758-2E86316EB7FD} Win32Proj network_ping_pong - 10.0.17763.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_resolve_host.vcxproj b/projects/VS2017/examples/network_resolve_host.vcxproj index 7a354192b..6f86939aa 100644 --- a/projects/VS2017/examples/network_resolve_host.vcxproj +++ b/projects/VS2017/examples/network_resolve_host.vcxproj @@ -31,33 +31,33 @@ {A16D19CB-6AF4-4D17-8318-EABD8805247C} Win32Proj network_resolve_host - 10.0.17763.0 + 10.0 network_resolve_host Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_serialisation.vcxproj b/projects/VS2017/examples/network_serialisation.vcxproj index 57048bd4f..dd172a4da 100644 --- a/projects/VS2017/examples/network_serialisation.vcxproj +++ b/projects/VS2017/examples/network_serialisation.vcxproj @@ -31,33 +31,33 @@ {46B18968-56BC-4FB1-A7C0-FA418E095AFD} Win32Proj network_serialisation - 10.0.17763.0 + 10.0 network_serialisation Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_tcp_client.vcxproj b/projects/VS2017/examples/network_tcp_client.vcxproj index d33fa7424..87dd01c36 100644 --- a/projects/VS2017/examples/network_tcp_client.vcxproj +++ b/projects/VS2017/examples/network_tcp_client.vcxproj @@ -31,33 +31,33 @@ {3415FF09-CF64-451E-AC03-F2A30EC2AFD5} Win32Proj network_tcp_client - 10.0.17763.0 + 10.0 network_tcp_client Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_tcp_server.vcxproj b/projects/VS2017/examples/network_tcp_server.vcxproj index 6da6ecf53..c3cdf8f83 100644 --- a/projects/VS2017/examples/network_tcp_server.vcxproj +++ b/projects/VS2017/examples/network_tcp_server.vcxproj @@ -31,33 +31,33 @@ {B7AA867E-AA24-4CD6-A61E-5A0B9A068131} Win32Proj network_tcp_server - 10.0.17763.0 + 10.0 network_tcp_server Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_test.vcxproj b/projects/VS2017/examples/network_test.vcxproj index 5d8d78988..9dcfd23cd 100644 --- a/projects/VS2017/examples/network_test.vcxproj +++ b/projects/VS2017/examples/network_test.vcxproj @@ -22,33 +22,33 @@ {4297B501-7D79-4192-BC79-C6A8121B6C83} Win32Proj network_test - 10.0.17763.0 + 10.0 network_test Application true - v141 + v142 Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_udp_client.vcxproj b/projects/VS2017/examples/network_udp_client.vcxproj index cd93a1c4c..b550c80ef 100644 --- a/projects/VS2017/examples/network_udp_client.vcxproj +++ b/projects/VS2017/examples/network_udp_client.vcxproj @@ -31,33 +31,33 @@ {0207D9BA-25E0-44A0-9B54-952FFDA3D58D} Win32Proj network_udp_client - 10.0.17763.0 + 10.0 network_udp_client Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/examples/network_udp_server.vcxproj b/projects/VS2017/examples/network_udp_server.vcxproj index 1a47e09f0..baeb35bd0 100644 --- a/projects/VS2017/examples/network_udp_server.vcxproj +++ b/projects/VS2017/examples/network_udp_server.vcxproj @@ -31,33 +31,33 @@ {C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A} Win32Proj network_udp_server - 10.0.17763.0 + 10.0 network_udp_server Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/projects/VS2017/raylib/raylib.vcxproj b/projects/VS2017/raylib/raylib.vcxproj index e5fadcca8..6a69e27c0 100644 --- a/projects/VS2017/raylib/raylib.vcxproj +++ b/projects/VS2017/raylib/raylib.vcxproj @@ -22,32 +22,32 @@ {E89D61AC-55DE-4482-AFD4-DF7242EBC859} Win32Proj raylib - 10.0.17763.0 + 10.0 StaticLibrary true - v141 + v142 Unicode DynamicLibrary true - v141 + v142 Unicode StaticLibrary false - v141 + v142 true Unicode DynamicLibrary false - v141 + v142 true Unicode diff --git a/src/raylib.h b/src/raylib.h index 0aac73f73..69d392a3d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -479,7 +479,7 @@ typedef struct VrStereoConfig { } VrStereoConfig; // Network typedefs -typedef uint32_t SocketChannel; +typedef uint32_t SocketChannel; typedef struct _AddressInformation * AddressInformation; typedef struct _SocketAddress * SocketAddress; typedef struct _SocketAddressIPv4 * SocketAddressIPv4; @@ -487,81 +487,89 @@ typedef struct _SocketAddressIPv6 * SocketAddressIPv6; typedef struct _SocketAddressStorage *SocketAddressStorage; // IPAddress definition (in network byte order) -typedef struct IPAddress { +typedef struct IPAddress +{ unsigned long host; /* 32-bit IPv4 host address */ unsigned short port; /* 16-bit protocol port */ -} IPAddress; +} IPAddress; // An option ID, value, sizeof(value) tuple for setsockopt(2). -typedef struct SocketOpt { +typedef struct SocketOpt +{ int id; void *value; int valueLen; } SocketOpt; -typedef enum { +typedef enum +{ SOCKET_TCP = 1, // SOCK_STREAM SOCKET_UDP = 2 // SOCK_DGRAM } SocketType; -typedef struct UDPChannel { +typedef struct UDPChannel +{ int numbound; // The total number of addresses this channel is bound to IPAddress address[SOCKET_MAX_UDPADDRESSES]; // The list of remote addresses this channel is bound to } UDPChannel; -typedef struct Socket { +typedef struct Socket +{ int ready; // Is the socket ready? i.e. has information int status; // The last status code to have occured using this socket bool isServer; // Is this socket a server socket (i.e. TCP/UDP Listen Server) - bool isIPv6; SocketChannel channel; // The socket handle id SocketType type; // Is this socket a TCP or UDP socket? - IPAddress address; // The host/target IPv4 for this socket (in network byte order) + bool isIPv6; // Is this socket address an ipv6 address? SocketAddressIPv4 addripv4; // The host/target IPv4 for this socket (in network byte order) SocketAddressIPv6 addripv6; // The host/target IPv6 for this socket (in network byte order) + struct UDPChannel binding[SOCKET_MAX_UDPCHANNELS]; // The amount of channels (if UDP) this socket is bound to } Socket; -typedef struct SocketSet { +typedef struct SocketSet +{ int numsockets; int maxsockets; struct Socket **sockets; } SocketSet; -typedef struct SocketDataPacket { - int channel; /* The src/dst channel of the packet */ - unsigned char *data; /* The packet data */ - int len; /* The length of the packet data */ - int maxlen; /* The size of the data buffer */ - int status; /* packet status after sending */ - IPAddress address; /* The source/dest address of an incoming/outgoing packet */ +typedef struct SocketDataPacket +{ + int channel; // The src/dst channel of the packet + unsigned char *data; // The packet data + int len; // The length of the packet data + int maxlen; // The size of the data buffer + int status; // packet status after sending + IPAddress address; // The source/dest address of an incoming/outgoing packet } SocketDataPacket; -// Configuration for a socket. Not all of these fields need to -// be set, and ones omitted from a C99-style "designated initializer" -// struct literal will be zeroed out and replaced with defaults. -typedef struct SocketConfig { - char * host; // The host address in xxx.xxx.xxx.xxx form - char * port; // The target port/service in the form "http" or "25565" - bool server; // Listen for incoming clients? - SocketType type; - bool nonblocking; // non-blocking operation? - int backlog_size; // set a custom backlog size - SocketOpt sockopts[SOCKET_MAX_SOCK_OPTS]; -} SocketConfig; +// Configuration for a socket. +typedef struct SocketConfig +{ + char * host; // The host address in xxx.xxx.xxx.xxx form + char * port; // The target port/service in the form "http" or "25565" + bool server; // Listen for incoming clients? + SocketType type; // The type of socket, TCP/UDP + bool nonblocking; // non-blocking operation? + int backlog_size; // set a custom backlog size + SocketOpt sockopts[SOCKET_MAX_SOCK_OPTS]; +} SocketConfig; // Result from calling open with a given config. -typedef struct SocketResult { +typedef struct SocketResult +{ int status; - Socket *socket; + Socket *socket; } SocketResult; // -typedef struct Packet { +typedef struct Packet +{ uint32_t size; // The total size of bytes in data uint32_t offs; // The offset to data access uint32_t maxs; // The max size of data - uint8_t* data; // Data stored in network byte order + uint8_t *data; // Data stored in network byte order } Packet; //---------------------------------------------------------------------------------- @@ -1539,6 +1547,8 @@ RLAPI int GetAddressProtocol(AddressInformation address); RLAPI char* GetAddressCanonName(AddressInformation address); RLAPI char *GetAddressHostAndPort(AddressInformation address, char *outhost, int *outport); RLAPI void PrintAddressInfo(AddressInformation address); + +// Address Memory API RLAPI AddressInformation AllocAddress(); RLAPI void FreeAddress(AddressInformation* addressInfo); RLAPI AddressInformation *AllocAddressList(int size); @@ -1553,14 +1563,23 @@ RLAPI Socket *SocketAccept(Socket *server, SocketConfig *config); // UDP Socket API RLAPI int SocketSetChannel(Socket *socket, int channel, const IPAddress *address); RLAPI void SocketUnsetChannel(Socket *socket, int channel); -RLAPI IPAddress* SocketGetPeerAddress(Socket *socket, int channel); + +// UDP DataPacket API +RLAPI SocketDataPacket *AllocPacket(int size); +RLAPI int ResizePacket(SocketDataPacket *packet, int newsize); +RLAPI void FreePacket(SocketDataPacket *packet); +RLAPI SocketDataPacket** AllocPacketList(int count, int size); +RLAPI void FreePacketList(SocketDataPacket **packets); // General Socket API RLAPI int SocketSend(Socket *sock, const void *datap, int len); RLAPI int SocketReceive(Socket *sock, void *data, int maxlen); RLAPI void SocketClose(Socket* sock); -RLAPI int SocketReady(Socket* sock); +RLAPI SocketAddressStorage SocketGetPeerAddress(Socket* sock); +RLAPI char* GetSocketAddressHost(SocketAddressStorage storage); +RLAPI short GetSocketAddressPort(SocketAddressStorage storage); +// Socket Memory API RLAPI Socket *AllocSocket(); RLAPI void FreeSocket(Socket **sock); RLAPI SocketResult *AllocSocketResult(); @@ -1576,8 +1595,8 @@ RLAPI int RemoveSocket(SocketSet *set, Socket *sock); RLAPI int CheckSockets(SocketSet *set, unsigned int timeout); // Packet API -Packet * AllocPacket(int size); -void FreePacket(Packet *packet); +// Packet * AllocPacket(int size); +// void FreePacket(Packet *packet); void PacketSend(Packet *packet); void PacketReceive(Packet *packet); void PacketWrite8(Packet *packet, uint16_t value); diff --git a/src/rnet.c b/src/rnet.c index 56dbac78c..f29f32bf2 100644 --- a/src/rnet.c +++ b/src/rnet.c @@ -58,19 +58,24 @@ // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef struct _SocketAddress { +typedef struct _SocketAddress +{ struct sockaddr address; } _SocketAddress; -typedef struct _SocketAddressIPv4 { +typedef struct _SocketAddressIPv4 +{ struct sockaddr_in address; } _SocketAddressIPv4; -typedef struct _SocketAddressIPv6 { +typedef struct _SocketAddressIPv6 +{ struct sockaddr_in6 address; } _SocketAddressIPv6; -typedef struct _SocketAddressStorage { +typedef struct _SocketAddressStorage +{ struct sockaddr_storage address; } _SocketAddressStorage; -typedef struct _AddressInformation { +typedef struct _AddressInformation +{ struct addrinfo addr; } _AddressInformation; @@ -78,24 +83,24 @@ typedef struct _AddressInformation { // Global module forward declarations //---------------------------------------------------------------------------------- +static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol); +static const char *SocketAddressToString(struct sockaddr_storage *sockaddr); +static bool IsIPv4Address(const char *ip); +static bool IsIPv6Address(const char *ip); +static void * GetSocketPortPtr(struct sockaddr_storage *sa); +static void * GetSocketAddressPtr(struct sockaddr_storage *sa); static bool IsSocketValid(Socket *sock); static void SocketSetLastError(int err); static int SocketGetLastError(); static char * SocketGetLastErrorString(); static char * SocketErrorCodeToString(int err); static bool SocketSetDefaults(SocketConfig *config); -static bool InitSocket(Socket *outsock, struct addrinfo *addr); +static bool InitSocket(Socket *sock, struct addrinfo *addr); static bool CreateSocket(SocketConfig *config, SocketResult *outresult); -static bool SocketSetBlocking(Socket *out); -static bool SocketSetNonBlocking(Socket *out); -static bool SocketSetOptions(SocketConfig *config, Socket *channel); -static void * GetSocketAddressPtr(struct sockaddr *sa); -static void * GetSocketPortPtr(struct sockaddr *sa); +static bool SocketSetBlocking(Socket *sock); +static bool SocketSetNonBlocking(Socket *sock); +static bool SocketSetOptions(SocketConfig *config, Socket *sock); static void SocketSetHints(SocketConfig *config, struct addrinfo *hints); -static bool IsIPv4Address(const char *ip); -static bool IsIPv6Address(const char *ip); -static const char *SocketAddressToString(struct sockaddr_storage *sockaddr); -static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol); //---------------------------------------------------------------------------------- // Global module implementation @@ -104,27 +109,35 @@ static void PrintSocket(struct sockaddr_storage *addr, const int family, // Print socket information static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol) { - switch (family) { - case AF_UNSPEC: { - TraceLog(LOG_DEBUG, "\tFamily: Unspecified"); - } break; - case AF_INET: { + switch (family) + { + case AF_UNSPEC: { TraceLog(LOG_DEBUG, "\tFamily: Unspecified"); + } + break; + case AF_INET: + { TraceLog(LOG_DEBUG, "\tFamily: AF_INET (IPv4)"); TraceLog(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr)); - } break; - case AF_INET6: { + } + break; + case AF_INET6: + { TraceLog(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)"); TraceLog(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr)); - } break; - case AF_NETBIOS: { + } + break; + case AF_NETBIOS: + { TraceLog(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)"); - } break; - default: { - TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family); - } break; + } + break; + default: { TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family); + } + break; } TraceLog(LOG_DEBUG, "\tSocket type:"); - switch (socktype) { + switch (socktype) + { case 0: TraceLog(LOG_DEBUG, "\t- Unspecified"); break; case SOCK_STREAM: TraceLog(LOG_DEBUG, "\t- SOCK_STREAM (stream)"); @@ -142,7 +155,8 @@ static void PrintSocket(struct sockaddr_storage *addr, const int family, const i default: TraceLog(LOG_DEBUG, "\t- Other %ld", socktype); break; } TraceLog(LOG_DEBUG, "\tProtocol:"); - switch (protocol) { + switch (protocol) + { case 0: TraceLog(LOG_DEBUG, "\t- Unspecified"); break; case IPPROTO_TCP: TraceLog(LOG_DEBUG, "\t- IPPROTO_TCP (TCP)"); break; case IPPROTO_UDP: TraceLog(LOG_DEBUG, "\t- IPPROTO_UDP (UDP)"); break; @@ -156,15 +170,20 @@ static const char *SocketAddressToString(struct sockaddr_storage *sockaddr) static ipv6[INET6_ADDRSTRLEN]; assert(sockaddr != NULL); assert(sockaddr->ss_family == AF_INET || sockaddr->ss_family == AF_INET6); - switch (sockaddr->ss_family) { - case AF_INET: { + switch (sockaddr->ss_family) + { + case AF_INET: + { struct sockaddr_in *s = ((struct sockaddr_in *) sockaddr); return inet_ntop(AF_INET, &s->sin_addr, ipv6, INET_ADDRSTRLEN); - } break; - case AF_INET6: { + } + break; + case AF_INET6: + { struct sockaddr_in6 *s = ((struct sockaddr_in6 *) sockaddr); return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN); - } break; + } + break; } return NULL; } @@ -186,9 +205,10 @@ static bool IsIPv6Address(const char *ip) } // Return a pointer to the port from the correct address family (IPv4, or IPv6) -void *GetSocketPortPtr(struct sockaddr *sa) +static void *GetSocketPortPtr(struct sockaddr_storage *sa) { - if (sa->sa_family == AF_INET) { + if (sa->ss_family == AF_INET) + { return &(((struct sockaddr_in *) sa)->sin_port); } @@ -196,9 +216,10 @@ void *GetSocketPortPtr(struct sockaddr *sa) } // Return a pointer to the address from the correct address family (IPv4, or IPv6) -void *GetSocketAddressPtr(struct sockaddr *sa) +static void *GetSocketAddressPtr(struct sockaddr_storage *sa) { - if (sa->sa_family == AF_INET) { + if (sa->ss_family == AF_INET) + { return &(((struct sockaddr_in *) sa)->sin_addr); } @@ -208,7 +229,8 @@ void *GetSocketAddressPtr(struct sockaddr *sa) // Is the socket in a valid state? static bool IsSocketValid(Socket *sock) { - if (sock != NULL) { + if (sock != NULL) + { return (sock->channel != INVALID_SOCKET); } return false; @@ -255,7 +277,8 @@ static char *SocketErrorCodeToString(int err) // Set the defaults in the supplied SocketConfig if they're not already set static bool SocketSetDefaults(SocketConfig *config) { - if (config->backlog_size == 0) { + if (config->backlog_size == 0) + { config->backlog_size = SOCKET_MAX_QUEUE_SIZE; } @@ -265,18 +288,25 @@ static bool SocketSetDefaults(SocketConfig *config) // Create the socket channel static bool InitSocket(Socket *sock, struct addrinfo *addr) { - switch (sock->type) { + switch (sock->type) + { case SOCKET_TCP: - if (addr->ai_family == AF_INET) { + if (addr->ai_family == AF_INET) + { sock->channel = socket(AF_INET, SOCK_STREAM, 0); - } else { + } + else + { sock->channel = socket(AF_INET6, SOCK_STREAM, 0); } break; case SOCKET_UDP: - if (addr->ai_family == AF_INET) { + if (addr->ai_family == AF_INET) + { sock->channel = socket(AF_INET, SOCK_DGRAM, 0); - } else { + } + else + { sock->channel = socket(AF_INET6, SOCK_DGRAM, 0); } break; @@ -330,7 +360,8 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) ); // Did we succeed? - if (addrstatus != 0) { + if (addrstatus != 0) + { outresult->socket->status = SocketGetLastError(); TraceLog(LOG_WARNING, "Socket Error: %s", @@ -342,7 +373,9 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) config->port, SocketGetLastErrorString()); return (success = false); - } else { + } + else + { char hoststr[NI_MAXHOST]; char portstr[NI_MAXSERV]; socklen_t client_len = sizeof(struct sockaddr_storage); @@ -352,9 +385,11 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) // Walk the address information linked-list struct addrinfo *it; - for (it = res; it != NULL; it = it->ai_next) { + for (it = res; it != NULL; it = it->ai_next) + { // Initialise the socket - if (!InitSocket(outresult->socket, it)) { + if (!InitSocket(outresult->socket, it)) + { outresult->socket->status = SocketGetLastError(); TraceLog(LOG_WARNING, "Socket Error: %s", @@ -364,7 +399,8 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) } // Set socket options - if (!SocketSetOptions(config, outresult->socket)) { + if (!SocketSetOptions(config, outresult->socket)) + { outresult->socket->status = SocketGetLastError(); TraceLog(LOG_WARNING, "Socket Error: %s", @@ -375,7 +411,8 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) } } - if (!IsSocketValid(outresult->socket)) { + if (!IsSocketValid(outresult->socket)) + { outresult->socket->status = SocketGetLastError(); TraceLog( LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->status)); @@ -384,21 +421,27 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) return (success = false); } - if (success) { + if (success) + { outresult->status = RESULT_SUCCESS; outresult->socket->ready = 0; outresult->socket->status = 0; - if (!(config->type == SOCKET_UDP)) { + if (!(config->type == SOCKET_UDP)) + { outresult->socket->isServer = config->server; } - switch (res->ai_addr->sa_family) { - case AF_INET: { + switch (res->ai_addr->sa_family) + { + case AF_INET: + { outresult->socket->addripv4 = (struct _SocketAddressIPv4 *) malloc( sizeof(*outresult->socket->addripv4)); - if (outresult->socket->addripv4 != NULL) { + if (outresult->socket->addripv4 != NULL) + { memset(outresult->socket->addripv4, 0, sizeof(*outresult->socket->addripv4)); - if (outresult->socket->addripv4 != NULL) { + if (outresult->socket->addripv4 != NULL) + { memcpy(&outresult->socket->addripv4->address, (struct sockaddr_in *) res->ai_addr, sizeof(struct sockaddr_in)); outresult->socket->isIPv6 = false; @@ -410,14 +453,18 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); } } - } break; - case AF_INET6: { + } + break; + case AF_INET6: + { outresult->socket->addripv6 = (struct _SocketAddressIPv6 *) malloc( sizeof(*outresult->socket->addripv6)); - if (outresult->socket->addripv6 != NULL) { + if (outresult->socket->addripv6 != NULL) + { memset(outresult->socket->addripv6, 0, sizeof(*outresult->socket->addripv6)); - if (outresult->socket->addripv6 != NULL) { + if (outresult->socket->addripv6 != NULL) + { memcpy(&outresult->socket->addripv6->address, (struct sockaddr_in6 *) res->ai_addr, sizeof(struct sockaddr_in6)); outresult->socket->isIPv6 = true; @@ -429,7 +476,8 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult) TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); } } - } break; + } + break; } } freeaddrinfo(res); @@ -445,7 +493,8 @@ static bool SocketSetBlocking(Socket *sock) ret = ioctlsocket(sock->channel, FIONBIO, &mode); #else const int flags = fcntl(sock->channel, F_GETFL, 0); - if (!(flags & O_NONBLOCK)) { + if (!(flags & O_NONBLOCK)) + { TraceLog(LOG_DEBUG, "Socket was already in blocking mode"); return ret; } @@ -464,7 +513,8 @@ static bool SocketSetNonBlocking(Socket *sock) ret = ioctlsocket(sock->channel, FIONBIO, &mode); #else const int flags = fcntl(sock->channel, F_GETFL, 0); - if ((flags & O_NONBLOCK)) { + if ((flags & O_NONBLOCK)) + { TraceLog(LOG_DEBUG, "Socket was already in non-blocking mode"); return ret; } @@ -476,13 +526,16 @@ static bool SocketSetNonBlocking(Socket *sock) // Set options specified in SocketConfig to Socket sock static bool SocketSetOptions(SocketConfig *config, Socket *sock) { - for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) { + for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) + { SocketOpt *opt = &config->sockopts[i]; - if (opt->id == 0) { + if (opt->id == 0) + { break; } - if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) { + if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) + { return false; } } @@ -493,32 +546,43 @@ static bool SocketSetOptions(SocketConfig *config, Socket *sock) // Set "hints" in an addrinfo struct, to be passed to getaddrinfo. static void SocketSetHints(SocketConfig *config, struct addrinfo *hints) { - if (config == NULL || hints == NULL) { + if (config == NULL || hints == NULL) + { return; } memset(hints, 0, sizeof(*hints)); // Check if the ip supplied in the config is a valid ipv4 ip ipv6 address - if (IsIPv4Address(config->host)) { + if (IsIPv4Address(config->host)) + { hints->ai_family = AF_INET; hints->ai_flags |= AI_NUMERICHOST; - } else { - if (IsIPv6Address(config->host)) { + } + else + { + if (IsIPv6Address(config->host)) + { hints->ai_family = AF_INET6; hints->ai_flags |= AI_NUMERICHOST; - } else { + } + else + { hints->ai_family = AF_UNSPEC; } } - if (config->type == SOCKET_UDP) { + if (config->type == SOCKET_UDP) + { hints->ai_socktype = SOCK_DGRAM; - } else { + } + else + { hints->ai_socktype = SOCK_STREAM; } // Set passive unless UDP client - if (!(config->type == SOCKET_UDP) || config->server) { + if (!(config->type == SOCKET_UDP) || config->server) + { hints->ai_flags = AI_PASSIVE; } } @@ -537,14 +601,18 @@ bool InitNetwork() wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) { + if (err != 0) + { TraceLog(LOG_WARNING, "WinSock failed to initialise."); return false; - } else { + } + else + { TraceLog(LOG_INFO, "WinSock initialised."); } - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) + { TraceLog(LOG_WARNING, "WinSock failed to initialise."); WSACleanup(); return false; @@ -597,14 +665,18 @@ void ResolveIP(const char *ip, const char *port, int flags, char *host, char *se ); // Did we succeed? - if (status != 0) { + if (status != 0) + { TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", ip, port, gai_strerror(errno)); - } else { + } + else + { TraceLog(LOG_DEBUG, "Resolving... %s::%s", ip, port); } // Attempt to resolve network byte order ip to hostname - switch (res->ai_family) { + switch (res->ai_family) + { case AF_INET: status = getnameinfo(&*((struct sockaddr *) res->ai_addr), sizeof(*((struct sockaddr_in *) res->ai_addr)), @@ -626,9 +698,12 @@ void ResolveIP(const char *ip, const char *port, int flags, char *host, char *se default: break; } - if (status != 0) { + if (status != 0) + { TraceLog(LOG_WARNING, "Failed to resolve ip %s: %s", ip, SocketGetLastErrorString()); - } else { + } + else + { TraceLog(LOG_DEBUG, "Successfully resolved %s::%s to %s", ip, port, host); } @@ -656,7 +731,6 @@ int ResolveHost(const char *address, const char *service, int addressType, int f struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) struct addrinfo *res; // will point to the results struct addrinfo *iterator; - int portptr; assert(((address != NULL || address != 0) || (service != NULL || service != 0))); assert(((addressType == AF_INET) || (addressType == AF_INET6) || (addressType == AF_UNSPEC))); @@ -671,8 +745,12 @@ int ResolveHost(const char *address, const char *service, int addressType, int f assert(hints.ai_next == NULL || hints.ai_next == 0); // When the address is NULL, populate the IP for me - if (address == NULL) { - hints.ai_flags |= AI_PASSIVE; + if (address == NULL) + { + if ((hints.ai_flags & AI_PASSIVE) == 0) + { + hints.ai_flags |= AI_PASSIVE; + } } TraceLog(LOG_INFO, "Resolving host..."); @@ -685,46 +763,58 @@ int ResolveHost(const char *address, const char *service, int addressType, int f ); // Did we succeed? - if (status != 0) { + if (status != 0) + { int error = SocketGetLastError(); SocketSetLastError(0); TraceLog(LOG_WARNING, "Failed to get resolve host: %s", SocketErrorCodeToString(error)); return -1; - } else { + } + else + { TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, service); } // Calculate the size of the address information list int size = 0; - for (iterator = res; iterator != NULL; iterator = iterator->ai_next) { + for (iterator = res; iterator != NULL; iterator = iterator->ai_next) + { size++; } // Validate the size is > 0, otherwise return - if (size <= 0) { + if (size <= 0) + { TraceLog(LOG_WARNING, "Error, no addresses found."); return -1; } // If not address list was allocated, allocate it dynamically with the known address size - if (outAddr == NULL) { + if (outAddr == NULL) + { outAddr = (AddressInformation *) malloc(size * sizeof(AddressInformation)); } // Dynamically allocate an array of address information structs - if (outAddr != NULL) { + if (outAddr != NULL) + { int i; - for (i = 0; i < size; ++i) { + for (i = 0; i < size; ++i) + { outAddr[i] = AllocAddress(); - if (outAddr[i] == NULL) { + if (outAddr[i] == NULL) + { break; } } outAddr[i] = NULL; - if (i != size) { + if (i != size) + { outAddr = NULL; } - } else { + } + else + { TraceLog(LOG_WARNING, "Error, failed to dynamically allocate memory for the address list"); return -1; @@ -732,8 +822,10 @@ int ResolveHost(const char *address, const char *service, int addressType, int f // Copy all the address information from res into outAddrList int i = 0; - for (iterator = res; iterator != NULL; iterator = iterator->ai_next) { - if (i < size) { + for (iterator = res; iterator != NULL; iterator = iterator->ai_next) + { + if (i < size) + { outAddr[i]->addr.ai_flags = iterator->ai_flags; outAddr[i]->addr.ai_family = iterator->ai_family; outAddr[i]->addr.ai_socktype = iterator->ai_socktype; @@ -781,23 +873,33 @@ bool SocketCreate(SocketConfig *config, SocketResult *result) bool success = true; // Make sure we've not received a null config or result pointer - if (config == NULL || result == NULL) { + if (config == NULL || result == NULL) + { return (success = false); } // Set the defaults based on the config - if (!SocketSetDefaults(config)) { + if (!SocketSetDefaults(config)) + { TraceLog(LOG_WARNING, "Configuration Error."); success = false; - } else { + } + else + { // Create the socket - if (CreateSocket(config, result)) { - if (config->nonblocking) { + if (CreateSocket(config, result)) + { + if (config->nonblocking) + { SocketSetNonBlocking(result->socket); - } else { + } + else + { SocketSetBlocking(result->socket); } - } else { + } + else + { success = false; } } @@ -808,26 +910,36 @@ bool SocketCreate(SocketConfig *config, SocketResult *result) // Note: The bind function is required on an unconnected socket before subsequent calls to the listen function. bool SocketBind(SocketConfig *config, SocketResult *result) { - bool success = false; - result->status = RESULT_FAILURE; - struct sockaddr *sock_addr = NULL; + bool success = false; + result->status = RESULT_FAILURE; + struct sockaddr_storage *sock_addr = NULL; // Don't bind to a socket that isn't configured as a server - if (!IsSocketValid(result->socket) || !config->server) { + if (!IsSocketValid(result->socket) || !config->server) + { TraceLog(LOG_WARNING, "Cannot bind to socket marked as \"Client\" in SocketConfig."); success = false; - } else { - if (result->socket->isIPv6) { - sock_addr = (struct sockaddr *) &result->socket->addripv6->address; - } else { - sock_addr = (struct sockaddr *) &result->socket->addripv4->address; + } + else + { + if (result->socket->isIPv6) + { + sock_addr = (struct sockaddr_storage *) &result->socket->addripv6->address; } - if (sock_addr != NULL) { - if (bind(result->socket->channel, (struct sockaddr *) sock_addr, sizeof(*sock_addr)) != SOCKET_ERROR) { + else + { + sock_addr = (struct sockaddr_storage *) &result->socket->addripv4->address; + } + if (sock_addr != NULL) + { + if (bind(result->socket->channel, (struct sockaddr *) sock_addr, sizeof(*sock_addr)) != SOCKET_ERROR) + { TraceLog(LOG_INFO, "Successfully bound socket."); success = true; - } else { + } + else + { result->socket->status = SocketGetLastError(); TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status)); @@ -837,17 +949,31 @@ bool SocketBind(SocketConfig *config, SocketResult *result) } } // Was the bind a success? - if (success) { + if (success) + { result->status = RESULT_SUCCESS; result->socket->ready = 0; result->socket->status = 0; socklen_t sock_len = sizeof(*sock_addr); - if (getsockname(result->socket->channel, (struct sockaddr *) sock_addr, &sock_len) < 0) { + if (getsockname(result->socket->channel, (struct sockaddr *) sock_addr, &sock_len) < 0) + { TraceLog(LOG_WARNING, "Couldn't get socket address"); - } else { - struct sockaddr_in *s = (struct sockaddr_in *) sock_addr; - result->socket->address.host = s->sin_addr.s_addr; - result->socket->address.port = s->sin_port; + } + else + { + struct sockaddr_in *s = (struct sockaddr_in *) sock_addr; + // result->socket->address.host = s->sin_addr.s_addr; + // result->socket->address.port = s->sin_port; + + // + result->socket->addripv4 + = (struct _SocketAddressIPv4 *) malloc(sizeof(*result->socket->addripv4)); + if (result->socket->addripv4 != NULL) + { + memset(result->socket->addripv4, 0, sizeof(*result->socket->addripv4)); + } + memcpy(&result->socket->addripv4->address, (struct sockaddr_in *) &s->sin_addr, sizeof(struct sockaddr_in)); + // } } return success; @@ -860,20 +986,29 @@ bool SocketListen(SocketConfig *config, SocketResult *result) result->status = RESULT_FAILURE; // Don't bind to a socket that isn't configured as a server - if (!IsSocketValid(result->socket) || !config->server) { + if (!IsSocketValid(result->socket) || !config->server) + { TraceLog(LOG_WARNING, "Cannot listen on socket marked as \"Client\" in SocketConfig."); success = false; - } else { + } + else + { // Don't listen on UDP sockets - if (!(config->type == SOCKET_UDP)) { - if (listen(result->socket->channel, config->backlog_size) != SOCKET_ERROR) { + if (!(config->type == SOCKET_UDP)) + { + if (listen(result->socket->channel, config->backlog_size) != SOCKET_ERROR) + { TraceLog(LOG_INFO, "Started listening on socket..."); success = true; - } else { + } + else + { success = false; } - } else { + } + else + { TraceLog(LOG_WARNING, "Cannot listen on socket marked as \"UDP\" (datagram) in SocketConfig."); success = false; @@ -881,7 +1016,8 @@ bool SocketListen(SocketConfig *config, SocketResult *result) } // Was the listen a success? - if (success) { + if (success) + { result->status = RESULT_SUCCESS; result->socket->ready = 0; result->socket->status = 0; @@ -896,12 +1032,16 @@ bool SocketConnect(SocketConfig *config, SocketResult *result) result->status = RESULT_FAILURE; // Only bind to sockets marked as server - if (config->server) { + if (config->server) + { TraceLog(LOG_WARNING, "Cannot connect to socket marked as \"Server\" in SocketConfig."); success = false; - } else { - if (IsIPv4Address(config->host)) { + } + else + { + if (IsIPv4Address(config->host)) + { struct sockaddr_in ip4addr; ip4addr.sin_family = AF_INET; unsigned long hport; @@ -909,27 +1049,36 @@ bool SocketConnect(SocketConfig *config, SocketResult *result) ip4addr.sin_port = htons(hport); inet_pton(AF_INET, config->host, &ip4addr.sin_addr); int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip4addr, sizeof(ip4addr)); - if (connect_result == SOCKET_ERROR) { + if (connect_result == SOCKET_ERROR) + { result->socket->status = SocketGetLastError(); SocketSetLastError(0); - switch (result->socket->status) { - case WSAEWOULDBLOCK: { + switch (result->socket->status) + { + case WSAEWOULDBLOCK: + { success = true; break; } - default: { + default: + { TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status)); success = false; break; } } - } else { + } + else + { TraceLog(LOG_INFO, "Successfully connected to socket."); success = true; } - } else { - if (IsIPv6Address(config->host)) { + } + else + { + if (IsIPv6Address(config->host)) + { struct sockaddr_in6 ip6addr; ip6addr.sin6_family = AF_INET6; unsigned long hport; @@ -937,22 +1086,28 @@ bool SocketConnect(SocketConfig *config, SocketResult *result) ip6addr.sin6_port = htons(hport); inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr); int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip6addr, sizeof(ip6addr)); - if (connect_result == SOCKET_ERROR) { + if (connect_result == SOCKET_ERROR) + { result->socket->status = SocketGetLastError(); SocketSetLastError(0); - switch (result->socket->status) { - case WSAEWOULDBLOCK: { + switch (result->socket->status) + { + case WSAEWOULDBLOCK: + { success = true; break; } - default: { + default: + { TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status)); success = false; break; } } - } else { + } + else + { TraceLog(LOG_INFO, "Successfully connected to socket."); success = true; } @@ -960,7 +1115,8 @@ bool SocketConnect(SocketConfig *config, SocketResult *result) } } - if (success) { + if (success) + { result->status = RESULT_SUCCESS; result->socket->ready = 0; result->socket->status = 0; @@ -974,13 +1130,45 @@ bool SocketConnect(SocketConfig *config, SocketResult *result) // SocketChannel socket - The id of the socket to close void SocketClose(Socket *sock) { - if (sock != NULL) { - if (sock->channel != INVALID_SOCKET) { + if (sock != NULL) + { + if (sock->channel != INVALID_SOCKET) + { closesocket(sock->channel); } } } +// Returns the sockaddress for a specific socket in a generic storage struct +SocketAddressStorage SocketGetPeerAddress(Socket *sock) +{ + if (sock->isServer) + { + return NULL; + } + if (sock->isIPv6) + { + return sock->addripv6; + } + else + { + return sock->addripv4; + } +} + +// Return the address-type appropriate host portion of a socket address +char *GetSocketAddressHost(SocketAddressStorage storage) +{ + assert(storage->address.ss_family == AF_INET || storage->address.ss_family == AF_INET6); + return SocketAddressToString((struct sockaddr_storage *) storage); +} + +// Return the address-type appropriate port(service) portion of a socket address +short GetSocketAddressPort(SocketAddressStorage storage) +{ + return ntohs(GetSocketPortPtr(storage)); +} + // The accept function permits an incoming connection attempt on a socket. // // SocketChannel listener - The socket to listen for incoming connections on (i.e. server) @@ -999,7 +1187,8 @@ void SocketClose(Socket *sock) // } Socket *SocketAccept(Socket *server, SocketConfig *config) { - if (!server->isServer || server->type == SOCKET_UDP) { + if (!server->isServer || server->type == SOCKET_UDP) + { return NULL; } struct sockaddr_storage sock_addr; @@ -1009,7 +1198,8 @@ Socket *SocketAccept(Socket *server, SocketConfig *config) server->ready = 0; sock_alen = sizeof(sock_addr); sock->channel = accept(server->channel, (struct sockaddr *) &sock_addr, &sock_alen); - if (sock->channel == INVALID_SOCKET) { + if (sock->channel == INVALID_SOCKET) + { sock->status = SocketGetLastError(); TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); SocketSetLastError(0); @@ -1020,27 +1210,34 @@ Socket *SocketAccept(Socket *server, SocketConfig *config) sock->isServer = false; sock->ready = 0; sock->type = server->type; - switch (sock_addr.ss_family) { - case AF_INET: { + switch (sock_addr.ss_family) + { + case AF_INET: + { struct sockaddr_in *s = ((struct sockaddr_in *) &sock_addr); sock->addripv4 = (struct _SocketAddressIPv4 *) malloc(sizeof(*sock->addripv4)); - if (sock->addripv4 != NULL) { + if (sock->addripv4 != NULL) + { memset(sock->addripv4, 0, sizeof(*sock->addripv4)); + memcpy(&sock->addripv4->address, (struct sockaddr_in *) &s->sin_addr, sizeof(struct sockaddr_in)); + TraceLog(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString((struct sockaddr_storage *) s), + ntohs(sock->addripv4->address.sin_port)); } - memcpy(&sock->addripv4->address, (struct sockaddr_in *) &s->sin_addr, sizeof(struct sockaddr_in)); - TraceLog(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString((struct sockaddr_storage *) s), - ntohs(sock->addripv4->address.sin_port)); - } break; - case AF_INET6: { + } + break; + case AF_INET6: + { struct sockaddr_in6 *s = ((struct sockaddr_in6 *) &sock_addr); sock->addripv6 = (struct _SocketAddressIPv6 *) malloc(sizeof(*sock->addripv6)); - if (sock->addripv6 != NULL) { + if (sock->addripv6 != NULL) + { memset(sock->addripv6, 0, sizeof(*sock->addripv6)); + memcpy(&sock->addripv6->address, (struct sockaddr_in6 *) &s->sin6_addr, sizeof(struct sockaddr_in6)); + TraceLog(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString((struct sockaddr_storage *) s), + ntohs(sock->addripv6->address.sin6_port)); } - memcpy(&sock->addripv6->address, (struct sockaddr_in6 *) &s->sin6_addr, sizeof(struct sockaddr_in6)); - TraceLog(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString((struct sockaddr_storage *) s), - ntohs(sock->addripv4->address.sin_port)); - } break; + } + break; } return sock; } @@ -1048,7 +1245,8 @@ Socket *SocketAccept(Socket *server, SocketConfig *config) // Verify that the channel is in the valid range static int ValidChannel(int channel) { - if ((channel < 0) || (channel >= SOCKET_MAX_UDPCHANNELS)) { + if ((channel < 0) || (channel >= SOCKET_MAX_UDPCHANNELS)) + { TraceLog(LOG_WARNING, "Invalid channel"); return 0; } @@ -1059,24 +1257,32 @@ static int ValidChannel(int channel) int SocketSetChannel(Socket *socket, int channel, const IPAddress *address) { struct UDPChannel *binding; - if (socket == NULL) { + if (socket == NULL) + { TraceLog(LOG_WARNING, "Passed a NULL socket"); return (-1); } - if (channel == -1) { - for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel) { + if (channel == -1) + { + for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel) + { binding = &socket->binding[channel]; - if (binding->numbound < SOCKET_MAX_UDPADDRESSES) { + if (binding->numbound < SOCKET_MAX_UDPADDRESSES) + { break; } } - } else { - if (!ValidChannel(channel)) { + } + else + { + if (!ValidChannel(channel)) + { return (-1); } binding = &socket->binding[channel]; } - if (binding->numbound == SOCKET_MAX_UDPADDRESSES) { + if (binding->numbound == SOCKET_MAX_UDPADDRESSES) + { TraceLog(LOG_WARNING, "No room for new addresses"); return (-1); } @@ -1087,30 +1293,105 @@ int SocketSetChannel(Socket *socket, int channel, const IPAddress *address) // Remove the socket channel void SocketUnsetChannel(Socket *socket, int channel) { - if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) { + if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) + { socket->binding[channel].numbound = 0; } } -// Get the primary IP address of the remote system associated with the socket and channel. -// If the channel is not bound, this function returns NULL. -IPAddress *SocketGetPeerAddress(Socket *socket, int channel) +/* Allocate/free a single UDP packet 'size' bytes long. + The new packet is returned, or NULL if the function ran out of memory. + */ +SocketDataPacket *AllocPacket(int size) { - IPAddress *address; - address = NULL; - switch (channel) { - case -1: - /* Return the actual address of the socket */ - address = &socket->address; - break; - default: - /* Return the address of the bound channel */ - if (ValidChannel(channel) && (socket->binding[channel].numbound > 0)) { - address = &socket->binding[channel].address[0]; - } - break; + SocketDataPacket *packet; + int error; + + error = 1; + packet = (SocketDataPacket *) malloc(sizeof(*packet)); + if (packet != NULL) + { + packet->maxlen = size; + packet->data = (uint8_t *) malloc(size); + if (packet->data != NULL) + { + error = 0; + } + } + if (error) + { + FreePacket(packet); + packet = NULL; + } + return (packet); +} + +int ResizePacket(SocketDataPacket *packet, int newsize) +{ + uint8_t *newdata; + + newdata = (uint8_t *) malloc(newsize); + if (newdata != NULL) + { + free(packet->data); + packet->data = newdata; + packet->maxlen = newsize; + } + return (packet->maxlen); +} + +void FreePacket(SocketDataPacket *packet) +{ + if (packet) + { + free(packet->data); + free(packet); + } +} + +/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets, + each 'size' bytes long. + A pointer to the packet array is returned, or NULL if the function ran out + of memory. + */ +SocketDataPacket **AllocPacketList(int howmany, int size) +{ + SocketDataPacket **packetV; + + packetV = (SocketDataPacket **) malloc((howmany + 1) * sizeof(*packetV)); + if (packetV != NULL) + { + int i; + for (i = 0; i < howmany; ++i) + { + packetV[i] = AllocPacket(size); + if (packetV[i] == NULL) + { + break; + } + } + packetV[i] = NULL; + + if (i != howmany) + { + FreePacketList(packetV); + packetV = NULL; + } + } + return (packetV); +} + +void FreePacketList(SocketDataPacket **packetV) +{ + if (packetV) + { + int i; + for (i = 0; packetV[i]; ++i) + { + FreePacket(packetV[i]); + } + free(packetV); } - return (address); } // Send 'len' bytes of 'data' over the non-server socket 'sock' @@ -1125,18 +1406,23 @@ int SocketSend(Socket *sock, const void *datap, int length) const unsigned char *data = (const unsigned char *) datap; // Server sockets are for accepting connections only - if (sock->isServer) { + if (sock->isServer) + { TraceLog(LOG_WARNING, "Cannot send information on a server socket"); return -1; } // Which socket are we trying to send data on - switch (sock->type) { - case SOCKET_TCP: { + switch (sock->type) + { + case SOCKET_TCP: + { SocketSetLastError(0); - do { + do + { length = send(sock->channel, (const char *) data, left, 0); - if (length > 0) { + if (length > 0) + { sent += length; left -= length; data += length; @@ -1146,39 +1432,51 @@ int SocketSend(Socket *sock, const void *datap, int length) (SocketGetLastError() == WSAEINTR)) // The socket was interupted ); - if (length == SOCKET_ERROR) { + if (length == SOCKET_ERROR) + { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status)); SocketSetLastError(0); - } else { + } + else + { TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, sent); } return sent; - } break; - case SOCKET_UDP: { + } + break; + case SOCKET_UDP: + { SocketSetLastError(0); - if (sock->isIPv6) { + if (sock->isIPv6) + { status = sendto(sock->channel, (const char *) data, left, 0, (struct sockaddr *) &sock->addripv6->address, sizeof(sock->addripv6->address)); - } else { + } + else + { status = sendto(sock->channel, (const char *) data, left, 0, (struct sockaddr *) &sock->addripv4->address, sizeof(sock->addripv4->address)); } - if (sent >= 0) { + if (sent >= 0) + { sock->status = 0; ++numsent; TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, status); - } else { + } + else + { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status)); SocketSetLastError(0); return 0; } return numsent; - } break; + } + break; default: break; } return -1; @@ -1199,7 +1497,8 @@ int SocketReceive(Socket *sock, void *data, int maxlen) char ip[INET6_ADDRSTRLEN]; // Server sockets are for accepting connections only - if (sock->isServer && sock->type == SOCKET_TCP) { + if (sock->isServer && sock->type == SOCKET_TCP) + { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", "Server sockets cannot be used to receive data"); @@ -1208,16 +1507,21 @@ int SocketReceive(Socket *sock, void *data, int maxlen) } // Which socket are we trying to send data on - switch (sock->type) { - case SOCKET_TCP: { + switch (sock->type) + { + case SOCKET_TCP: + { SocketSetLastError(0); - do { + do + { len = recv(sock->channel, (char *) data, maxlen, 0); } while (SocketGetLastError() == WSAEINTR); - if (len > 0) { + if (len > 0) + { // Who sent the packet? - if (sock->type == SOCKET_UDP) { + if (sock->type == SOCKET_UDP) + { TraceLog( LOG_DEBUG, "Received data from: %s", inet_ntop(sock_addr.ss_family, GetSocketAddressPtr((struct sockaddr *) &sock_addr), ip, sizeof(ip))); } @@ -1226,8 +1530,10 @@ int SocketReceive(Socket *sock, void *data, int maxlen) } sock->ready = 0; return len; - } break; - case SOCKET_UDP: { + } + break; + case SOCKET_UDP: + { SocketSetLastError(0); sock_len = sizeof(sock_addr); status = recvfrom(sock->channel, // The receving channel @@ -1237,15 +1543,19 @@ int SocketReceive(Socket *sock, void *data, int maxlen) (struct sockaddr *) &sock_addr, // The address of the recevied data &sock_len // The length of the received data address ); - if (status >= 0) { + if (status >= 0) + { ++numrecv; - } else { + } + else + { sock->status = SocketGetLastError(); - switch (sock->status) { - case WSAEWOULDBLOCK: { - break; + switch (sock->status) + { + case WSAEWOULDBLOCK: { break; } - default: { + default: + { TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); break; } @@ -1255,8 +1565,8 @@ int SocketReceive(Socket *sock, void *data, int maxlen) } sock->ready = 0; return numrecv; - - } break; + } + break; } return -1; } @@ -1267,26 +1577,6 @@ bool IsSocketReady(Socket *sock) return (sock != NULL) && (sock->ready); } -// Returns true if a socket is has data available for reading right now -bool SocketReady(Socket *sock) -{ - int retval = 0; - struct timeval tv; - fd_set mask; - - // Check the file descriptors for available data - do { - SocketSetLastError(0); - FD_ZERO(&mask); - FD_SET(sock->channel, &mask); - tv.tv_sec = 0; - tv.tv_usec = 0; - retval = select(sock->channel + 1, &mask, NULL, NULL, &tv); - } while (SocketGetLastError() == WSAEINTR); - - return (retval == 1); -} - // Check if the socket is considered connected bool IsSocketConnected(Socket *sock) { @@ -1298,14 +1588,20 @@ bool IsSocketConnected(Socket *sock) timeout.tv_sec = 1; timeout.tv_usec = 1000000000UL; int total = select(0, NULL, &writefds, NULL, &timeout); - if (total == -1) { // Error + if (total == -1) + { // Error sock->status = SocketGetLastError(); TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); SocketSetLastError(0); - } else if (total == 0) { // Timeout + } + else if (total == 0) + { // Timeout return false; - } else { - if (FD_ISSET(sock->channel, &writefds)) { + } + else + { + if (FD_ISSET(sock->channel, &writefds)) + { return true; } } @@ -1320,9 +1616,11 @@ SocketResult *AllocSocketResult() { struct SocketResult *res; res = (struct SocketResult *) malloc(sizeof(*res)); - if (res != NULL) { + if (res != NULL) + { memset(res, 0, sizeof(*res)); - if ((res->socket = AllocSocket()) == NULL) { + if ((res->socket = AllocSocket()) == NULL) + { free(res); res = NULL; } @@ -1333,8 +1631,10 @@ SocketResult *AllocSocketResult() // Free an allocated SocketResult void FreeSocketResult(SocketResult **result) { - if (*result != NULL) { - if ((*result)->socket != NULL) { + if (*result != NULL) + { + if ((*result)->socket != NULL) + { FreeSocket(&((*result)->socket)); } free(*result); @@ -1348,9 +1648,12 @@ Socket *AllocSocket() // Allocate a socket if one already hasn't been struct Socket *sock; sock = (Socket *) malloc(sizeof(*sock)); - if (sock != NULL) { + if (sock != NULL) + { memset(sock, 0, sizeof(*sock)); - } else { + } + else + { TraceLog( LOG_WARNING, "Ran out of memory attempting to allocate a socket"); SocketClose(sock); @@ -1363,7 +1666,8 @@ Socket *AllocSocket() // Free an allocated Socket void FreeSocket(Socket **sock) { - if (*sock != NULL) { + if (*sock != NULL) + { free(*sock); *sock = NULL; } @@ -1376,15 +1680,20 @@ SocketSet *AllocSocketSet(int max) int i; set = (struct SocketSet *) malloc(sizeof(*set)); - if (set != NULL) { + if (set != NULL) + { set->numsockets = 0; set->maxsockets = max; set->sockets = (struct Socket **) malloc(max * sizeof(*set->sockets)); - if (set->sockets != NULL) { - for (i = 0; i < max; ++i) { + if (set->sockets != NULL) + { + for (i = 0; i < max; ++i) + { set->sockets[i] = NULL; } - } else { + } + else + { free(set); set = NULL; } @@ -1395,7 +1704,8 @@ SocketSet *AllocSocketSet(int max) // Free an allocated SocketSet void FreeSocketSet(SocketSet *set) { - if (set) { + if (set) + { free(set->sockets); free(set); } @@ -1404,14 +1714,18 @@ void FreeSocketSet(SocketSet *set) // Add a Socket "sock" to the SocketSet "set" int AddSocket(SocketSet *set, Socket *sock) { - if (sock != NULL) { - if (set->numsockets == set->maxsockets) { + if (sock != NULL) + { + if (set->numsockets == set->maxsockets) + { TraceLog(LOG_DEBUG, "Socket Error: %s", "SocketSet is full"); SocketSetLastError(0); return (-1); } set->sockets[set->numsockets++] = (struct Socket *) sock; - } else { + } + else + { TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket was null"); SocketSetLastError(0); return (-1); @@ -1424,19 +1738,24 @@ int RemoveSocket(SocketSet *set, Socket *sock) { int i; - if (sock != NULL) { - for (i = 0; i < set->numsockets; ++i) { - if (set->sockets[i] == (struct Socket *) sock) { + if (sock != NULL) + { + for (i = 0; i < set->numsockets; ++i) + { + if (set->sockets[i] == (struct Socket *) sock) + { break; } } - if (i == set->numsockets) { + if (i == set->numsockets) + { TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket not found"); SocketSetLastError(0); return (-1); } --set->numsockets; - for (; i < set->numsockets; ++i) { + for (; i < set->numsockets; ++i) + { set->sockets[i] = set->sockets[i + 1]; } } @@ -1454,19 +1773,23 @@ int CheckSockets(SocketSet *set, unsigned int timeout) /* Find the largest file descriptor */ maxfd = 0; - for (i = set->numsockets - 1; i >= 0; --i) { - if (set->sockets[i]->channel > maxfd) { + for (i = set->numsockets - 1; i >= 0; --i) + { + if (set->sockets[i]->channel > maxfd) + { maxfd = set->sockets[i]->channel; } } // Check the file descriptors for available data - do { + do + { SocketSetLastError(0); // Set up the mask of file descriptors FD_ZERO(&mask); - for (i = set->numsockets - 1; i >= 0; --i) { + for (i = set->numsockets - 1; i >= 0; --i) + { FD_SET(set->sockets[i]->channel, &mask); } // Set up the timeout tv.tv_sec = timeout / 1000; @@ -1477,9 +1800,12 @@ int CheckSockets(SocketSet *set, unsigned int timeout) } while (SocketGetLastError() == WSAEINTR); // Mark all file descriptors ready that have data available - if (retval > 0) { - for (i = set->numsockets - 1; i >= 0; --i) { - if (FD_ISSET(set->sockets[i]->channel, &mask)) { + if (retval > 0) + { + for (i = set->numsockets - 1; i >= 0; --i) + { + if (FD_ISSET(set->sockets[i]->channel, &mask)) + { set->sockets[i]->ready = 1; } } @@ -1487,54 +1813,64 @@ int CheckSockets(SocketSet *set, unsigned int timeout) return (retval); } -// Allocate a Packet -Packet *AllocPacket(int size) -{ - struct Packet *packet; - packet = (struct Packet *) malloc(sizeof(*packet)); - if (packet != NULL) { - memset(packet, 0, sizeof(*packet)); - packet->size = 0; - packet->offs = 0; - packet->maxs = size; - packet->data = (uint8_t *) malloc(size * sizeof(uint8_t)); - memset(packet->data, '\0', size); - if (packet->data == NULL) { - free(packet); - packet = NULL; - } - } else { - free(packet); - packet = NULL; - } - return packet; -} +// Allocate a Packet +// Packet *AllocPacket(int size) +// { +// struct Packet *packet; +// packet = (struct Packet *) malloc(sizeof(*packet)); +// if (packet != NULL) +// { +// memset(packet, 0, sizeof(*packet)); +// packet->size = 0; +// packet->offs = 0; +// packet->maxs = size; +// packet->data = (uint8_t *) malloc(size * sizeof(uint8_t)); +// memset(packet->data, '\0', size); +// if (packet->data == NULL) +// { +// free(packet); +// packet = NULL; +// } +// } +// else +// { +// free(packet); +// packet = NULL; +// } +// return packet; +// } // Free an allocated Packet -void FreePacket(Packet *packet) -{ - if (packet != NULL) { - if (packet->data != NULL) { - free(packet->data); - packet->data = NULL; - } - free(packet); - packet = NULL; - } -} +// void FreePacket(Packet *packet) +// { +// if (packet != NULL) +// { +// if (packet->data != NULL) +// { +// free(packet->data); +// packet->data = NULL; +// } +// free(packet); +// packet = NULL; +// } +// } // Allocate an AddressInformation AddressInformation AllocAddress() { AddressInformation addressInfo = NULL; addressInfo = (AddressInformation) calloc(1, sizeof(*addressInfo)); - if (addressInfo != NULL) { + if (addressInfo != NULL) + { addressInfo->addr.ai_addr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr)); - if (addressInfo->addr.ai_addr == NULL) { + if (addressInfo->addr.ai_addr == NULL) + { TraceLog(LOG_WARNING, "Failed to allocate memory for \"struct sockaddr\""); } - } else { + } + else + { TraceLog(LOG_WARNING, "Failed to allocate memory for \"struct AddressInformation\""); } @@ -1544,8 +1880,10 @@ AddressInformation AllocAddress() // Free an AddressInformation struct void FreeAddress(AddressInformation *addressInfo) { - if (*addressInfo != NULL) { - if ((*addressInfo)->addr.ai_addr != NULL) { + if (*addressInfo != NULL) + { + if ((*addressInfo)->addr.ai_addr != NULL) + { free((*addressInfo)->addr.ai_addr); (*addressInfo)->addr.ai_addr = NULL; } @@ -1592,22 +1930,30 @@ char *GetAddressHostAndPort(AddressInformation address, char *outhost, int *outp char * ip[INET6_ADDRSTRLEN]; char * result = NULL; struct sockaddr_storage *storage = (struct sockaddr_storage *) address->addr.ai_addr; - switch (storage->ss_family) { - case AF_INET: { + switch (storage->ss_family) + { + case AF_INET: + { struct sockaddr_in *s = ((struct sockaddr_in *) address->addr.ai_addr); result = inet_ntop(AF_INET, &s->sin_addr, ip, INET_ADDRSTRLEN); *outport = ntohs(s->sin_port); - } break; - case AF_INET6: { + } + break; + case AF_INET6: + { struct sockaddr_in6 *s = ((struct sockaddr_in6 *) address->addr.ai_addr); result = inet_ntop(AF_INET6, &s->sin6_addr, ip, INET6_ADDRSTRLEN); *outport = ntohs(s->sin6_port); - } break; + } + break; } - if (result == NULL) { + if (result == NULL) + { TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(SocketGetLastError())); SocketSetLastError(0); - } else { + } + else + { strcpy(outhost, result); } return result;