Comments and examples

This commit is contained in:
Jak Barnes 2019-02-23 13:51:20 +00:00
parent 97d01fe36d
commit bde0b6cd75
3 changed files with 646 additions and 558 deletions

View File

@ -37,9 +37,9 @@ int main()
InitNetwork();
AddressInformation addr;
ResolveHost(&addr, "www.google.com", NULL, SOCKET_TCP);
ResolveIP("8.8.8.8", NULL);
ResolveIP("2001:4860:4860::8888", "80");
ResolveHost("www.google.com", "80", &addr);
// ResolveIP("8.8.8.8", NULL, NAME_INFO_DEFAULT);
// ResolveIP("2001:4860:4860::8888", "80", NAME_INFO_NUMERICSERV);
// Main game loop
while (!WindowShouldClose())

View File

@ -100,13 +100,19 @@
// Network limits
#define MAX_SOCKET_SET_SIZE 32
#define MAX_SOCKET_QUEUE_SIZE 16
#define MAX_HOST_NAME_SIZE 1025
#define MAX_SERV_NAME_SIZE 32
#define MAX_IPV4_NAME_SIZE 22
#define MAX_IPV6_NAME_SIZE 65
#define MAX_SOCK_OPTS 4
// getnameinfo() defines
#define NAME_INFO_DEFAULT 0x00 /* No flags set */
#define NAME_INFO_NOFQDN 0x01 /* Only return nodename portion for local hosts */
#define NAME_INFO_NUMERICHOST 0x02 /* Return numeric form of the host's address */
#define NAME_INFO_NAMEREQD 0x04 /* Error if the host's name not in DNS */
#define NAME_INFO_NUMERICSERV 0x08 /* Return numeric form of the service (port #) */
#define NAME_INFO_DGRAM 0x10 /* Service is a datagram service */
// NOTE: MSC C++ compiler does not support compound literals (C99 feature)
// Plain structures in C++ (without constructors) can be initialized from { } initializers.
#if defined(__cplusplus)
@ -437,6 +443,7 @@ typedef struct IPAddress
unsigned char* port; /* 16-bit protocol port */
} IPAddress;
// Used by the getaddrinfo function to hold host address information.
typedef struct AddressInformation
{
int flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
@ -449,31 +456,35 @@ typedef struct AddressInformation
struct AddressInformation *next; // Next structure in linked list
} AddressInformation;
// Used
//
// The sockaddr structure varies depending on the protocol selected.
// Except for the sin*_family parameter, sockaddr contents are expressed
// in network byte order.
typedef struct SocketAddress
{
unsigned short family; // Address family.
char data[14]; // Up to 14 bytes of direct address.
} SocketAddress;
/* An option ID, value, sizeof(value) tuple for setsockopt(2). */
// An option ID, value, sizeof(value) tuple for setsockopt(2).
typedef struct SocketOpt {
int option_id;
int id;
void *value;
int value_len;
int valueLen;
} SocketOpt;
typedef struct Socket
{
int ready;
SocketHandle handle;
IPAddress remoteAddress;
IPAddress localAddress;
int sflag;
int ready; // Is the socket ready? i.e. has information
SocketHandle handle; // The socket handle id
IPAddress host; // The host/target ip for this socket
int sflag; // Is this socket a server socket (i.e. TCP/UDP Listen Server)
} Socket;
/* Configuration for a socket. Not all of these fields need to
* be set, and ones omitted from a C99-style "designated initializer"
* struct literal will be zeroed out and replaced with defaults. */
// Configuration for a socket. Not all of these fields need to
// be set, and ones omitted from a C99-style "designated initializer"
// struct literal will be zeroed out and replaced with defaults.
typedef struct SocketConfig {
/* Hostname and port, for TCP or UDP sockets. */
char *host;
@ -488,7 +499,7 @@ typedef struct SocketConfig {
char *IPv6;
bool server; /* Listen for incoming clients? */
bool datagram; /* UDP or datagram Unix domain? */
bool datagram; /* UDP or datagram? */
bool nonblocking; /* non-blocking operation? */
int backlog_size; /* set a custom backlog size */
@ -1510,12 +1521,15 @@ RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pit
// Network (Module: network)
//------------------------------------------------------------------------------------
// Initialisation and cleanup
RLAPI bool InitNetwork(void);
RLAPI void CloseNetwork(void);
// Resolution
RLAPI void ResolveHost(AddressInformation *outaddr, const char *address, const char *port, SocketType socketType);
RLAPI char *ResolveIP(const char *host, const char *port);
// Protocol-independent name resolution from an address to an ANSI host name and from a port number to the ANSI service name.
RLAPI char* ResolveIP(const char *host, const char *port, int flags);
// Protocol-independent translation from an ANSI host name to an address.
RLAPI char* ResolveHost(const char *address, const char *port, AddressInformation *outaddr);
// IP
RLAPI void GetLocalAddresses();
@ -1530,7 +1544,7 @@ RLAPI int SocketGetError(char *buf, int buf_size, SocketResult *res);
RLAPI void SocketPrintError(SocketResult *res);
RLAPI void SocketSetHints(SocketConfig *cfg, AddressInformation *hints);
// Print methods
// Utility print methods
RLAPI char *SocketAddressToString(SocketAddress *sockaddr, char buffer[]);
RLAPI void PrintSocket(SocketAddress *addr, const int family, const int socktype, const int protocol);

View File

@ -65,12 +65,12 @@
static bool SocketSetDefaults(SocketConfig* cfg);
static bool CreateSocket(SocketConfig* cfg, SocketResult* out);
static bool SocketSetNonBlocking(SocketResult* out);
static bool SocketSetOptions(SocketConfig *cfg,
SocketResult *out, int fd);
static bool SocketSetOptions(SocketConfig* cfg, SocketResult* out, int fd);
static const char* SocketStatusToString(enum SocketStatus s);
/* Static network API methods */
// Sets the error code that can be retrieved through the WSAGetLastError function.
static void SocketSetError(int err)
{
#if PLATFORM == PLATFORM_WINDOWS
@ -80,6 +80,7 @@ static void SocketSetError(int err)
#endif
}
// Returns the error status for the last Sockets operation that failed
static int SocketGetLastError()
{
#if PLATFORM == PLATFORM_WINDOWS
@ -89,16 +90,28 @@ static int SocketGetLastError()
#endif
}
// Returns a human-readable string representing the last error message
static char* SocketGetLastErrorString()
{
return gai_strerror(SocketGetLastError());
}
static bool SocketSetDefaults(SocketConfig* cfg)
{
if (cfg->backlog_size == 0) { cfg->backlog_size = DEF_BACKLOG_SIZE; }
if (cfg->backlog_size == 0)
{
cfg->backlog_size = DEF_BACKLOG_SIZE;
}
/* Screen out contradictory settings */
if (cfg->IPv6 && cfg->IPv4) { return false; }
if (cfg->IPv6 && cfg->IPv4)
{
return false;
}
return true;
}
static bool SocketStatusToError(SocketResult *out, enum SocketStatus status)
static bool SocketSaveError(SocketResult* out, enum SocketStatus status)
{
out->status = status;
out->saved_errno = SocketGetLastError();
@ -117,10 +130,9 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
SocketSetHints(cfg, &hints);
if (PORT_STR_BUFSZ < snprintf(port_str, PORT_STR_BUFSZ,
"%u", cfg->port))
if (PORT_STR_BUFSZ < snprintf(port_str, PORT_STR_BUFSZ, "%u", cfg->port))
{
return SocketStatusToError(out, SOCKET_ERROR_SNPRINTF);
return SocketSaveError(out, SOCKET_ERROR_SNPRINTF);
}
struct addrinfo* ai = NULL;
@ -129,7 +141,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
{
out->getaddrinfo_error = addr_res;
freeaddrinfo(res);
return SocketStatusToError(out, SOCKET_ERROR_GETADDRINFO);
return SocketSaveError(out, SOCKET_ERROR_GETADDRINFO);
}
memcpy(&out->addrinfo, res, sizeof(struct addrinfo));
@ -157,7 +169,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
if (bind_res == -1)
{
freeaddrinfo(res);
return SocketStatusToError(out, SOCKET_ERROR_BIND);
return SocketSaveError(out, SOCKET_ERROR_BIND);
}
if (!cfg->datagram)
@ -166,14 +178,17 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
if (listen_res == -1)
{
freeaddrinfo(res);
return SocketStatusToError(out, SOCKET_ERROR_LISTEN);
return SocketSaveError(out, SOCKET_ERROR_LISTEN);
}
}
break;
}
else /* client */
{
if (cfg->datagram) { break; }
if (cfg->datagram)
{
break;
}
int connect_res = connect(fd, ai->ai_addr, ai->ai_addrlen);
if (connect_res == 0)
@ -195,7 +210,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
if (out->status == SOCKET_OK)
{
freeaddrinfo(res);
return SocketStatusToError(out, SOCKET_ERROR_UNKNOWN);
return SocketSaveError(out, SOCKET_ERROR_UNKNOWN);
}
else
{
@ -211,8 +226,8 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
out->saved_errno = 0;
out->socket.handle = fd;
out->socket.ready = 0;
out->socket.remoteAddress.host = ((struct sockaddr_in*)res->ai_addr)->sin_addr.s_addr;
out->socket.remoteAddress.port = ((struct sockaddr_in*)res->ai_addr)->sin_port;
out->socket.host.host = ((struct sockaddr_in*) res->ai_addr)->sin_addr.s_addr;
out->socket.host.port = ((struct sockaddr_in*) res->ai_addr)->sin_port;
out->socket.sflag = cfg->server;
return true;
}
@ -223,34 +238,35 @@ static bool SocketSetNonBlocking(SocketResult *out)
unsigned long mode = 1;
if (ioctlsocket(out->socket.handle, FIONBIO, &mode) != 0)
{
return SocketStatusToError(out, SOCKET_ERROR_FCNTL);
return SocketSaveError(out, SOCKET_ERROR_FCNTL);
}
#else
int flags = fcntl(out->socket.handle, F_GETFL, 0);
if (flags == -1)
{
return SocketStatusToError(out, SOCKET_ERROR_FCNTL);
return SocketSaveError(out, SOCKET_ERROR_FCNTL);
}
if (fcntl(out->socket, F_SETFL, flags | O_NONBLOCK) < 0)
{
return SocketStatusToError(out, SOCKET_ERROR_FCNTL);
return SocketSaveError(out, SOCKET_ERROR_FCNTL);
}
#endif
return true;
}
static bool SocketSetOptions(SocketConfig *cfg,
SocketResult *out, int fd)
static bool SocketSetOptions(SocketConfig* cfg, SocketResult* out, int fd)
{
for (int i = 0; i < MAX_SOCK_OPTS; i++)
{
SocketOpt* opt = &cfg->sockopts[i];
if (opt->option_id == 0) { break; }
if (setsockopt(fd, SOL_SOCKET, opt->option_id,
opt->value, opt->value_len) < 0)
if (opt->id == 0)
{
return SocketStatusToError(out, SOCKET_ERROR_SETSOCKOPT);
break;
}
if (setsockopt(fd, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0)
{
return SocketSaveError(out, SOCKET_ERROR_SETSOCKOPT);
}
}
@ -294,22 +310,40 @@ static const char *SocketStatusToString(enum SocketStatus s)
// Initialise the network (requires for windows platforms only)
bool InitNetwork()
{
#if PLATFORM == PLATFORM_WINDOWS
WORD wVersionRequested;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR)
{
TraceLog(LOG_INFO, "WinSock initialised.");
return true;
}
else
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.");
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
TraceLog(LOG_WARNING, "WinSock failed to initialise.");
WSACleanup();
return false;
}
return true;
#else
return true;
#endif
}
// Cleanup, and close the network
void CloseNetwork()
{
#if PLATFORM == PLATFORM_WINDOWS
if (WSACleanup() == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEINPROGRESS)
@ -318,13 +352,26 @@ void CloseNetwork()
WSACleanup();
}
}
#endif
}
// Resolve the hostname
char* ResolveIP(const char* ip, const char* port)
// 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 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 */
char* ResolveIP(const char* ip, const char* port, int flags)
{
// Variables
char host[MAX_HOST_NAME_SIZE];
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int status; // Status value to return (0) is success
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
@ -337,7 +384,6 @@ char* ResolveIP(const char* ip, const char* port)
// Set the hints
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
hints.ai_socktype = SOCKET_TCP; // TCP (SOCK_STREAM), UDP (SOCK_DGRAM)
hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
// Populate address information
@ -361,22 +407,22 @@ char* ResolveIP(const char* ip, const char* port)
switch (results->ai_family)
{
case AF_INET:
status = getnameinfo(&*((struct sockaddr_in*) results->ai_addr),
status = getnameinfo(&*((struct sockaddr*) results->ai_addr),
sizeof(*((struct sockaddr_in*) results->ai_addr)),
host,
sizeof(host),
NULL,
NULL,
0);
service,
NI_MAXSERV,
flags);
break;
case AF_INET6:
status = getnameinfo(&*((struct sockaddr_in6*) results->ai_addr),
sizeof(*((struct sockaddr_in6*) results->ai_addr)),
host,
sizeof(host),
NULL,
NULL,
0);
service,
NI_MAXSERV,
flags);
break;
default:
break;
@ -385,7 +431,7 @@ char* ResolveIP(const char* ip, const char* port)
// Did we succeed?
if (status != 0)
{
TraceLog(LOG_WARNING, "Failed to resolve ip %s: %ls", ip, gai_strerror(errno));
TraceLog(LOG_WARNING, "Failed to resolve ip %s: %ls", ip, SocketGetLastErrorString());
}
else
{
@ -399,8 +445,13 @@ char* ResolveIP(const char* ip, const char* port)
return host;
}
// Get address information
void ResolveHost(AddressInformation* outaddr, const char* address, const char* port, SocketType socketType)
// 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"
// AddressInformation* outaddr - Results of host resolution (getaddrinfo)
char* ResolveHost(const char* address, const char* port, AddressInformation* outaddr)
{
// Variables
int status; // Status value to return (0) is success
@ -410,7 +461,6 @@ void ResolveHost(AddressInformation* outaddr, const char* address, const char* p
// Set the hints
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
hints.ai_socktype = socketType == SOCKET_TCP ? SOCK_STREAM : SOCK_DGRAM; // TCP (SOCK_STREAM), UDP (SOCK_DGRAM)
hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
// When the address is NULL, populate the IP for me
@ -442,7 +492,7 @@ void ResolveHost(AddressInformation* outaddr, const char* address, const char* p
for (iterator = outaddr; iterator != NULL; iterator = iterator->ai_next)
{
TraceLog(LOG_DEBUG, "GetAddressInformation");
TraceLog(LOG_DEBUG, "Flags: 0x%x", iterator->ai_flags);
TraceLog(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags);
PrintSocket(iterator->ai_addr,
iterator->ai_family,
iterator->ai_socktype,
@ -451,34 +501,60 @@ void ResolveHost(AddressInformation* outaddr, const char* address, const char* p
TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname);
}
// Free the pointer to the data returned by addrinfo
freeaddrinfo(results);
// Return the resulting hostname
return SocketAddressToString(outaddr->ai_addr);
}
/* Attempt to open a socket, according to the configuration stored in
* CFG. Returns whether the the socket opened; further details will be
* stored in RES. */
bool SocketOpen(SocketConfig *cfg, SocketResult *res)
// 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)
//
// e.g.
// SocketConfig server_cfg = { SocketConfig client_cfg = {
// .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 SocketOpen(SocketConfig* config, SocketResult* result)
{
if (cfg == NULL || res == NULL) { return false; }
memset(res, 0, sizeof(*res));
if (config == NULL || result == NULL)
{
return false;
}
memset(result, 0, sizeof(*result));
if (!SocketSetDefaults(cfg))
if (!SocketSetDefaults(config))
{
res->status = SOCKET_ERROR_CONFIGURATION;
result->status = SOCKET_ERROR_CONFIGURATION;
return false;
}
if (!CreateSocket(cfg, res)) { return false; }
if (cfg->nonblocking)
if (!CreateSocket(config, result))
{
if (!SocketSetNonBlocking(res)) { return false; }
return false;
}
if (config->nonblocking)
{
if (!SocketSetNonBlocking(result))
{
return false;
}
}
return true;
}
/* Close a network socket */
// Closes an existing socket
//
// SocketHandle socket - The id of the socket to close
void SocketClose(SocketHandle socket)
{
if (socket)
@ -487,16 +563,14 @@ void SocketClose(SocketHandle socket)
}
}
/* Accept an incoming connection on the given server socket.
The newly created socket is returned, or NULL if there was an error.
*/
// The accept function permits an incoming connection attempt on a socket.
//
bool SocketAccept(SocketHandle listener, SocketResult* out)
{
struct sockaddr_in sock_addr;
socklen_t sock_alen;
sock_alen = sizeof(sock_addr);
out->socket.handle = accept(listener, (struct sockaddr *)&sock_addr,
&sock_alen);
out->socket.handle = accept(listener, (struct sockaddr*) &sock_addr, &sock_alen);
if (out->socket.handle == INVALID_SOCKET)
{
/* Save errno, but will be clobbered if others succeed. */
@ -506,8 +580,8 @@ bool SocketAccept(SocketHandle listener, SocketResult* out)
return false;
}
memcpy(&out->addrinfo, &sock_addr, sizeof(struct sockaddr));
out->socket.remoteAddress.host = sock_addr.sin_addr.s_addr;
out->socket.remoteAddress.port = sock_addr.sin_port;
out->socket.host.host = sock_addr.sin_addr.s_addr;
out->socket.host.port = sock_addr.sin_port;
return true;
}
@ -544,8 +618,7 @@ int SocketSend(Socket* socket, const void *datap, int len)
left -= len;
data += len;
}
}
while ((left > 0) && ((len > 0) || (SocketGetLastError() == EINTR)));
} while ((left > 0) && ((len > 0) || (SocketGetLastError() == EINTR)));
return (sent);
}
@ -573,8 +646,7 @@ int SocketReceive(Socket* socket, void *data, int maxlen)
do
{
len = recv(socket->handle, (char*) data, maxlen, 0);
}
while (SocketGetLastError() == EINTR);
} while (SocketGetLastError() == EINTR);
// sock->ready = 0;
return (len);
@ -586,28 +658,30 @@ int SocketReceive(Socket* socket, void *data, int maxlen)
* has been truncated. Returns -1 if either BUF or RES are NULL. */
int SocketGetError(char* buf, size_t buf_size, SocketResult* res)
{
if (buf == NULL || res == NULL) { return 0; }
return snprintf(buf, buf_size, "%s: %ls",
SocketStatusToString(res->status),
(res->status == SOCKET_ERROR_GETADDRINFO
? gai_strerror(res->getaddrinfo_error)
: strerror(res->saved_errno)));
if (buf == NULL || res == NULL)
{
return 0;
}
return snprintf(buf, buf_size, "%s: %ls", SocketStatusToString(res->status), (res->status == SOCKET_ERROR_GETADDRINFO ? gai_strerror(res->getaddrinfo_error) : strerror(res->saved_errno)));
}
/* Print an error message based on the status contained in *RES. */
void SocketPrintError(SocketResult* res)
{
if (res == NULL) { return; }
printf("%s: %ls\n", SocketStatusToString(res->status),
(res->status == SOCKET_ERROR_GETADDRINFO
? gai_strerror(res->getaddrinfo_error)
: strerror(res->saved_errno)));
if (res == NULL)
{
return;
}
printf("%s: %ls\n", SocketStatusToString(res->status), (res->status == SOCKET_ERROR_GETADDRINFO ? gai_strerror(res->getaddrinfo_error) : strerror(res->saved_errno)));
}
/* Set "hints" in an addrinfo struct, to be passed to getaddrinfo. */
void SocketSetHints(SocketConfig* cfg, struct addrinfo* hints)
{
if (cfg == NULL || hints == NULL) { return; }
if (cfg == NULL || hints == NULL)
{
return;
}
memset(hints, 0, sizeof(*hints));
/* if .IPv4 or .IPv6 are used, set and use that instead of *host */
@ -658,71 +732,71 @@ void PrintSocket(struct SocketAddress* addr, const int family, const int socktyp
{
case AF_UNSPEC:
{
TraceLog(LOG_DEBUG, "Family: Unspecified");
TraceLog(LOG_DEBUG, "\tFamily: Unspecified");
}
break;
case AF_INET:
{
TraceLog(LOG_DEBUG, "Family: AF_INET (IPv4)");
TraceLog(LOG_INFO, "- IPv4 address %s", SocketAddressToString(addr, ip));
TraceLog(LOG_DEBUG, "\tFamily: AF_INET (IPv4)");
TraceLog(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr, ip));
}
break;
case AF_INET6:
{
TraceLog(LOG_DEBUG, "Family: AF_INET6 (IPv6)");
TraceLog(LOG_INFO, "- IPv6 address %s", SocketAddressToString(addr, ip));
TraceLog(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)");
TraceLog(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr, ip));
}
break;
case AF_NETBIOS:
{
TraceLog(LOG_DEBUG, "Family: AF_NETBIOS (NetBIOS)");
TraceLog(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)");
}
break;
default:
{
TraceLog(LOG_DEBUG, "Family: Other %ld", family);
TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family);
}
break;
}
TraceLog(LOG_DEBUG, "Socket type:");
TraceLog(LOG_DEBUG, "\tSocket type:");
switch (socktype)
{
case 0:
TraceLog(LOG_DEBUG, "- Unspecified");
TraceLog(LOG_DEBUG, "\t- Unspecified");
break;
case SOCK_STREAM:
TraceLog(LOG_DEBUG, "- SOCK_STREAM (stream)");
TraceLog(LOG_DEBUG, "\t- SOCK_STREAM (stream)");
break;
case SOCK_DGRAM:
TraceLog(LOG_DEBUG, "- SOCK_DGRAM (datagram)");
TraceLog(LOG_DEBUG, "\t- SOCK_DGRAM (datagram)");
break;
case SOCK_RAW:
TraceLog(LOG_DEBUG, "- SOCK_RAW (raw)");
TraceLog(LOG_DEBUG, "\t- SOCK_RAW (raw)");
break;
case SOCK_RDM:
TraceLog(LOG_DEBUG, "- SOCK_RDM (reliable message datagram)");
TraceLog(LOG_DEBUG, "\t- SOCK_RDM (reliable message datagram)");
break;
case SOCK_SEQPACKET:
TraceLog(LOG_DEBUG, "- SOCK_SEQPACKET (pseudo-stream packet)");
TraceLog(LOG_DEBUG, "\t- SOCK_SEQPACKET (pseudo-stream packet)");
break;
default:
TraceLog(LOG_DEBUG, "- Other %ld", socktype);
TraceLog(LOG_DEBUG, "\t- Other %ld", socktype);
break;
}
TraceLog(LOG_DEBUG, "Protocol:");
TraceLog(LOG_DEBUG, "\tProtocol:");
switch (protocol)
{
case 0:
TraceLog(LOG_DEBUG, "- Unspecified");
TraceLog(LOG_DEBUG, "\t- Unspecified");
break;
case IPPROTO_TCP:
TraceLog(LOG_DEBUG, "- IPPROTO_TCP (TCP)");
TraceLog(LOG_DEBUG, "\t- IPPROTO_TCP (TCP)");
break;
case IPPROTO_UDP:
TraceLog(LOG_DEBUG, "- IPPROTO_UDP (UDP)");
TraceLog(LOG_DEBUG, "\t- IPPROTO_UDP (UDP)");
break;
default:
TraceLog(LOG_DEBUG, "- Other %ld", protocol);
TraceLog(LOG_DEBUG, "\t- Other %ld", protocol);
break;
}
}