diff --git a/src/rnet.c b/src/rnet.c index 79a6f07f9..55d4a26ac 100644 --- a/src/rnet.c +++ b/src/rnet.c @@ -59,27 +59,27 @@ typedef struct _SocketAddress { - struct sockaddr address; + struct sockaddr address; } _SocketAddress; typedef struct _SocketAddressIPv4 { - struct sockaddr_in address; + struct sockaddr_in address; } _SocketAddressIPv4; typedef struct _SocketAddressIPv6 { - struct sockaddr_in6 address; + struct sockaddr_in6 address; } _SocketAddressIPv6; typedef struct _SocketAddressStorage { - struct sockaddr_storage address; + struct sockaddr_storage address; } _SocketAddressStorage; typedef struct _AddressInformation { - struct addrinfo addr; + struct addrinfo addr; } _AddressInformation; @@ -88,24 +88,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 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 *sock, struct addrinfo *addr); -static bool CreateSocket(SocketConfig *config, SocketResult *outresult); -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 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 *sock, struct addrinfo *addr); +static bool CreateSocket(SocketConfig *config, SocketResult *outresult); +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); //---------------------------------------------------------------------------------- // Global module implementation @@ -114,140 +114,146 @@ static void SocketSetHints(SocketConfig *config, struct addrinfo *hints); // 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: - { - TraceLog(LOG_DEBUG, "\tFamily: AF_INET (IPv4)"); - TraceLog(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr)); - } - break; - case AF_INET6: - { - TraceLog(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)"); - TraceLog(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr)); - } - break; - case AF_NETBIOS: - { - TraceLog(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)"); - } - break; - default: { TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family); - } - break; - } - TraceLog(LOG_DEBUG, "\tSocket type:"); - switch (socktype) - { - case 0: TraceLog(LOG_DEBUG, "\t- Unspecified"); break; - case SOCK_STREAM: - TraceLog(LOG_DEBUG, "\t- SOCK_STREAM (stream)"); - break; - case SOCK_DGRAM: - TraceLog(LOG_DEBUG, "\t- SOCK_DGRAM (datagram)"); - break; - case SOCK_RAW: TraceLog(LOG_DEBUG, "\t- SOCK_RAW (raw)"); break; - case SOCK_RDM: - TraceLog(LOG_DEBUG, "\t- SOCK_RDM (reliable message datagram)"); - break; - case SOCK_SEQPACKET: - TraceLog(LOG_DEBUG, "\t- SOCK_SEQPACKET (pseudo-stream packet)"); - break; - default: TraceLog(LOG_DEBUG, "\t- Other %ld", socktype); break; - } - TraceLog(LOG_DEBUG, "\tProtocol:"); - 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; - default: TraceLog(LOG_DEBUG, "\t- Other %ld", protocol); break; - } + 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: + { + TraceLog(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)"); + TraceLog(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr)); + } + break; + case AF_NETBIOS: + { + TraceLog(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)"); + } + break; + default: { TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family); + } + break; + } + TraceLog(LOG_DEBUG, "\tSocket type:"); + switch (socktype) + { + case 0: TraceLog(LOG_DEBUG, "\t- Unspecified"); break; + case SOCK_STREAM: + TraceLog(LOG_DEBUG, "\t- SOCK_STREAM (stream)"); + break; + case SOCK_DGRAM: + TraceLog(LOG_DEBUG, "\t- SOCK_DGRAM (datagram)"); + break; + case SOCK_RAW: TraceLog(LOG_DEBUG, "\t- SOCK_RAW (raw)"); break; + case SOCK_RDM: + TraceLog(LOG_DEBUG, "\t- SOCK_RDM (reliable message datagram)"); + break; + case SOCK_SEQPACKET: + TraceLog(LOG_DEBUG, "\t- SOCK_SEQPACKET (pseudo-stream packet)"); + break; + default: TraceLog(LOG_DEBUG, "\t- Other %ld", socktype); break; + } + TraceLog(LOG_DEBUG, "\tProtocol:"); + 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; + default: TraceLog(LOG_DEBUG, "\t- Other %ld", protocol); break; + } } // Convert network ordered socket address to human readable string (127.0.0.1) static const char *SocketAddressToString(struct sockaddr_storage *sockaddr) { - static const char* ipv6[INET6_ADDRSTRLEN]; - assert(sockaddr != NULL); - assert(sockaddr->ss_family == AF_INET || sockaddr->ss_family == AF_INET6); - 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: - { - struct sockaddr_in6 *s = ((struct sockaddr_in6 *) sockaddr); - return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN); - } - break; - } - return NULL; + //static const char* ipv6[INET6_ADDRSTRLEN]; + assert(sockaddr != NULL); + assert(sockaddr->ss_family == AF_INET || sockaddr->ss_family == AF_INET6); + 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); // TODO. + } + break; + case AF_INET6: + { + //struct sockaddr_in6 *s = ((struct sockaddr_in6 *) sockaddr); + //return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN); // TODO. + } + break; + } + return NULL; } // Check if the null terminated string ip is a valid IPv4 address static bool IsIPv4Address(const char *ip) { - struct sockaddr_in sa; - int result = inet_pton(AF_INET, ip, &(sa.sin_addr)); - return result != 0; + /* + struct sockaddr_in sa; + int result = inet_pton(AF_INET, ip, &(sa.sin_addr)); // TODO. + return (result != 0); + */ + return false; } // Check if the null terminated string ip is a valid IPv6 address static bool IsIPv6Address(const char *ip) { - struct sockaddr_in6 sa; - int result = inet_pton(AF_INET6, ip, &(sa.sin6_addr)); - return result != 0; + /* + struct sockaddr_in6 sa; + int result = inet_pton(AF_INET6, ip, &(sa.sin6_addr)); // TODO. + return result != 0; + */ + return false; } // Return a pointer to the port from the correct address family (IPv4, or IPv6) static void *GetSocketPortPtr(struct sockaddr_storage *sa) { - if (sa->ss_family == AF_INET) - { - return &(((struct sockaddr_in *) sa)->sin_port); - } + if (sa->ss_family == AF_INET) + { + return &(((struct sockaddr_in *) sa)->sin_port); + } - return &(((struct sockaddr_in6 *) sa)->sin6_port); + return &(((struct sockaddr_in6 *) sa)->sin6_port); } // Return a pointer to the address from the correct address family (IPv4, or IPv6) static void *GetSocketAddressPtr(struct sockaddr_storage *sa) { - if (sa->ss_family == AF_INET) - { - return &(((struct sockaddr_in *) sa)->sin_addr); - } + if (sa->ss_family == AF_INET) + { + return &(((struct sockaddr_in *) sa)->sin_addr); + } - return &(((struct sockaddr_in6 *) sa)->sin6_addr); + return &(((struct sockaddr_in6 *) sa)->sin6_addr); } // Is the socket in a valid state? static bool IsSocketValid(Socket *sock) { - if (sock != NULL) - { - return (sock->channel != INVALID_SOCKET); - } - return false; + if (sock != NULL) + { + return (sock->channel != INVALID_SOCKET); + } + return false; } // Sets the error code that can be retrieved through the WSAGetLastError function. static void SocketSetLastError(int err) { #if defined(_WIN32) - WSASetLastError(err); + WSASetLastError(err); #else - errno = err; + errno = err; #endif } @@ -255,1059 +261,1055 @@ static void SocketSetLastError(int err) static int SocketGetLastError() { #if defined(_WIN32) - return WSAGetLastError(); + return WSAGetLastError(); #else - return errno; + return errno; #endif } // Returns a human-readable string representing the last error message static char *SocketGetLastErrorString() { - return SocketErrorCodeToString(SocketGetLastError()); + return SocketErrorCodeToString(SocketGetLastError()); } // Returns a human-readable string representing the error message (err) static char *SocketErrorCodeToString(int err) { #if defined(_WIN32) - static char gaiStrErrorBuffer[GAI_STRERROR_BUFFER_SIZE]; - sprintf(gaiStrErrorBuffer, "%s", gai_strerror(err)); - return gaiStrErrorBuffer; + static char gaiStrErrorBuffer[GAI_STRERROR_BUFFER_SIZE]; + sprintf(gaiStrErrorBuffer, "%s", gai_strerror(err)); + return gaiStrErrorBuffer; #else - return gai_strerror(err); + return gai_strerror(err); #endif } // Set the defaults in the supplied SocketConfig if they're not already set static bool SocketSetDefaults(SocketConfig *config) { - if (config->backlog_size == 0) - { - config->backlog_size = SOCKET_MAX_QUEUE_SIZE; - } + if (config->backlog_size == 0) + { + config->backlog_size = SOCKET_MAX_QUEUE_SIZE; + } - return true; + return true; } // Create the socket channel static bool InitSocket(Socket *sock, struct addrinfo *addr) { - switch (sock->type) - { - case SOCKET_TCP: - if (addr->ai_family == AF_INET) - { - sock->channel = socket(AF_INET, SOCK_STREAM, 0); - } - else - { - sock->channel = socket(AF_INET6, SOCK_STREAM, 0); - } - break; - case SOCKET_UDP: - if (addr->ai_family == AF_INET) - { - sock->channel = socket(AF_INET, SOCK_DGRAM, 0); - } - else - { - sock->channel = socket(AF_INET6, SOCK_DGRAM, 0); - } - break; - default: - TraceLog(LOG_WARNING, "Invalid socket type specified."); - break; - } - return IsSocketValid(sock); + switch (sock->type) + { + case SOCKET_TCP: + if (addr->ai_family == AF_INET) + { + sock->channel = socket(AF_INET, SOCK_STREAM, 0); + } + else + { + sock->channel = socket(AF_INET6, SOCK_STREAM, 0); + } + break; + case SOCKET_UDP: + if (addr->ai_family == AF_INET) + { + sock->channel = socket(AF_INET, SOCK_DGRAM, 0); + } + else + { + sock->channel = socket(AF_INET6, SOCK_DGRAM, 0); + } + break; + default: + TraceLog(LOG_WARNING, "Invalid socket type specified."); + break; + } + return IsSocketValid(sock); } -// CreateSocket() - Interally called by CreateSocket() +// CreateSocket() - Interally called by CreateSocket() // -// This here is the bread and butter of the socket API, This function will -// attempt to open a socket, bind and listen to it based on the config passed in +// This here is the bread and butter of the socket API, This function will +// attempt to open a socket, bind and listen to it based on the config passed in // -// SocketConfig* config - Configuration for which socket to open -// SocketResult* result - The results of this function (if any, including errors) +// SocketConfig* config - Configuration for which socket to open +// SocketResult* result - The results of this function (if any, including errors) // -// e.g. -// SocketConfig server_config = { SocketConfig client_config = { -// .host = "127.0.0.1", .host = "127.0.0.1", -// .port = 8080, .port = 8080, -// .server = true, }; -// .nonblocking = true, -// }; -// SocketResult server_res; SocketResult client_res; +// e.g. +// SocketConfig server_config = { SocketConfig client_config = { +// .host = "127.0.0.1", .host = "127.0.0.1", +// .port = 8080, .port = 8080, +// .server = true, }; +// .nonblocking = true, +// }; +// SocketResult server_res; SocketResult client_res; static bool CreateSocket(SocketConfig *config, SocketResult *outresult) { - bool success = true; - int addrstatus; - struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) - struct addrinfo *res; // A pointer to the resulting address list - outresult->socket->channel = INVALID_SOCKET; - outresult->status = RESULT_FAILURE; + bool success = true; + int addrstatus; + struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) + struct addrinfo *res; // A pointer to the resulting address list + outresult->socket->channel = INVALID_SOCKET; + outresult->status = RESULT_FAILURE; - // Set the socket type - outresult->socket->type = config->type; + // Set the socket type + outresult->socket->type = config->type; - // Set the hints based on information in the config - // - // AI_CANONNAME Causes the ai_canonname of the result to the filled out with the host's canonical (real) name. - // AI_PASSIVE: Causes the result's IP address to be filled out with INADDR_ANY (IPv4)or in6addr_any (IPv6); - // Note: This causes a subsequent call to bind() to auto-fill the IP address - // of the struct sockaddr with the address of the current host. - // - SocketSetHints(config, &hints); + // Set the hints based on information in the config + // + // AI_CANONNAME Causes the ai_canonname of the result to the filled out with the host's canonical (real) name. + // AI_PASSIVE: Causes the result's IP address to be filled out with INADDR_ANY (IPv4)or in6addr_any (IPv6); + // Note: This causes a subsequent call to bind() to auto-fill the IP address + // of the struct sockaddr with the address of the current host. + // + SocketSetHints(config, &hints); - // Populate address information - addrstatus = getaddrinfo(config->host, // e.g. "www.example.com" or IP (Can be null if AI_PASSIVE flag is set - config->port, // e.g. "http" or port number - &hints, // e.g. SOCK_STREAM/SOCK_DGRAM - &res // The struct to populate - ); + // Populate address information + addrstatus = getaddrinfo(config->host, // e.g. "www.example.com" or IP (Can be null if AI_PASSIVE flag is set + config->port, // e.g. "http" or port number + &hints, // e.g. SOCK_STREAM/SOCK_DGRAM + &res // The struct to populate + ); - // Did we succeed? - if (addrstatus != 0) - { - outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_WARNING, - "Socket Error: %s", - SocketErrorCodeToString(outresult->socket->status)); - SocketSetLastError(0); - TraceLog(LOG_WARNING, - "Failed to get resolve host %s:%s: %s", - config->host, - config->port, - SocketGetLastErrorString()); - return (success = false); - } - else - { - char hoststr[NI_MAXHOST]; - char portstr[NI_MAXSERV]; - socklen_t client_len = sizeof(struct sockaddr_storage); - int rc = getnameinfo((struct sockaddr *) res->ai_addr, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); - TraceLog(LOG_INFO, "Successfully resolved host %s:%s", hoststr, portstr); - } + // Did we succeed? + if (addrstatus != 0) + { + outresult->socket->status = SocketGetLastError(); + TraceLog(LOG_WARNING, + "Socket Error: %s", + SocketErrorCodeToString(outresult->socket->status)); + SocketSetLastError(0); + TraceLog(LOG_WARNING, + "Failed to get resolve host %s:%s: %s", + config->host, + config->port, + SocketGetLastErrorString()); + return (success = false); + } + else + { + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + //socklen_t client_len = sizeof(struct sockaddr_storage); + //int rc = getnameinfo((struct sockaddr *) res->ai_addr, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + TraceLog(LOG_INFO, "Successfully resolved host %s:%s", hoststr, portstr); + } - // Walk the address information linked-list - struct addrinfo *it; - for (it = res; it != NULL; it = it->ai_next) - { - // Initialise the socket - if (!InitSocket(outresult->socket, it)) - { - outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_WARNING, - "Socket Error: %s", - SocketErrorCodeToString(outresult->socket->status)); - SocketSetLastError(0); - continue; - } + // Walk the address information linked-list + struct addrinfo *it; + for (it = res; it != NULL; it = it->ai_next) + { + // Initialise the socket + if (!InitSocket(outresult->socket, it)) + { + outresult->socket->status = SocketGetLastError(); + TraceLog(LOG_WARNING, + "Socket Error: %s", + SocketErrorCodeToString(outresult->socket->status)); + SocketSetLastError(0); + continue; + } - // Set socket options - if (!SocketSetOptions(config, outresult->socket)) - { - outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_WARNING, - "Socket Error: %s", - SocketErrorCodeToString(outresult->socket->status)); - SocketSetLastError(0); - freeaddrinfo(res); - return (success = false); - } - } + // Set socket options + if (!SocketSetOptions(config, outresult->socket)) + { + outresult->socket->status = SocketGetLastError(); + TraceLog(LOG_WARNING, + "Socket Error: %s", + SocketErrorCodeToString(outresult->socket->status)); + SocketSetLastError(0); + freeaddrinfo(res); + return (success = false); + } + } - if (!IsSocketValid(outresult->socket)) - { - outresult->socket->status = SocketGetLastError(); - TraceLog( - LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->status)); - SocketSetLastError(0); - freeaddrinfo(res); - return (success = false); - } + if (!IsSocketValid(outresult->socket)) + { + outresult->socket->status = SocketGetLastError(); + TraceLog( + LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->status)); + SocketSetLastError(0); + freeaddrinfo(res); + return (success = false); + } - if (success) - { - outresult->status = RESULT_SUCCESS; - outresult->socket->ready = 0; - outresult->socket->status = 0; - if (!(config->type == SOCKET_UDP)) - { - outresult->socket->isServer = config->server; - } - switch (res->ai_addr->sa_family) - { - case AF_INET: - { - outresult->socket->addripv4 = (struct _SocketAddressIPv4 *) malloc( - sizeof(*outresult->socket->addripv4)); - if (outresult->socket->addripv4 != NULL) - { - memset(outresult->socket->addripv4, 0, - sizeof(*outresult->socket->addripv4)); - if (outresult->socket->addripv4 != NULL) - { - memcpy(&outresult->socket->addripv4->address, - (struct sockaddr_in *) res->ai_addr, sizeof(struct sockaddr_in)); - outresult->socket->isIPv6 = false; - char hoststr[NI_MAXHOST]; - char portstr[NI_MAXSERV]; - socklen_t client_len = sizeof(struct sockaddr_storage); - getnameinfo( - (struct sockaddr *) &outresult->socket->addripv4->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); - TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); - } - } - } - break; - case AF_INET6: - { - outresult->socket->addripv6 = (struct _SocketAddressIPv6 *) malloc( - sizeof(*outresult->socket->addripv6)); - if (outresult->socket->addripv6 != NULL) - { - memset(outresult->socket->addripv6, 0, - sizeof(*outresult->socket->addripv6)); - if (outresult->socket->addripv6 != NULL) - { - memcpy(&outresult->socket->addripv6->address, - (struct sockaddr_in6 *) res->ai_addr, sizeof(struct sockaddr_in6)); - outresult->socket->isIPv6 = true; - char hoststr[NI_MAXHOST]; - char portstr[NI_MAXSERV]; - socklen_t client_len = sizeof(struct sockaddr_storage); - getnameinfo( - (struct sockaddr *) &outresult->socket->addripv6->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); - TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); - } - } - } - break; - } - } - freeaddrinfo(res); - return success; + if (success) + { + outresult->status = RESULT_SUCCESS; + outresult->socket->ready = 0; + outresult->socket->status = 0; + if (!(config->type == SOCKET_UDP)) + { + outresult->socket->isServer = config->server; + } + switch (res->ai_addr->sa_family) + { + case AF_INET: + { + outresult->socket->addripv4 = (struct _SocketAddressIPv4 *) malloc( + sizeof(*outresult->socket->addripv4)); + if (outresult->socket->addripv4 != NULL) + { + memset(outresult->socket->addripv4, 0, + sizeof(*outresult->socket->addripv4)); + if (outresult->socket->addripv4 != NULL) + { + memcpy(&outresult->socket->addripv4->address, + (struct sockaddr_in *) res->ai_addr, sizeof(struct sockaddr_in)); + outresult->socket->isIPv6 = false; + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + socklen_t client_len = sizeof(struct sockaddr_storage); + getnameinfo( + (struct sockaddr *) &outresult->socket->addripv4->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); + } + } + } + break; + case AF_INET6: + { + outresult->socket->addripv6 = (struct _SocketAddressIPv6 *) malloc( + sizeof(*outresult->socket->addripv6)); + if (outresult->socket->addripv6 != NULL) + { + memset(outresult->socket->addripv6, 0, + sizeof(*outresult->socket->addripv6)); + if (outresult->socket->addripv6 != NULL) + { + memcpy(&outresult->socket->addripv6->address, + (struct sockaddr_in6 *) res->ai_addr, sizeof(struct sockaddr_in6)); + outresult->socket->isIPv6 = true; + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + socklen_t client_len = sizeof(struct sockaddr_storage); + getnameinfo( + (struct sockaddr *) &outresult->socket->addripv6->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); + } + } + } + break; + } + } + freeaddrinfo(res); + return success; } // Set the state of the Socket sock to blocking static bool SocketSetBlocking(Socket *sock) { - bool ret = true; + bool ret = true; #if defined(_WIN32) - unsigned long mode = 0; - ret = ioctlsocket(sock->channel, FIONBIO, &mode); + unsigned long mode = 0; + ret = ioctlsocket(sock->channel, FIONBIO, &mode); #else - const int flags = fcntl(sock->channel, F_GETFL, 0); - if (!(flags & O_NONBLOCK)) - { - TraceLog(LOG_DEBUG, "Socket was already in blocking mode"); - return ret; - } + const int flags = fcntl(sock->channel, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) + { + TraceLog(LOG_DEBUG, "Socket was already in blocking mode"); + return ret; + } - ret = (0 == fcntl(sock->channel, F_SETFL, (flags ^ O_NONBLOCK))); + ret = (0 == fcntl(sock->channel, F_SETFL, (flags ^ O_NONBLOCK))); #endif - return ret; + return ret; } // Set the state of the Socket sock to non-blocking static bool SocketSetNonBlocking(Socket *sock) { - bool ret = true; + bool ret = true; #if defined(_WIN32) - unsigned long mode = 1; - ret = ioctlsocket(sock->channel, FIONBIO, &mode); + unsigned long mode = 1; + ret = ioctlsocket(sock->channel, FIONBIO, &mode); #else - const int flags = fcntl(sock->channel, F_GETFL, 0); - if ((flags & O_NONBLOCK)) - { - TraceLog(LOG_DEBUG, "Socket was already in non-blocking mode"); - return ret; - } - ret = (0 == fcntl(sock->channel, F_SETFL, (flags | O_NONBLOCK))); + const int flags = fcntl(sock->channel, F_GETFL, 0); + if ((flags & O_NONBLOCK)) + { + TraceLog(LOG_DEBUG, "Socket was already in non-blocking mode"); + return ret; + } + ret = (0 == fcntl(sock->channel, F_SETFL, (flags | O_NONBLOCK))); #endif - return ret; + return ret; } // 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++) - { - SocketOpt *opt = &config->sockopts[i]; - if (opt->id == 0) - { - break; - } + for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) + { + SocketOpt *opt = &config->sockopts[i]; + if (opt->id == 0) + { + break; + } - if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) - { - return false; - } - } + if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) + { + return false; + } + } - return true; + return true; } // Set "hints" in an addrinfo struct, to be passed to getaddrinfo. static void SocketSetHints(SocketConfig *config, struct addrinfo *hints) { - if (config == NULL || hints == NULL) - { - return; - } - memset(hints, 0, sizeof(*hints)); + 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)) - { - hints->ai_family = AF_INET; - hints->ai_flags |= AI_NUMERICHOST; - } - else - { - if (IsIPv6Address(config->host)) - { - hints->ai_family = AF_INET6; - hints->ai_flags |= AI_NUMERICHOST; - } - else - { - hints->ai_family = AF_UNSPEC; - } - } + // Check if the ip supplied in the config is a valid ipv4 ip ipv6 address + if (IsIPv4Address(config->host)) + { + hints->ai_family = AF_INET; + hints->ai_flags |= AI_NUMERICHOST; + } + else + { + if (IsIPv6Address(config->host)) + { + hints->ai_family = AF_INET6; + hints->ai_flags |= AI_NUMERICHOST; + } + else + { + hints->ai_family = AF_UNSPEC; + } + } - if (config->type == SOCKET_UDP) - { - hints->ai_socktype = SOCK_DGRAM; - } - else - { - hints->ai_socktype = SOCK_STREAM; - } + if (config->type == SOCKET_UDP) + { + hints->ai_socktype = SOCK_DGRAM; + } + else + { + hints->ai_socktype = SOCK_STREAM; + } - // Set passive unless UDP client - if (!(config->type == SOCKET_UDP) || config->server) - { - hints->ai_flags = AI_PASSIVE; - } + // Set passive unless UDP client + if (!(config->type == SOCKET_UDP) || config->server) + { + hints->ai_flags = AI_PASSIVE; + } } //---------------------------------------------------------------------------------- // Module implementation //---------------------------------------------------------------------------------- -// Initialise the network (requires for windows platforms only) +// Initialise the network (requires for windows platforms only) bool InitNetwork() { #if defined(_WIN32) - WORD wVersionRequested; - WSADATA wsaData; - int err; + WORD wVersionRequested; + WSADATA wsaData; + int err; - wVersionRequested = MAKEWORD(2, 2); - err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) - { - TraceLog(LOG_WARNING, "WinSock failed to initialise."); - return false; - } - else - { - TraceLog(LOG_INFO, "WinSock initialised."); - } + wVersionRequested = MAKEWORD(2, 2); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) + { + TraceLog(LOG_WARNING, "WinSock failed to initialise."); + return false; + } + else + { + TraceLog(LOG_INFO, "WinSock initialised."); + } - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) - { - TraceLog(LOG_WARNING, "WinSock failed to initialise."); - WSACleanup(); - return false; - } + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) + { + TraceLog(LOG_WARNING, "WinSock failed to initialise."); + WSACleanup(); + return false; + } - return true; + return true; #else - return true; + return true; #endif } -// Cleanup, and close the network +// Cleanup, and close the network void CloseNetwork() { #if defined(_WIN32) - WSACleanup(); + WSACleanup(); #endif } -// Protocol-independent name resolution from an address to an ANSI host name -// and from a port number to the ANSI service name. +// Protocol-independent name resolution from an address to an ANSI host name +// and from a port number to the ANSI service name. // -// The flags parameter can be used to customize processing of the getnameinfo function +// The flags parameter can be used to customize processing of the getnameinfo function // -// The following flags are available: +// The following flags are available: // -// NAME_INFO_DEFAULT 0x00 // No flags set -// NAME_INFO_NOFQDN 0x01 // Only return nodename portion for local hosts -// NAME_INFO_NUMERICHOST 0x02 // Return numeric form of the host's address -// NAME_INFO_NAMEREQD 0x04 // Error if the host's name not in DNS -// NAME_INFO_NUMERICSERV 0x08 // Return numeric form of the service (port #) -// NAME_INFO_DGRAM 0x10 // Service is a datagram service +// NAME_INFO_DEFAULT 0x00 // No flags set +// NAME_INFO_NOFQDN 0x01 // Only return nodename portion for local hosts +// NAME_INFO_NUMERICHOST 0x02 // Return numeric form of the host's address +// NAME_INFO_NAMEREQD 0x04 // Error if the host's name not in DNS +// NAME_INFO_NUMERICSERV 0x08 // Return numeric form of the service (port #) +// NAME_INFO_DGRAM 0x10 // Service is a datagram service void ResolveIP(const char *ip, const char *port, int flags, char *host, char *serv) { - // Variables - int status; // Status value to return (0) is success - struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) - struct addrinfo *res; // A pointer to the resulting address list + // Variables + int status; // Status value to return (0) is success + struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) + struct addrinfo *res; // A pointer to the resulting address list - // Set the hints - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6) - hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP) + // Set the hints + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6) + hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP) - // Populate address information - status = getaddrinfo(ip, // e.g. "www.example.com" or IP - port, // e.g. "http" or port number - &hints, // e.g. SOCK_STREAM/SOCK_DGRAM - &res // The struct to populate - ); + // Populate address information + status = getaddrinfo(ip, // e.g. "www.example.com" or IP + port, // e.g. "http" or port number + &hints, // e.g. SOCK_STREAM/SOCK_DGRAM + &res // The struct to populate + ); - // Did we succeed? - if (status != 0) - { - TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", ip, port, gai_strerror(errno)); - } - else - { - TraceLog(LOG_DEBUG, "Resolving... %s::%s", ip, port); - } + // Did we succeed? + if (status != 0) + { + TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", ip, port, gai_strerror(errno)); + } + else + { + TraceLog(LOG_DEBUG, "Resolving... %s::%s", ip, port); + } - // Attempt to resolve network byte order ip to hostname - switch (res->ai_family) - { - case AF_INET: - status = getnameinfo(&*((struct sockaddr *) res->ai_addr), - sizeof(*((struct sockaddr_in *) res->ai_addr)), - host, - NI_MAXHOST, - serv, - NI_MAXSERV, - flags); - break; - case AF_INET6: - status = getnameinfo(&*((struct sockaddr_in6 *) res->ai_addr), - sizeof(*((struct sockaddr_in6 *) res->ai_addr)), - host, - NI_MAXHOST, - serv, - NI_MAXSERV, - flags); - break; - default: break; - } + // Attempt to resolve network byte order ip to hostname + switch (res->ai_family) + { + case AF_INET: + status = getnameinfo(&*((struct sockaddr *) res->ai_addr), + sizeof(*((struct sockaddr_in *) res->ai_addr)), + host, + NI_MAXHOST, + serv, + NI_MAXSERV, + flags); + break; + case AF_INET6: + /* + status = getnameinfo(&*((struct sockaddr_in6 *) res->ai_addr), // TODO. + sizeof(*((struct sockaddr_in6 *) res->ai_addr)), + host, NI_MAXHOST, serv, NI_MAXSERV, flags); + */ + break; + default: break; + } - if (status != 0) - { - TraceLog(LOG_WARNING, "Failed to resolve ip %s: %s", ip, SocketGetLastErrorString()); - } - else - { - TraceLog(LOG_DEBUG, "Successfully resolved %s::%s to %s", ip, port, host); - } + if (status != 0) + { + TraceLog(LOG_WARNING, "Failed to resolve ip %s: %s", ip, SocketGetLastErrorString()); + } + else + { + TraceLog(LOG_DEBUG, "Successfully resolved %s::%s to %s", ip, port, host); + } - // Free the pointer to the data returned by addrinfo - freeaddrinfo(res); + // Free the pointer to the data returned by addrinfo + freeaddrinfo(res); } -// Protocol-independent translation from an ANSI host name to an address +// Protocol-independent translation from an ANSI host name to an address // -// e.g. -// const char* address = "127.0.0.1" (local address) -// const char* port = "80" +// e.g. +// const char* address = "127.0.0.1" (local address) +// const char* port = "80" // // Parameters: // const char* address - A pointer to a NULL-terminated ANSI string that contains a host (node) name or a numeric host address string. // const char* service - A pointer to a NULL-terminated ANSI string that contains either a service name or port number represented as a string. // -// Returns: -// The total amount of addresses found, -1 on error +// Returns: +// The total amount of addresses found, -1 on error // int ResolveHost(const char *address, const char *service, int addressType, int flags, AddressInformation *outAddr) { - // Variables - int status; // Status value to return (0) is success - struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) - struct addrinfo *res; // will point to the results - struct addrinfo *iterator; - assert(((address != NULL || address != 0) || (service != NULL || service != 0))); - assert(((addressType == AF_INET) || (addressType == AF_INET6) || (addressType == AF_UNSPEC))); + // Variables + int status; // Status value to return (0) is success + struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) + struct addrinfo *res; // will point to the results + struct addrinfo *iterator; + assert(((address != NULL || address != 0) || (service != NULL || service != 0))); + assert(((addressType == AF_INET) || (addressType == AF_INET6) || (addressType == AF_UNSPEC))); - // Set the hints - memset(&hints, 0, sizeof hints); - hints.ai_family = addressType; // Either IPv4 or IPv6 (ADDRESS_TYPE_IPV4, ADDRESS_TYPE_IPV6) - hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP) - hints.ai_flags = flags; - assert((hints.ai_addrlen == NULL) || (hints.ai_addrlen == 0)); - assert((hints.ai_canonname == NULL) || (hints.ai_canonname == 0)); - assert((hints.ai_addr == NULL) || (hints.ai_addr == 0)); - assert((hints.ai_next == NULL) || (hints.ai_next == 0)); + // Set the hints + memset(&hints, 0, sizeof hints); + hints.ai_family = addressType; // Either IPv4 or IPv6 (ADDRESS_TYPE_IPV4, ADDRESS_TYPE_IPV6) + hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP) + hints.ai_flags = flags; + assert((hints.ai_addrlen == 0) || (hints.ai_addrlen == 0)); + assert((hints.ai_canonname == 0) || (hints.ai_canonname == 0)); + assert((hints.ai_addr == 0) || (hints.ai_addr == 0)); + assert((hints.ai_next == 0) || (hints.ai_next == 0)); - // When the address is NULL, populate the IP for me - if (address == NULL) - { - if ((hints.ai_flags & AI_PASSIVE) == 0) - { - hints.ai_flags |= AI_PASSIVE; - } - } + // When the address is NULL, populate the IP for me + if (address == NULL) + { + if ((hints.ai_flags & AI_PASSIVE) == 0) + { + hints.ai_flags |= AI_PASSIVE; + } + } - TraceLog(LOG_INFO, "Resolving host..."); + TraceLog(LOG_INFO, "Resolving host..."); - // Populate address information - status = getaddrinfo(address, // e.g. "www.example.com" or IP - service, // e.g. "http" or port number - &hints, // e.g. SOCK_STREAM/SOCK_DGRAM - &res // The struct to populate - ); + // Populate address information + status = getaddrinfo(address, // e.g. "www.example.com" or IP + service, // e.g. "http" or port number + &hints, // e.g. SOCK_STREAM/SOCK_DGRAM + &res // The struct to populate + ); - // Did we succeed? - if (status != 0) - { - int error = SocketGetLastError(); - SocketSetLastError(0); - TraceLog(LOG_WARNING, "Failed to get resolve host: %s", SocketErrorCodeToString(error)); - return -1; - } - else - { - TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, service); - } + // Did we succeed? + if (status != 0) + { + int error = SocketGetLastError(); + SocketSetLastError(0); + TraceLog(LOG_WARNING, "Failed to get resolve host: %s", SocketErrorCodeToString(error)); + return -1; + } + 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) - { - size++; - } + // Calculate the size of the address information list + int size = 0; + for (iterator = res; iterator != NULL; iterator = iterator->ai_next) + { + size++; + } - // Validate the size is > 0, otherwise return - if (size <= 0) - { - TraceLog(LOG_WARNING, "Error, no addresses found."); - return -1; - } + // Validate the size is > 0, otherwise return + 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) - { - outAddr = (AddressInformation *) malloc(size * sizeof(AddressInformation)); - } + // If not address list was allocated, allocate it dynamically with the known address size + if (outAddr == NULL) + { + outAddr = (AddressInformation *) malloc(size * sizeof(AddressInformation)); + } - // Dynamically allocate an array of address information structs - if (outAddr != NULL) - { - int i; - for (i = 0; i < size; ++i) - { - outAddr[i] = AllocAddress(); - if (outAddr[i] == NULL) - { - break; - } - } - outAddr[i] = NULL; - if (i != size) - { - outAddr = NULL; - } - } - else - { - TraceLog(LOG_WARNING, - "Error, failed to dynamically allocate memory for the address list"); - return -1; - } + // Dynamically allocate an array of address information structs + if (outAddr != NULL) + { + int i; + for (i = 0; i < size; ++i) + { + outAddr[i] = AllocAddress(); + if (outAddr[i] == NULL) + { + break; + } + } + outAddr[i] = NULL; + if (i != size) + { + outAddr = NULL; + } + } + else + { + TraceLog(LOG_WARNING, + "Error, failed to dynamically allocate memory for the address list"); + return -1; + } - // Copy all the address information from res into outAddrList - int i = 0; - 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; - outAddr[i]->addr.ai_protocol = iterator->ai_protocol; - outAddr[i]->addr.ai_addrlen = iterator->ai_addrlen; - *outAddr[i]->addr.ai_addr = *iterator->ai_addr; + // Copy all the address information from res into outAddrList + int i = 0; + 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; + outAddr[i]->addr.ai_protocol = iterator->ai_protocol; + outAddr[i]->addr.ai_addrlen = iterator->ai_addrlen; + *outAddr[i]->addr.ai_addr = *iterator->ai_addr; #if NET_DEBUG_ENABLED - TraceLog(LOG_DEBUG, "GetAddressInformation"); - TraceLog(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags); - PrintSocket(outAddr[i]->addr.ai_addr, - outAddr[i]->addr.ai_family, - outAddr[i]->addr.ai_socktype, - outAddr[i]->addr.ai_protocol); - TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", outAddr[i]->addr.ai_addrlen); - TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname); + TraceLog(LOG_DEBUG, "GetAddressInformation"); + TraceLog(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags); + //PrintSocket(outAddr[i]->addr.ai_addr, outAddr[i]->addr.ai_family, outAddr[i]->addr.ai_socktype, outAddr[i]->addr.ai_protocol); + TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", outAddr[i]->addr.ai_addrlen); + TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname); #endif - i++; - } - } + i++; + } + } - // Free the pointer to the data returned by addrinfo - freeaddrinfo(res); + // Free the pointer to the data returned by addrinfo + freeaddrinfo(res); - // Return the total count of addresses found - return size; + // Return the total count of addresses found + return size; } -// This here is the bread and butter of the socket API, This function will -// attempt to open a socket, bind and listen to it based on the config passed in +// This here is the bread and butter of the socket API, This function will +// attempt to open a socket, bind and listen to it based on the config passed in // -// SocketConfig* config - Configuration for which socket to open -// SocketResult* result - The results of this function (if any, including errors) +// SocketConfig* config - Configuration for which socket to open +// SocketResult* result - The results of this function (if any, including errors) // -// e.g. -// SocketConfig server_config = { SocketConfig client_config = { -// .host = "127.0.0.1", .host = "127.0.0.1", -// .port = 8080, .port = 8080, -// .server = true, }; -// .nonblocking = true, -// }; -// SocketResult server_res; SocketResult client_res; +// e.g. +// SocketConfig server_config = { SocketConfig client_config = { +// .host = "127.0.0.1", .host = "127.0.0.1", +// .port = 8080, .port = 8080, +// .server = true, }; +// .nonblocking = true, +// }; +// SocketResult server_res; SocketResult client_res; bool SocketCreate(SocketConfig *config, SocketResult *result) { - // Socket creation result - bool success = true; + // Socket creation result + bool success = true; - // Make sure we've not received a null config or result pointer - if (config == NULL || result == NULL) - { - return (success = false); - } + // Make sure we've not received a null config or result pointer + if (config == NULL || result == NULL) + { + return (success = false); + } - // Set the defaults based on the config - if (!SocketSetDefaults(config)) - { - TraceLog(LOG_WARNING, "Configuration Error."); - success = false; - } - else - { - // Create the socket - if (CreateSocket(config, result)) - { - if (config->nonblocking) - { - SocketSetNonBlocking(result->socket); - } - else - { - SocketSetBlocking(result->socket); - } - } - else - { - success = false; - } - } - return success; + // Set the defaults based on the config + if (!SocketSetDefaults(config)) + { + TraceLog(LOG_WARNING, "Configuration Error."); + success = false; + } + else + { + // Create the socket + if (CreateSocket(config, result)) + { + if (config->nonblocking) + { + SocketSetNonBlocking(result->socket); + } + else + { + SocketSetBlocking(result->socket); + } + } + else + { + success = false; + } + } + return success; } // Bind a socket to a local address // 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_storage *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) - { - TraceLog(LOG_WARNING, - "Cannot bind to socket marked as \"Client\" in SocketConfig."); - success = false; - } - else - { - if (result->socket->isIPv6) - { - sock_addr = (struct sockaddr_storage *) &result->socket->addripv6->address; - } - 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 - { - result->socket->status = SocketGetLastError(); - TraceLog(LOG_WARNING, "Socket Error: %s", - SocketErrorCodeToString(result->socket->status)); - SocketSetLastError(0); - success = false; - } - } - } - // Was the bind a 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) - { - 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; + // Don't bind to a socket that isn't configured as a 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_storage *) &result->socket->addripv6->address; + } + 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 + { + result->socket->status = SocketGetLastError(); + TraceLog(LOG_WARNING, "Socket Error: %s", + SocketErrorCodeToString(result->socket->status)); + SocketSetLastError(0); + success = false; + } + } + } + // Was the bind a 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) + { + 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; - // - 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; + // + 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; } // Listens (and queues) incoming connections requests for a bound port. bool SocketListen(SocketConfig *config, SocketResult *result) { - bool success = false; - result->status = RESULT_FAILURE; + bool success = false; + result->status = RESULT_FAILURE; - // Don't bind to a socket that isn't configured as a server - if (!IsSocketValid(result->socket) || !config->server) - { - TraceLog(LOG_WARNING, - "Cannot listen on socket marked as \"Client\" in SocketConfig."); - success = false; - } - else - { - // Don't listen on UDP sockets - 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 - { - success = false; - result->socket->status = SocketGetLastError(); - TraceLog(LOG_WARNING, "Socket Error: %s", - SocketErrorCodeToString(result->socket->status)); - SocketSetLastError(0); - } - } - else - { - TraceLog(LOG_WARNING, - "Cannot listen on socket marked as \"UDP\" (datagram) in SocketConfig."); - success = false; - } - } + // Don't bind to a socket that isn't configured as a server + if (!IsSocketValid(result->socket) || !config->server) + { + TraceLog(LOG_WARNING, + "Cannot listen on socket marked as \"Client\" in SocketConfig."); + success = false; + } + else + { + // Don't listen on UDP sockets + 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 + { + success = false; + result->socket->status = SocketGetLastError(); + TraceLog(LOG_WARNING, "Socket Error: %s", + SocketErrorCodeToString(result->socket->status)); + SocketSetLastError(0); + } + } + else + { + TraceLog(LOG_WARNING, + "Cannot listen on socket marked as \"UDP\" (datagram) in SocketConfig."); + success = false; + } + } - // Was the listen a success? - if (success) - { - result->status = RESULT_SUCCESS; - result->socket->ready = 0; - result->socket->status = 0; - } - return success; + // Was the listen a success? + if (success) + { + result->status = RESULT_SUCCESS; + result->socket->ready = 0; + result->socket->status = 0; + } + return success; } // Connect the socket to the destination specified by "host" and "port" in SocketConfig bool SocketConnect(SocketConfig *config, SocketResult *result) { - bool success = true; - result->status = RESULT_FAILURE; + bool success = true; + result->status = RESULT_FAILURE; - // Only bind to sockets marked as server - if (config->server) - { - TraceLog(LOG_WARNING, - "Cannot connect to socket marked as \"Server\" in SocketConfig."); - success = false; - } - else - { - if (IsIPv4Address(config->host)) - { - struct sockaddr_in ip4addr; - ip4addr.sin_family = AF_INET; - unsigned long hport; - hport = strtoul(config->port, NULL, 0); - 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) - { - result->socket->status = SocketGetLastError(); - SocketSetLastError(0); - switch (result->socket->status) - { - case WSAEWOULDBLOCK: - { - success = true; - break; - } - default: - { - TraceLog(LOG_WARNING, "Socket Error: %s", - SocketErrorCodeToString(result->socket->status)); - success = false; - break; - } - } - } - else - { - TraceLog(LOG_INFO, "Successfully connected to socket."); - success = true; - } - } - else - { - if (IsIPv6Address(config->host)) - { - struct sockaddr_in6 ip6addr; - ip6addr.sin6_family = AF_INET6; - unsigned long hport; - hport = strtoul(config->port, NULL, 0); - 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) - { - result->socket->status = SocketGetLastError(); - SocketSetLastError(0); - switch (result->socket->status) - { - case WSAEWOULDBLOCK: - { - success = true; - break; - } - default: - { - TraceLog(LOG_WARNING, "Socket Error: %s", - SocketErrorCodeToString(result->socket->status)); - success = false; - break; - } - } - } - else - { - TraceLog(LOG_INFO, "Successfully connected to socket."); - success = true; - } - } - } - } + // Only bind to sockets marked as server + if (config->server) + { + TraceLog(LOG_WARNING, + "Cannot connect to socket marked as \"Server\" in SocketConfig."); + success = false; + } + else + { + if (IsIPv4Address(config->host)) + { + struct sockaddr_in ip4addr; + ip4addr.sin_family = AF_INET; + unsigned long hport; + hport = strtoul(config->port, NULL, 0); + ip4addr.sin_port = htons(hport); + + // TODO: Changed the code to avoid the usage of inet_pton and inet_ntop replacing them with getnameinfo (that should have a better support on windows). + + //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) + { + result->socket->status = SocketGetLastError(); + SocketSetLastError(0); + switch (result->socket->status) + { + case WSAEWOULDBLOCK: + { + success = true; + break; + } + default: + { + TraceLog(LOG_WARNING, "Socket Error: %s", + SocketErrorCodeToString(result->socket->status)); + success = false; + break; + } + } + } + else + { + TraceLog(LOG_INFO, "Successfully connected to socket."); + success = true; + } + } + else + { + if (IsIPv6Address(config->host)) + { + struct sockaddr_in6 ip6addr; + ip6addr.sin6_family = AF_INET6; + unsigned long hport; + hport = strtoul(config->port, NULL, 0); + ip6addr.sin6_port = htons(hport); + //inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr); // TODO. + int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip6addr, sizeof(ip6addr)); + if (connect_result == SOCKET_ERROR) + { + result->socket->status = SocketGetLastError(); + SocketSetLastError(0); + switch (result->socket->status) + { + case WSAEWOULDBLOCK: + { + success = true; + break; + } + default: + { + TraceLog(LOG_WARNING, "Socket Error: %s", + SocketErrorCodeToString(result->socket->status)); + success = false; + break; + } + } + } + else + { + TraceLog(LOG_INFO, "Successfully connected to socket."); + success = true; + } + } + } + } - if (success) - { - result->status = RESULT_SUCCESS; - result->socket->ready = 0; - result->socket->status = 0; - } + if (success) + { + result->status = RESULT_SUCCESS; + result->socket->ready = 0; + result->socket->status = 0; + } - return success; + return success; } -// Closes an existing socket +// Closes an existing socket // -// SocketChannel socket - The id of the socket to close +// SocketChannel socket - The id of the socket to close void SocketClose(Socket *sock) { - if (sock != NULL) - { - if (sock->channel != INVALID_SOCKET) - { - closesocket(sock->channel); - } - } + 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; - } + // TODO. + /* + if (sock->isServer) return NULL; + if (sock->isIPv6) return sock->addripv6; + else return sock->addripv4; + */ + + return NULL; } // 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); + 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)); + //return ntohs(GetSocketPortPtr(storage)); // TODO. + + return 0; } -// The accept function permits an incoming connection attempt on a socket. +// The accept function permits an incoming connection attempt on a socket. // -// SocketChannel listener - The socket to listen for incoming connections on (i.e. server) -// SocketResult* out - The result of this function (if any, including errors) +// SocketChannel listener - The socket to listen for incoming connections on (i.e. server) +// SocketResult* out - The result of this function (if any, including errors) // -// e.g. +// e.g. // -// SocketResult connection; -// bool connected = false; -// if (!connected) -// { -// if (SocketAccept(server_res.socket.channel, &connection)) -// { -// connected = true; -// } -// } +// SocketResult connection; +// bool connected = false; +// if (!connected) +// { +// if (SocketAccept(server_res.socket.channel, &connection)) +// { +// connected = true; +// } +// } Socket *SocketAccept(Socket *server, SocketConfig *config) { - if (!server->isServer || server->type == SOCKET_UDP) - { - return NULL; - } - struct sockaddr_storage sock_addr; - socklen_t sock_alen; - Socket * sock; - sock = AllocSocket(); - server->ready = 0; - sock_alen = sizeof(sock_addr); - sock->channel = accept(server->channel, (struct sockaddr *) &sock_addr, &sock_alen); - if (sock->channel == INVALID_SOCKET) - { - sock->status = SocketGetLastError(); - TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); - SocketSetLastError(0); - SocketClose(sock); - return NULL; - } - (config->nonblocking) ? SocketSetNonBlocking(sock) : SocketSetBlocking(sock); - sock->isServer = false; - sock->ready = 0; - sock->type = server->type; - 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) - { - 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)); - } - } - 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) - { - 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)); - } - } - break; - } - return sock; + if (!server->isServer || server->type == SOCKET_UDP) + { + return NULL; + } + struct sockaddr_storage sock_addr; + socklen_t sock_alen; + Socket * sock; + sock = AllocSocket(); + server->ready = 0; + sock_alen = sizeof(sock_addr); + sock->channel = accept(server->channel, (struct sockaddr *) &sock_addr, &sock_alen); + if (sock->channel == INVALID_SOCKET) + { + sock->status = SocketGetLastError(); + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); + SocketSetLastError(0); + SocketClose(sock); + return NULL; + } + (config->nonblocking) ? SocketSetNonBlocking(sock) : SocketSetBlocking(sock); + sock->isServer = false; + sock->ready = 0; + sock->type = server->type; + 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) + { + 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)); + } + } + 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) + { + 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)); + } + } + break; + } + return sock; } // Verify that the channel is in the valid range static int ValidChannel(int channel) { - if ((channel < 0) || (channel >= SOCKET_MAX_UDPCHANNELS)) - { - TraceLog(LOG_WARNING, "Invalid channel"); - return 0; - } - return 1; + if ((channel < 0) || (channel >= SOCKET_MAX_UDPCHANNELS)) + { + TraceLog(LOG_WARNING, "Invalid channel"); + return 0; + } + return 1; } // Set the socket channel int SocketSetChannel(Socket *socket, int channel, const IPAddress *address) { - struct UDPChannel *binding; - if (socket == NULL) - { - TraceLog(LOG_WARNING, "Passed a NULL socket"); - return (-1); - } - if (channel == -1) - { - for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel) - { - binding = &socket->binding[channel]; - if (binding->numbound < SOCKET_MAX_UDPADDRESSES) - { - break; - } - } - } - else - { - if (!ValidChannel(channel)) - { - return (-1); - } - binding = &socket->binding[channel]; - } - if (binding->numbound == SOCKET_MAX_UDPADDRESSES) - { - TraceLog(LOG_WARNING, "No room for new addresses"); - return (-1); - } - binding->address[binding->numbound++] = *address; - return (channel); + struct UDPChannel *binding; + if (socket == NULL) + { + TraceLog(LOG_WARNING, "Passed a NULL socket"); + return (-1); + } + if (channel == -1) + { + for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel) + { + binding = &socket->binding[channel]; + if (binding->numbound < SOCKET_MAX_UDPADDRESSES) + { + break; + } + } + } + else + { + if (!ValidChannel(channel)) + { + return (-1); + } + binding = &socket->binding[channel]; + } + if (binding->numbound == SOCKET_MAX_UDPADDRESSES) + { + TraceLog(LOG_WARNING, "No room for new addresses"); + return (-1); + } + binding->address[binding->numbound++] = *address; + return (channel); } // Remove the socket channel void SocketUnsetChannel(Socket *socket, int channel) { - if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) - { - socket->binding[channel].numbound = 0; - } + if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) + { + socket->binding[channel].numbound = 0; + } } /* Allocate/free a single UDP packet 'size' bytes long. @@ -1315,49 +1317,49 @@ void SocketUnsetChannel(Socket *socket, int channel) */ SocketDataPacket *AllocPacket(int size) { - SocketDataPacket *packet; - int error; + 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); + 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; + uint8_t *newdata; - newdata = (uint8_t *) malloc(newsize); - if (newdata != NULL) - { - free(packet->data); - packet->data = newdata; - packet->maxlen = newsize; - } - return (packet->maxlen); + 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); - } + if (packet) + { + free(packet->data); + free(packet); + } } /* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets, @@ -1367,656 +1369,656 @@ void FreePacket(SocketDataPacket *packet) */ SocketDataPacket **AllocPacketList(int howmany, int size) { - SocketDataPacket **packetV; + 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; + 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); + 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); - } + if (packetV) + { + int i; + for (i = 0; packetV[i]; ++i) + { + FreePacket(packetV[i]); + } + free(packetV); + } } -// Send 'len' bytes of 'data' over the non-server socket 'sock' +// Send 'len' bytes of 'data' over the non-server socket 'sock' // -// Example +// Example int SocketSend(Socket *sock, const void *datap, int length) { - int sent = 0; - int left = length; - int status = -1; - int numsent = 0; - const unsigned char *data = (const unsigned char *) datap; + int sent = 0; + int left = length; + int status = -1; + int numsent = 0; + const unsigned char *data = (const unsigned char *) datap; - // Server sockets are for accepting connections only - if (sock->isServer) - { - TraceLog(LOG_WARNING, "Cannot send information on a server socket"); - return -1; - } + // Server sockets are for accepting connections only + 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: - { - SocketSetLastError(0); - do - { - length = send(sock->channel, (const char *) data, left, 0); - if (length > 0) - { - sent += length; - left -= length; - data += length; - } - } while ((left > 0) && // While we still have bytes left to send - ((length > 0) || // The amount of bytes we actually sent is > 0 - (SocketGetLastError() == WSAEINTR)) // The socket was interupted - ); + // Which socket are we trying to send data on + switch (sock->type) + { + case SOCKET_TCP: + { + SocketSetLastError(0); + do + { + length = send(sock->channel, (const char *) data, left, 0); + if (length > 0) + { + sent += length; + left -= length; + data += length; + } + } while ((left > 0) && // While we still have bytes left to send + ((length > 0) || // The amount of bytes we actually sent is > 0 + (SocketGetLastError() == WSAEINTR)) // The socket was interupted + ); - if (length == SOCKET_ERROR) - { - sock->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status)); - SocketSetLastError(0); - } - else - { - TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, sent); - } + if (length == SOCKET_ERROR) + { + sock->status = SocketGetLastError(); + TraceLog(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status)); + SocketSetLastError(0); + } + else + { + TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, sent); + } - return sent; - } - break; - case SOCKET_UDP: - { - SocketSetLastError(0); - if (sock->isIPv6) - { - status = sendto(sock->channel, (const char *) data, left, 0, - (struct sockaddr *) &sock->addripv6->address, - sizeof(sock->addripv6->address)); - } - else - { - status = sendto(sock->channel, (const char *) data, left, 0, - (struct sockaddr *) &sock->addripv4->address, - sizeof(sock->addripv4->address)); - } - if (sent >= 0) - { - sock->status = 0; - ++numsent; - TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, status); - } - else - { - sock->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status)); - SocketSetLastError(0); - return 0; - } - return numsent; - } - break; - default: break; - } - return -1; + return sent; + } + break; + case SOCKET_UDP: + { + SocketSetLastError(0); + if (sock->isIPv6) + { + status = sendto(sock->channel, (const char *) data, left, 0, + (struct sockaddr *) &sock->addripv6->address, + sizeof(sock->addripv6->address)); + } + else + { + status = sendto(sock->channel, (const char *) data, left, 0, + (struct sockaddr *) &sock->addripv4->address, + sizeof(sock->addripv4->address)); + } + if (sent >= 0) + { + sock->status = 0; + ++numsent; + TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, status); + } + else + { + sock->status = SocketGetLastError(); + TraceLog(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status)); + SocketSetLastError(0); + return 0; + } + return numsent; + } + break; + default: break; + } + return -1; } -// Receive up to 'maxlen' bytes of data over the non-server socket 'sock', -// and store them in the buffer pointed to by 'data'. -// This function returns the actual amount of data received. If the return -// value is less than or equal to zero, then either the remote connection was -// closed, or an unknown socket error occurred. +// Receive up to 'maxlen' bytes of data over the non-server socket 'sock', +// and store them in the buffer pointed to by 'data'. +// This function returns the actual amount of data received. If the return +// value is less than or equal to zero, then either the remote connection was +// closed, or an unknown socket error occurred. int SocketReceive(Socket *sock, void *data, int maxlen) { - int len = 0; - int numrecv = 0; - int status = 0; - socklen_t sock_len; - struct sockaddr_storage sock_addr; - char ip[INET6_ADDRSTRLEN]; + int len = 0; + int numrecv = 0; + int status = 0; + socklen_t sock_len; + struct sockaddr_storage sock_addr; + //char ip[INET6_ADDRSTRLEN]; - // Server sockets are for accepting connections only - if (sock->isServer && sock->type == SOCKET_TCP) - { - sock->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, "Socket Error: %s", - "Server sockets cannot be used to receive data"); - SocketSetLastError(0); - return 0; - } + // Server sockets are for accepting connections only + if (sock->isServer && sock->type == SOCKET_TCP) + { + sock->status = SocketGetLastError(); + TraceLog(LOG_DEBUG, "Socket Error: %s", "Server sockets cannot be used to receive data"); + SocketSetLastError(0); + return 0; + } - // Which socket are we trying to send data on - switch (sock->type) - { - case SOCKET_TCP: - { - SocketSetLastError(0); - do - { - len = recv(sock->channel, (char *) data, maxlen, 0); - } while (SocketGetLastError() == WSAEINTR); + // Which socket are we trying to send data on + switch (sock->type) + { + case SOCKET_TCP: + { + SocketSetLastError(0); + do + { + len = recv(sock->channel, (char *) data, maxlen, 0); + } while (SocketGetLastError() == WSAEINTR); - if (len > 0) - { - // Who sent the packet? - 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))); - } - ((unsigned char *) data)[len] = '\0'; // Add null terminating character to the end of the stream - TraceLog(LOG_DEBUG, "Received \"%s\" (%d bytes)", data, len); - } - sock->ready = 0; - return len; - } - break; - case SOCKET_UDP: - { - SocketSetLastError(0); - sock_len = sizeof(sock_addr); - status = recvfrom(sock->channel, // The receving channel + if (len > 0) + { + // Who sent the packet? + 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))); + } + + ((unsigned char *) data)[len] = '\0'; // Add null terminating character to the end of the stream + TraceLog(LOG_DEBUG, "Received \"%s\" (%d bytes)", data, len); + } + + sock->ready = 0; + return len; + } + break; + case SOCKET_UDP: + { + SocketSetLastError(0); + sock_len = sizeof(sock_addr); + status = recvfrom(sock->channel, // The receving channel data, // A pointer to the data buffer to fill maxlen, // The max length of the data to fill 0, // Flags (struct sockaddr *) &sock_addr, // The address of the recevied data &sock_len // The length of the received data address ); - if (status >= 0) - { - ++numrecv; - } - else - { - sock->status = SocketGetLastError(); - switch (sock->status) - { - case WSAEWOULDBLOCK: { break; - } - default: - { - TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); - break; - } - } - SocketSetLastError(0); - return 0; - } - sock->ready = 0; - return numrecv; - } - break; - } - return -1; + if (status >= 0) + { + ++numrecv; + } + else + { + sock->status = SocketGetLastError(); + switch (sock->status) + { + case WSAEWOULDBLOCK: { break; + } + default: + { + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); + break; + } + } + SocketSetLastError(0); + return 0; + } + sock->ready = 0; + return numrecv; + } + break; + } + return -1; } // Does the socket have it's 'ready' flag set? bool IsSocketReady(Socket *sock) { - return (sock != NULL) && (sock->ready); + return (sock != NULL) && (sock->ready); } // Check if the socket is considered connected bool IsSocketConnected(Socket *sock) { #if defined(_WIN32) - FD_SET writefds; - FD_ZERO(&writefds); - FD_SET(sock->channel, &writefds); - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 1000000000UL; - int total = select(0, NULL, &writefds, NULL, &timeout); - if (total == -1) - { // Error - sock->status = SocketGetLastError(); - TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); - SocketSetLastError(0); - } - else if (total == 0) - { // Timeout - return false; - } - else - { - if (FD_ISSET(sock->channel, &writefds)) - { - return true; - } - } - return false; + FD_SET writefds; + FD_ZERO(&writefds); + FD_SET(sock->channel, &writefds); + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 1000000000UL; + int total = select(0, NULL, &writefds, NULL, &timeout); + if (total == -1) + { // Error + sock->status = SocketGetLastError(); + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); + SocketSetLastError(0); + } + else if (total == 0) + { // Timeout + return false; + } + else + { + if (FD_ISSET(sock->channel, &writefds)) + { + return true; + } + } + return false; #else - return true; + return true; #endif } // Allocate and return a SocketResult struct SocketResult *AllocSocketResult() { - struct SocketResult *res; - res = (struct SocketResult *) malloc(sizeof(*res)); - if (res != NULL) - { - memset(res, 0, sizeof(*res)); - if ((res->socket = AllocSocket()) == NULL) - { - free(res); - res = NULL; - } - } - return res; + struct SocketResult *res; + res = (struct SocketResult *) malloc(sizeof(*res)); + if (res != NULL) + { + memset(res, 0, sizeof(*res)); + if ((res->socket = AllocSocket()) == NULL) + { + free(res); + res = NULL; + } + } + return res; } // Free an allocated SocketResult void FreeSocketResult(SocketResult **result) { - if (*result != NULL) - { - if ((*result)->socket != NULL) - { - FreeSocket(&((*result)->socket)); - } - free(*result); - *result = NULL; - } + if (*result != NULL) + { + if ((*result)->socket != NULL) + { + FreeSocket(&((*result)->socket)); + } + free(*result); + *result = NULL; + } } // Allocate a Socket Socket *AllocSocket() { - // Allocate a socket if one already hasn't been - struct Socket *sock; - sock = (Socket *) malloc(sizeof(*sock)); - if (sock != NULL) - { - memset(sock, 0, sizeof(*sock)); - } - else - { - TraceLog( - LOG_WARNING, "Ran out of memory attempting to allocate a socket"); - SocketClose(sock); - free(sock); - sock = NULL; - } - return sock; + // Allocate a socket if one already hasn't been + struct Socket *sock; + sock = (Socket *) malloc(sizeof(*sock)); + if (sock != NULL) + { + memset(sock, 0, sizeof(*sock)); + } + else + { + TraceLog( + LOG_WARNING, "Ran out of memory attempting to allocate a socket"); + SocketClose(sock); + free(sock); + sock = NULL; + } + return sock; } // Free an allocated Socket void FreeSocket(Socket **sock) { - if (*sock != NULL) - { - free(*sock); - *sock = NULL; - } + if (*sock != NULL) + { + free(*sock); + *sock = NULL; + } } // Allocate a SocketSet SocketSet *AllocSocketSet(int max) { - struct SocketSet *set; - int i; + struct SocketSet *set; + int i; - set = (struct SocketSet *) malloc(sizeof(*set)); - 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) - { - set->sockets[i] = NULL; - } - } - else - { - free(set); - set = NULL; - } - } - return (set); + set = (struct SocketSet *) malloc(sizeof(*set)); + 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) + { + set->sockets[i] = NULL; + } + } + else + { + free(set); + set = NULL; + } + } + return (set); } // Free an allocated SocketSet void FreeSocketSet(SocketSet *set) { - if (set) - { - free(set->sockets); - free(set); - } + if (set) + { + free(set->sockets); + free(set); + } } // Add a Socket "sock" to the SocketSet "set" int AddSocket(SocketSet *set, Socket *sock) { - 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 - { - TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket was null"); - SocketSetLastError(0); - return (-1); - } - return (set->numsockets); + 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 + { + TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket was null"); + SocketSetLastError(0); + return (-1); + } + return (set->numsockets); } // Remove a Socket "sock" to the SocketSet "set" int RemoveSocket(SocketSet *set, Socket *sock) { - int i; + int i; - if (sock != NULL) - { - for (i = 0; i < set->numsockets; ++i) - { - if (set->sockets[i] == (struct Socket *) sock) - { - break; - } - } - if (i == set->numsockets) - { - TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket not found"); - SocketSetLastError(0); - return (-1); - } - --set->numsockets; - for (; i < set->numsockets; ++i) - { - set->sockets[i] = set->sockets[i + 1]; - } - } - return (set->numsockets); + if (sock != NULL) + { + for (i = 0; i < set->numsockets; ++i) + { + if (set->sockets[i] == (struct Socket *) sock) + { + break; + } + } + if (i == set->numsockets) + { + TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket not found"); + SocketSetLastError(0); + return (-1); + } + --set->numsockets; + for (; i < set->numsockets; ++i) + { + set->sockets[i] = set->sockets[i + 1]; + } + } + return (set->numsockets); } // Check the sockets in the socket set for pending information int CheckSockets(SocketSet *set, unsigned int timeout) { - int i; - SOCKET maxfd; - int retval; - struct timeval tv; - fd_set mask; + int i; + SOCKET maxfd; + int retval; + struct timeval tv; + fd_set mask; - /* Find the largest file descriptor */ - maxfd = 0; - for (i = set->numsockets - 1; i >= 0; --i) - { - if (set->sockets[i]->channel > maxfd) - { - maxfd = set->sockets[i]->channel; - } - } + /* Find the largest file descriptor */ + maxfd = 0; + 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 - { - SocketSetLastError(0); + // Check the file descriptors for available data + do + { + SocketSetLastError(0); - // Set up the mask of file descriptors - FD_ZERO(&mask); - for (i = set->numsockets - 1; i >= 0; --i) - { - FD_SET(set->sockets[i]->channel, &mask); - } // Set up the timeout - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; + // Set up the mask of file descriptors + FD_ZERO(&mask); + for (i = set->numsockets - 1; i >= 0; --i) + { + FD_SET(set->sockets[i]->channel, &mask); + } // Set up the timeout + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; - /* Look! */ - retval = select(maxfd + 1, &mask, NULL, NULL, &tv); - } while (SocketGetLastError() == WSAEINTR); + /* Look! */ + retval = select(maxfd + 1, &mask, NULL, NULL, &tv); + } 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)) - { - set->sockets[i]->ready = 1; - } - } - } - return (retval); + // 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)) + { + set->sockets[i]->ready = 1; + } + } + } + return (retval); } // Allocate an AddressInformation AddressInformation AllocAddress() { - AddressInformation addressInfo = NULL; - addressInfo = (AddressInformation) calloc(1, sizeof(*addressInfo)); - if (addressInfo != NULL) - { - addressInfo->addr.ai_addr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr)); - if (addressInfo->addr.ai_addr == NULL) - { - TraceLog(LOG_WARNING, - "Failed to allocate memory for \"struct sockaddr\""); - } - } - else - { - TraceLog(LOG_WARNING, - "Failed to allocate memory for \"struct AddressInformation\""); - } - return addressInfo; + AddressInformation addressInfo = NULL; + addressInfo = (AddressInformation) calloc(1, sizeof(*addressInfo)); + if (addressInfo != NULL) + { + addressInfo->addr.ai_addr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr)); + if (addressInfo->addr.ai_addr == NULL) + { + TraceLog(LOG_WARNING, + "Failed to allocate memory for \"struct sockaddr\""); + } + } + else + { + TraceLog(LOG_WARNING, + "Failed to allocate memory for \"struct AddressInformation\""); + } + return addressInfo; } // Free an AddressInformation struct void FreeAddress(AddressInformation *addressInfo) { - if (*addressInfo != NULL) - { - if ((*addressInfo)->addr.ai_addr != NULL) - { - free((*addressInfo)->addr.ai_addr); - (*addressInfo)->addr.ai_addr = NULL; - } - free(*addressInfo); - *addressInfo = NULL; - } + if (*addressInfo != NULL) + { + if ((*addressInfo)->addr.ai_addr != NULL) + { + free((*addressInfo)->addr.ai_addr); + (*addressInfo)->addr.ai_addr = NULL; + } + free(*addressInfo); + *addressInfo = NULL; + } } // Allocate a list of AddressInformation AddressInformation *AllocAddressList(int size) { - AddressInformation *addr; - addr = (AddressInformation *) malloc(size * sizeof(AddressInformation)); - return addr; + AddressInformation *addr; + addr = (AddressInformation *) malloc(size * sizeof(AddressInformation)); + return addr; } // Opaque datatype accessor addrinfo->ai_family int GetAddressFamily(AddressInformation address) { - return address->addr.ai_family; + return address->addr.ai_family; } // Opaque datatype accessor addrinfo->ai_socktype int GetAddressSocketType(AddressInformation address) { - return address->addr.ai_socktype; + return address->addr.ai_socktype; } // Opaque datatype accessor addrinfo->ai_protocol int GetAddressProtocol(AddressInformation address) { - return address->addr.ai_protocol; + return address->addr.ai_protocol; } // Opaque datatype accessor addrinfo->ai_canonname char *GetAddressCanonName(AddressInformation address) { - return address->addr.ai_canonname; + return address->addr.ai_canonname; } // Opaque datatype accessor addrinfo->ai_addr char *GetAddressHostAndPort(AddressInformation address, char *outhost, int *outport) { - 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: - { - 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: - { - 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; - } - if (result == NULL) - { - TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(SocketGetLastError())); - SocketSetLastError(0); - } - else - { - strcpy(outhost, result); - } - return result; + //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: + { + struct sockaddr_in *s = ((struct sockaddr_in *) address->addr.ai_addr); + //result = inet_ntop(AF_INET, &s->sin_addr, ip, INET_ADDRSTRLEN); // TODO. + *outport = ntohs(s->sin_port); + } + 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); // TODO. + *outport = ntohs(s->sin6_port); + } + break; + } + if (result == NULL) + { + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(SocketGetLastError())); + SocketSetLastError(0); + } + else + { + strcpy(outhost, result); + } + return result; } // void PacketSend(Packet *packet) { - printf("Sending packet (%s) with size %d\n", packet->data, packet->size); + printf("Sending packet (%s) with size %d\n", packet->data, packet->size); } // void PacketReceive(Packet *packet) { - printf("Receiving packet (%s) with size %d\n", packet->data, packet->size); + printf("Receiving packet (%s) with size %d\n", packet->data, packet->size); } // void PacketWrite16(Packet *packet, uint16_t value) { - printf("Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value); - uint8_t *data = packet->data + packet->offs; - *data++ = (uint8_t)(value >> 8); - *data++ = (uint8_t)(value); - packet->size += sizeof(uint16_t); - packet->offs += sizeof(uint16_t); - printf("Network: 0x%04" PRIX16 " - %" PRIu16 "\n", (uint16_t) *data, (uint16_t) *data); + printf("Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value); + uint8_t *data = packet->data + packet->offs; + *data++ = (uint8_t)(value >> 8); + *data++ = (uint8_t)(value); + packet->size += sizeof(uint16_t); + packet->offs += sizeof(uint16_t); + printf("Network: 0x%04" PRIX16 " - %" PRIu16 "\n", (uint16_t) *data, (uint16_t) *data); } // void PacketWrite32(Packet *packet, uint32_t value) { - printf("Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value); - uint8_t *data = packet->data + packet->offs; - *data++ = (uint8_t)(value >> 24); - *data++ = (uint8_t)(value >> 16); - *data++ = (uint8_t)(value >> 8); - *data++ = (uint8_t)(value); - packet->size += sizeof(uint32_t); - packet->offs += sizeof(uint32_t); - printf("Network: 0x%08" PRIX32 " - %" PRIu32 "\n", - (uint32_t)(((intptr_t) packet->data) - packet->offs), - (uint32_t)(((intptr_t) packet->data) - packet->offs)); + printf("Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value); + uint8_t *data = packet->data + packet->offs; + *data++ = (uint8_t)(value >> 24); + *data++ = (uint8_t)(value >> 16); + *data++ = (uint8_t)(value >> 8); + *data++ = (uint8_t)(value); + packet->size += sizeof(uint32_t); + packet->offs += sizeof(uint32_t); + printf("Network: 0x%08" PRIX32 " - %" PRIu32 "\n", + (uint32_t)(((intptr_t) packet->data) - packet->offs), + (uint32_t)(((intptr_t) packet->data) - packet->offs)); } // void PacketWrite64(Packet *packet, uint64_t value) { - printf("Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value); - uint8_t *data = packet->data + packet->offs; - *data++ = (uint8_t)(value >> 56); - *data++ = (uint8_t)(value >> 48); - *data++ = (uint8_t)(value >> 40); - *data++ = (uint8_t)(value >> 32); - *data++ = (uint8_t)(value >> 24); - *data++ = (uint8_t)(value >> 16); - *data++ = (uint8_t)(value >> 8); - *data++ = (uint8_t)(value); - packet->size += sizeof(uint64_t); - packet->offs += sizeof(uint64_t); - printf("Network: 0x%016" PRIX64 " - %" PRIu64 "\n", - (uint64_t)(packet->data - packet->offs), - (uint64_t)(packet->data - packet->offs)); + printf("Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value); + uint8_t *data = packet->data + packet->offs; + *data++ = (uint8_t)(value >> 56); + *data++ = (uint8_t)(value >> 48); + *data++ = (uint8_t)(value >> 40); + *data++ = (uint8_t)(value >> 32); + *data++ = (uint8_t)(value >> 24); + *data++ = (uint8_t)(value >> 16); + *data++ = (uint8_t)(value >> 8); + *data++ = (uint8_t)(value); + packet->size += sizeof(uint64_t); + packet->offs += sizeof(uint64_t); + printf("Network: 0x%016" PRIX64 " - %" PRIu64 "\n", + (uint64_t)(packet->data - packet->offs), + (uint64_t)(packet->data - packet->offs)); } // uint16_t PacketRead16(Packet *packet) { - uint8_t *data = packet->data + packet->offs; - packet->size += sizeof(uint16_t); - packet->offs += sizeof(uint16_t); - uint16_t value = ((uint16_t) data[0] << 8) | data[1]; - printf("Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value); - return value; + uint8_t *data = packet->data + packet->offs; + packet->size += sizeof(uint16_t); + packet->offs += sizeof(uint16_t); + uint16_t value = ((uint16_t) data[0] << 8) | data[1]; + printf("Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value); + return value; } // uint32_t PacketRead32(Packet *packet) { - uint8_t *data = packet->data + packet->offs; - packet->size += sizeof(uint32_t); - packet->offs += sizeof(uint32_t); - uint32_t value = ((uint32_t) data[0] << 24) | ((uint32_t) data[1] << 16) | ((uint32_t) data[2] << 8) | data[3]; - printf("Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value); - return value; + uint8_t *data = packet->data + packet->offs; + packet->size += sizeof(uint32_t); + packet->offs += sizeof(uint32_t); + uint32_t value = ((uint32_t) data[0] << 24) | ((uint32_t) data[1] << 16) | ((uint32_t) data[2] << 8) | data[3]; + printf("Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value); + return value; } // uint64_t PacketRead64(Packet *packet) { - uint8_t *data = packet->data + packet->offs; - packet->size += sizeof(uint64_t); - packet->offs += sizeof(uint64_t); - uint64_t value = ((uint64_t) data[0] << 56) | ((uint64_t) data[1] << 48) | ((uint64_t) data[2] << 40) | ((uint64_t) data[3] << 32) | ((uint64_t) data[4] << 24) | ((uint64_t) data[5] << 16) | ((uint64_t) data[6] << 8) | data[7]; - printf("Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value); - return value; + uint8_t *data = packet->data + packet->offs; + packet->size += sizeof(uint64_t); + packet->offs += sizeof(uint64_t); + uint64_t value = ((uint64_t) data[0] << 56) | ((uint64_t) data[1] << 48) | ((uint64_t) data[2] << 40) | ((uint64_t) data[3] << 32) | ((uint64_t) data[4] << 24) | ((uint64_t) data[5] << 16) | ((uint64_t) data[6] << 8) | data[7]; + printf("Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value); + return value; } diff --git a/src/rnet.h b/src/rnet.h index f5dde220d..6dbcb9253 100644 --- a/src/rnet.h +++ b/src/rnet.h @@ -78,15 +78,15 @@ #define NOMSG // typedef MSG and associated routines #define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* #define NOSCROLL // SB_* and scrolling routines -#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. -#define NOSOUND // Sound driver routines -#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines -#define NOWH // SetWindowsHook and WH_* -#define NOWINOFFSETS // GWL_*, GCL_*, associated routines -#define NOCOMM // COMM driver routines -#define NOKANJI // Kanji support stuff. -#define NOHELP // Help engine interface. -#define NOPROFILER // Profiler interface. +#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. +#define NOSOUND // Sound driver routines +#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines +#define NOWH // SetWindowsHook and WH_* +#define NOWINOFFSETS // GWL_*, GCL_*, associated routines +#define NOCOMM // COMM driver routines +#define NOKANJI // Kanji support stuff. +#define NOHELP // Help engine interface. +#define NOPROFILER // Profiler interface. #define NODEFERWINDOWPOS // DeferWindowPos routines #define NOMCX // Modem Configuration Extensions #define MMNOSOUND @@ -101,21 +101,21 @@ typedef int socklen_t; #endif #ifndef RESULT_SUCCESS -# define RESULT_SUCCESS 0 +# define RESULT_SUCCESS 0 #endif // RESULT_SUCCESS #ifndef RESULT_FAILURE -# define RESULT_FAILURE 1 +# define RESULT_FAILURE 1 #endif // RESULT_FAILURE #ifndef htonll -# ifdef _BIG_ENDIAN -# define htonll(x) (x) -# define ntohll(x) (x) -# else -# define htonll(x) ((((uint64) htonl(x)) << 32) + htonl(x >> 32)) -# define ntohll(x) ((((uint64) ntohl(x)) << 32) + ntohl(x >> 32)) -# endif // _BIG_ENDIAN +# ifdef _BIG_ENDIAN +# define htonll(x) (x) +# define ntohll(x) (x) +# else +# define htonll(x) ((((uint64) htonl(x)) << 32) + htonl(x >> 32)) +# define ntohll(x) ((((uint64) ntohl(x)) << 32) + ntohl(x >> 32)) +# endif // _BIG_ENDIAN #endif // htonll //---------------------------------------------------------------------------------- @@ -124,44 +124,42 @@ typedef int socklen_t; //---------------------------------------------------------------------------------- // Include system network headers - #if defined(_WIN32) -# pragma comment(lib, "ws2_32.lib") -# define __USE_W32_SOCKETS -# define WIN32_LEAN_AND_MEAN -# include -# include -# include -# define IPTOS_LOWDELAY 0x10 -#else /* UNIX */ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif /* WIN32 */ + #define __USE_W32_SOCKETS + #define WIN32_LEAN_AND_MEAN + #include + #include + #include + #define IPTOS_LOWDELAY 0x10 +#else // Unix + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif #ifndef INVALID_SOCKET -# define INVALID_SOCKET ~(0) + #define INVALID_SOCKET ~(0) #endif #ifndef __USE_W32_SOCKETS -# define closesocket close -# define SOCKET int -# define INVALID_SOCKET -1 -# define SOCKET_ERROR -1 + #define closesocket close + #define SOCKET int + #define INVALID_SOCKET -1 + #define SOCKET_ERROR -1 #endif #ifdef __USE_W32_SOCKETS -# ifndef EINTR -# define EINTR WSAEINTR -# endif + #ifndef EINTR + #define EINTR WSAEINTR + #endif #endif //---------------------------------------------------------------------------------- @@ -171,9 +169,9 @@ typedef int socklen_t; // Network connection related defines #define SOCKET_MAX_SET_SIZE (32) // Maximum sockets in a set #define SOCKET_MAX_QUEUE_SIZE (16) // Maximum socket queue size -#define SOCKET_MAX_SOCK_OPTS (4) // Maximum socket options -#define SOCKET_MAX_UDPCHANNELS (32) // Maximum UDP channels -#define SOCKET_MAX_UDPADDRESSES (4) // Maximum bound UDP addresses +#define SOCKET_MAX_SOCK_OPTS (4) // Maximum socket options +#define SOCKET_MAX_UDPCHANNELS (32) // Maximum UDP channels +#define SOCKET_MAX_UDPADDRESSES (4) // Maximum bound UDP addresses // Network address related defines @@ -231,97 +229,87 @@ typedef int socklen_t; #endif // Network typedefs -typedef uint32_t SocketChannel; -typedef struct _AddressInformation * AddressInformation; -typedef struct _SocketAddress * SocketAddress; -typedef struct _SocketAddressIPv4 * SocketAddressIPv4; -typedef struct _SocketAddressIPv6 * SocketAddressIPv6; +typedef uint32_t SocketChannel; +typedef struct _AddressInformation *AddressInformation; +typedef struct _SocketAddress *SocketAddress; +typedef struct _SocketAddressIPv4 *SocketAddressIPv4; +typedef struct _SocketAddressIPv6 *SocketAddressIPv6; typedef struct _SocketAddressStorage *SocketAddressStorage; // IPAddress definition (in network byte order) -typedef struct IPAddress -{ - unsigned long host; /* 32-bit IPv4 host address */ - unsigned short port; /* 16-bit protocol port */ +typedef struct IPAddress { + unsigned long host; /* 32-bit IPv4 host address */ + unsigned short port; /* 16-bit protocol port */ } IPAddress; // An option ID, value, sizeof(value) tuple for setsockopt(2). -typedef struct SocketOpt -{ - int id; - void *value; - int valueLen; +typedef struct SocketOpt { + int id; + void *value; + int valueLen; } SocketOpt; -typedef enum -{ - SOCKET_TCP = 0, // SOCK_STREAM - SOCKET_UDP = 1 // SOCK_DGRAM +typedef enum { + SOCKET_TCP = 0, // SOCK_STREAM + SOCKET_UDP = 1 // SOCK_DGRAM } SocketType; -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 +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 -{ - 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) - SocketChannel channel; // The socket handle id - SocketType type; // Is this socket a TCP or UDP socket? - 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) +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) + SocketChannel channel; // The socket handle id + SocketType type; // Is this socket a TCP or UDP socket? + 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 + struct UDPChannel binding[SOCKET_MAX_UDPCHANNELS]; // The amount of channels (if UDP) this socket is bound to } Socket; -typedef struct SocketSet -{ - int numsockets; - int maxsockets; - struct Socket **sockets; +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. -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]; +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 -{ - int status; - Socket *socket; +typedef struct SocketResult { + int status; + Socket *socket; } SocketResult; // Packet type -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 +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 } Packet;