Comments and examples
This commit is contained in:
parent
97d01fe36d
commit
bde0b6cd75
|
|
@ -37,9 +37,9 @@ int main()
|
||||||
InitNetwork();
|
InitNetwork();
|
||||||
|
|
||||||
AddressInformation addr;
|
AddressInformation addr;
|
||||||
ResolveHost(&addr, "www.google.com", NULL, SOCKET_TCP);
|
ResolveHost("www.google.com", "80", &addr);
|
||||||
ResolveIP("8.8.8.8", NULL);
|
// ResolveIP("8.8.8.8", NULL, NAME_INFO_DEFAULT);
|
||||||
ResolveIP("2001:4860:4860::8888", "80");
|
// ResolveIP("2001:4860:4860::8888", "80", NAME_INFO_NUMERICSERV);
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
while (!WindowShouldClose())
|
while (!WindowShouldClose())
|
||||||
|
|
|
||||||
56
src/raylib.h
56
src/raylib.h
|
|
@ -100,13 +100,19 @@
|
||||||
// Network limits
|
// Network limits
|
||||||
#define MAX_SOCKET_SET_SIZE 32
|
#define MAX_SOCKET_SET_SIZE 32
|
||||||
#define MAX_SOCKET_QUEUE_SIZE 16
|
#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
|
#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)
|
// NOTE: MSC C++ compiler does not support compound literals (C99 feature)
|
||||||
// Plain structures in C++ (without constructors) can be initialized from { } initializers.
|
// Plain structures in C++ (without constructors) can be initialized from { } initializers.
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
@ -437,6 +443,7 @@ typedef struct IPAddress
|
||||||
unsigned char* port; /* 16-bit protocol port */
|
unsigned char* port; /* 16-bit protocol port */
|
||||||
} IPAddress;
|
} IPAddress;
|
||||||
|
|
||||||
|
// Used by the getaddrinfo function to hold host address information.
|
||||||
typedef struct AddressInformation
|
typedef struct AddressInformation
|
||||||
{
|
{
|
||||||
int flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
|
int flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
|
||||||
|
|
@ -449,31 +456,35 @@ typedef struct AddressInformation
|
||||||
struct AddressInformation *next; // Next structure in linked list
|
struct AddressInformation *next; // Next structure in linked list
|
||||||
} AddressInformation;
|
} 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
|
typedef struct SocketAddress
|
||||||
{
|
{
|
||||||
unsigned short family; // Address family.
|
unsigned short family; // Address family.
|
||||||
char data[14]; // Up to 14 bytes of direct address.
|
char data[14]; // Up to 14 bytes of direct address.
|
||||||
} SocketAddress;
|
} SocketAddress;
|
||||||
|
|
||||||
/* An option ID, value, sizeof(value) tuple for setsockopt(2). */
|
// An option ID, value, sizeof(value) tuple for setsockopt(2).
|
||||||
typedef struct SocketOpt {
|
typedef struct SocketOpt {
|
||||||
int option_id;
|
int id;
|
||||||
void *value;
|
void *value;
|
||||||
int value_len;
|
int valueLen;
|
||||||
} SocketOpt;
|
} SocketOpt;
|
||||||
|
|
||||||
typedef struct Socket
|
typedef struct Socket
|
||||||
{
|
{
|
||||||
int ready;
|
int ready; // Is the socket ready? i.e. has information
|
||||||
SocketHandle handle;
|
SocketHandle handle; // The socket handle id
|
||||||
IPAddress remoteAddress;
|
IPAddress host; // The host/target ip for this socket
|
||||||
IPAddress localAddress;
|
int sflag; // Is this socket a server socket (i.e. TCP/UDP Listen Server)
|
||||||
int sflag;
|
|
||||||
} Socket;
|
} Socket;
|
||||||
|
|
||||||
/* Configuration for a socket. Not all of these fields need to
|
// Configuration for a socket. Not all of these fields need to
|
||||||
* be set, and ones omitted from a C99-style "designated initializer"
|
// be set, and ones omitted from a C99-style "designated initializer"
|
||||||
* struct literal will be zeroed out and replaced with defaults. */
|
// struct literal will be zeroed out and replaced with defaults.
|
||||||
typedef struct SocketConfig {
|
typedef struct SocketConfig {
|
||||||
/* Hostname and port, for TCP or UDP sockets. */
|
/* Hostname and port, for TCP or UDP sockets. */
|
||||||
char *host;
|
char *host;
|
||||||
|
|
@ -488,7 +499,7 @@ typedef struct SocketConfig {
|
||||||
char *IPv6;
|
char *IPv6;
|
||||||
|
|
||||||
bool server; /* Listen for incoming clients? */
|
bool server; /* Listen for incoming clients? */
|
||||||
bool datagram; /* UDP or datagram Unix domain? */
|
bool datagram; /* UDP or datagram? */
|
||||||
bool nonblocking; /* non-blocking operation? */
|
bool nonblocking; /* non-blocking operation? */
|
||||||
|
|
||||||
int backlog_size; /* set a custom backlog size */
|
int backlog_size; /* set a custom backlog size */
|
||||||
|
|
@ -1510,12 +1521,15 @@ RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pit
|
||||||
// Network (Module: network)
|
// Network (Module: network)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Initialisation and cleanup
|
||||||
RLAPI bool InitNetwork(void);
|
RLAPI bool InitNetwork(void);
|
||||||
RLAPI void CloseNetwork(void);
|
RLAPI void CloseNetwork(void);
|
||||||
|
|
||||||
// Resolution
|
// Protocol-independent name resolution from an address to an ANSI host name and from a port number to the ANSI service name.
|
||||||
RLAPI void ResolveHost(AddressInformation *outaddr, const char *address, const char *port, SocketType socketType);
|
RLAPI char* ResolveIP(const char *host, const char *port, int flags);
|
||||||
RLAPI char *ResolveIP(const char *host, const char *port);
|
|
||||||
|
// Protocol-independent translation from an ANSI host name to an address.
|
||||||
|
RLAPI char* ResolveHost(const char *address, const char *port, AddressInformation *outaddr);
|
||||||
|
|
||||||
// IP
|
// IP
|
||||||
RLAPI void GetLocalAddresses();
|
RLAPI void GetLocalAddresses();
|
||||||
|
|
@ -1530,7 +1544,7 @@ RLAPI int SocketGetError(char *buf, int buf_size, SocketResult *res);
|
||||||
RLAPI void SocketPrintError(SocketResult *res);
|
RLAPI void SocketPrintError(SocketResult *res);
|
||||||
RLAPI void SocketSetHints(SocketConfig *cfg, AddressInformation *hints);
|
RLAPI void SocketSetHints(SocketConfig *cfg, AddressInformation *hints);
|
||||||
|
|
||||||
// Print methods
|
// Utility print methods
|
||||||
RLAPI char *SocketAddressToString(SocketAddress *sockaddr, char buffer[]);
|
RLAPI char *SocketAddressToString(SocketAddress *sockaddr, char buffer[]);
|
||||||
RLAPI void PrintSocket(SocketAddress *addr, const int family, const int socktype, const int protocol);
|
RLAPI void PrintSocket(SocketAddress *addr, const int family, const int socktype, const int protocol);
|
||||||
|
|
||||||
|
|
|
||||||
476
src/rnet.c
476
src/rnet.c
|
|
@ -62,15 +62,15 @@
|
||||||
#define DEF_BACKLOG_SIZE SOMAXCONN
|
#define DEF_BACKLOG_SIZE SOMAXCONN
|
||||||
#define PORT_STR_BUFSZ 6
|
#define PORT_STR_BUFSZ 6
|
||||||
|
|
||||||
static bool SocketSetDefaults(SocketConfig *cfg);
|
static bool SocketSetDefaults(SocketConfig* cfg);
|
||||||
static bool CreateSocket(SocketConfig *cfg, SocketResult *out);
|
static bool CreateSocket(SocketConfig* cfg, SocketResult* out);
|
||||||
static bool SocketSetNonBlocking(SocketResult *out);
|
static bool SocketSetNonBlocking(SocketResult* out);
|
||||||
static bool SocketSetOptions(SocketConfig *cfg,
|
static bool SocketSetOptions(SocketConfig* cfg, SocketResult* out, int fd);
|
||||||
SocketResult *out, int fd);
|
static const char* SocketStatusToString(enum SocketStatus s);
|
||||||
static const char *SocketStatusToString(enum SocketStatus s);
|
|
||||||
|
|
||||||
/* Static network API methods */
|
/* Static network API methods */
|
||||||
|
|
||||||
|
// Sets the error code that can be retrieved through the WSAGetLastError function.
|
||||||
static void SocketSetError(int err)
|
static void SocketSetError(int err)
|
||||||
{
|
{
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
|
|
@ -80,6 +80,7 @@ static void SocketSetError(int err)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the error status for the last Sockets operation that failed
|
||||||
static int SocketGetLastError()
|
static int SocketGetLastError()
|
||||||
{
|
{
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
|
|
@ -89,47 +90,58 @@ static int SocketGetLastError()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SocketSetDefaults(SocketConfig *cfg)
|
// Returns a human-readable string representing the last error message
|
||||||
|
static char* SocketGetLastErrorString()
|
||||||
{
|
{
|
||||||
if (cfg->backlog_size == 0) { cfg->backlog_size = DEF_BACKLOG_SIZE; }
|
return gai_strerror(SocketGetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool SocketSetDefaults(SocketConfig* cfg)
|
||||||
|
{
|
||||||
|
if (cfg->backlog_size == 0)
|
||||||
|
{
|
||||||
|
cfg->backlog_size = DEF_BACKLOG_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Screen out contradictory settings */
|
/* Screen out contradictory settings */
|
||||||
if (cfg->IPv6 && cfg->IPv4) { return false; }
|
if (cfg->IPv6 && cfg->IPv4)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SocketStatusToError(SocketResult *out, enum SocketStatus status)
|
static bool SocketSaveError(SocketResult* out, enum SocketStatus status)
|
||||||
{
|
{
|
||||||
out->status = status;
|
out->status = status;
|
||||||
out->saved_errno = SocketGetLastError();
|
out->saved_errno = SocketGetLastError();
|
||||||
SocketSetError(0);
|
SocketSetError(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
static bool CreateSocket(SocketConfig* cfg, SocketResult* out)
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *res = NULL;
|
struct addrinfo* res = NULL;
|
||||||
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
char port_str[PORT_STR_BUFSZ];
|
char port_str[PORT_STR_BUFSZ];
|
||||||
memset(port_str, 0, PORT_STR_BUFSZ);
|
memset(port_str, 0, PORT_STR_BUFSZ);
|
||||||
|
|
||||||
SocketSetHints(cfg, &hints);
|
SocketSetHints(cfg, &hints);
|
||||||
|
|
||||||
if (PORT_STR_BUFSZ < snprintf(port_str, PORT_STR_BUFSZ,
|
if (PORT_STR_BUFSZ < snprintf(port_str, PORT_STR_BUFSZ, "%u", cfg->port))
|
||||||
"%u", cfg->port))
|
|
||||||
{
|
{
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_SNPRINTF);
|
return SocketSaveError(out, SOCKET_ERROR_SNPRINTF);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct addrinfo *ai = NULL;
|
struct addrinfo* ai = NULL;
|
||||||
int addr_res = getaddrinfo(cfg->host, port_str, &hints, &res);
|
int addr_res = getaddrinfo(cfg->host, port_str, &hints, &res);
|
||||||
if (addr_res != 0)
|
if (addr_res != 0)
|
||||||
{
|
{
|
||||||
out->getaddrinfo_error = addr_res;
|
out->getaddrinfo_error = addr_res;
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_GETADDRINFO);
|
return SocketSaveError(out, SOCKET_ERROR_GETADDRINFO);
|
||||||
}
|
}
|
||||||
memcpy(&out->addrinfo, res, sizeof(struct addrinfo));
|
memcpy(&out->addrinfo, res, sizeof(struct addrinfo));
|
||||||
|
|
||||||
|
|
@ -139,7 +151,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
/* Save errno, but will be clobbered if others succeed. */
|
/* Save errno, but will be clobbered if others succeed. */
|
||||||
out->status = SOCKET_ERROR_SOCKET;
|
out->status = SOCKET_ERROR_SOCKET;
|
||||||
out->saved_errno = SocketGetLastError();
|
out->saved_errno = SocketGetLastError();
|
||||||
SocketSetError(0);
|
SocketSetError(0);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -157,7 +169,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||||
if (bind_res == -1)
|
if (bind_res == -1)
|
||||||
{
|
{
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_BIND);
|
return SocketSaveError(out, SOCKET_ERROR_BIND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg->datagram)
|
if (!cfg->datagram)
|
||||||
|
|
@ -166,14 +178,17 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||||
if (listen_res == -1)
|
if (listen_res == -1)
|
||||||
{
|
{
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_LISTEN);
|
return SocketSaveError(out, SOCKET_ERROR_LISTEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else /* client */
|
else /* client */
|
||||||
{
|
{
|
||||||
if (cfg->datagram) { break; }
|
if (cfg->datagram)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int connect_res = connect(fd, ai->ai_addr, ai->ai_addrlen);
|
int connect_res = connect(fd, ai->ai_addr, ai->ai_addrlen);
|
||||||
if (connect_res == 0)
|
if (connect_res == 0)
|
||||||
|
|
@ -183,7 +198,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
out->status = SOCKET_ERROR_CONNECT;
|
out->status = SOCKET_ERROR_CONNECT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +210,7 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||||
if (out->status == SOCKET_OK)
|
if (out->status == SOCKET_OK)
|
||||||
{
|
{
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_UNKNOWN);
|
return SocketSaveError(out, SOCKET_ERROR_UNKNOWN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -208,56 +223,57 @@ static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||||
|
|
||||||
out->status = SOCKET_OK;
|
out->status = SOCKET_OK;
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
out->saved_errno = 0;
|
out->saved_errno = 0;
|
||||||
out->socket.handle = fd;
|
out->socket.handle = fd;
|
||||||
out->socket.ready = 0;
|
out->socket.ready = 0;
|
||||||
out->socket.remoteAddress.host = ((struct sockaddr_in*)res->ai_addr)->sin_addr.s_addr;
|
out->socket.host.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.port = ((struct sockaddr_in*) res->ai_addr)->sin_port;
|
||||||
out->socket.sflag = cfg->server;
|
out->socket.sflag = cfg->server;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SocketSetNonBlocking(SocketResult *out)
|
static bool SocketSetNonBlocking(SocketResult* out)
|
||||||
{
|
{
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
unsigned long mode = 1;
|
unsigned long mode = 1;
|
||||||
if (ioctlsocket(out->socket.handle, FIONBIO, &mode) != 0)
|
if (ioctlsocket(out->socket.handle, FIONBIO, &mode) != 0)
|
||||||
{
|
{
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_FCNTL);
|
return SocketSaveError(out, SOCKET_ERROR_FCNTL);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int flags = fcntl(out->socket.handle, F_GETFL, 0);
|
int flags = fcntl(out->socket.handle, F_GETFL, 0);
|
||||||
if (flags == -1)
|
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)
|
if (fcntl(out->socket, F_SETFL, flags | O_NONBLOCK) < 0)
|
||||||
{
|
{
|
||||||
return SocketStatusToError(out, SOCKET_ERROR_FCNTL);
|
return SocketSaveError(out, SOCKET_ERROR_FCNTL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SocketSetOptions(SocketConfig *cfg,
|
static bool SocketSetOptions(SocketConfig* cfg, SocketResult* out, int fd)
|
||||||
SocketResult *out, int fd)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_SOCK_OPTS; i++)
|
for (int i = 0; i < MAX_SOCK_OPTS; i++)
|
||||||
{
|
{
|
||||||
SocketOpt *opt = &cfg->sockopts[i];
|
SocketOpt* opt = &cfg->sockopts[i];
|
||||||
if (opt->option_id == 0) { break; }
|
if (opt->id == 0)
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, opt->option_id,
|
|
||||||
opt->value, opt->value_len) < 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *SocketStatusToString(enum SocketStatus s)
|
static const char* SocketStatusToString(enum SocketStatus s)
|
||||||
{
|
{
|
||||||
switch (s)
|
switch (s)
|
||||||
{
|
{
|
||||||
|
|
@ -291,25 +307,43 @@ static const char *SocketStatusToString(enum SocketStatus s)
|
||||||
// Module implementation
|
// Module implementation
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialise the network (requires for windows platforms only)
|
// Initialise the network (requires for windows platforms only)
|
||||||
bool InitNetwork()
|
bool InitNetwork()
|
||||||
{
|
{
|
||||||
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
|
WORD wVersionRequested;
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR)
|
int err;
|
||||||
{
|
|
||||||
TraceLog(LOG_INFO, "WinSock initialised.");
|
wVersionRequested = MAKEWORD(2, 2);
|
||||||
return true;
|
err = WSAStartup(wVersionRequested, &wsaData);
|
||||||
}
|
if (err != 0)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
TraceLog(LOG_WARNING, "WinSock failed to initialise.");
|
TraceLog(LOG_WARNING, "WinSock failed to initialise.");
|
||||||
return false;
|
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
|
// Cleanup, and close the network
|
||||||
void CloseNetwork()
|
void CloseNetwork()
|
||||||
{
|
{
|
||||||
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
if (WSACleanup() == SOCKET_ERROR)
|
if (WSACleanup() == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
if (WSAGetLastError() == WSAEINPROGRESS)
|
if (WSAGetLastError() == WSAEINPROGRESS)
|
||||||
|
|
@ -318,16 +352,29 @@ void CloseNetwork()
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the hostname
|
// Protocol-independent name resolution from an address to an ANSI host name
|
||||||
char* ResolveIP(const char* ip, const char* port)
|
// 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
|
// Variables
|
||||||
char host[MAX_HOST_NAME_SIZE];
|
char host[NI_MAXHOST];
|
||||||
char service[NI_MAXSERV];
|
char service[NI_MAXSERV];
|
||||||
int status; // Status value to return (0) is success
|
int status; // Status value to return (0) is success
|
||||||
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
|
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
|
||||||
struct addrinfo* results; // A pointer to the resulting address list
|
struct addrinfo* results; // A pointer to the resulting address list
|
||||||
|
|
||||||
// Zero out the host buffer
|
// Zero out the host buffer
|
||||||
|
|
@ -337,13 +384,12 @@ char* ResolveIP(const char* ip, const char* port)
|
||||||
// Set the hints
|
// Set the hints
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
|
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)
|
hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
|
||||||
|
|
||||||
// Populate address information
|
// Populate address information
|
||||||
status = getaddrinfo(ip, // e.g. "www.example.com" or IP
|
status = getaddrinfo(ip, // e.g. "www.example.com" or IP
|
||||||
port, // e.g. "http" or port number
|
port, // e.g. "http" or port number
|
||||||
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM
|
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM
|
||||||
&results // The struct to populate
|
&results // The struct to populate
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -361,22 +407,22 @@ char* ResolveIP(const char* ip, const char* port)
|
||||||
switch (results->ai_family)
|
switch (results->ai_family)
|
||||||
{
|
{
|
||||||
case AF_INET:
|
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)),
|
sizeof(*((struct sockaddr_in*) results->ai_addr)),
|
||||||
host,
|
host,
|
||||||
sizeof(host),
|
sizeof(host),
|
||||||
NULL,
|
service,
|
||||||
NULL,
|
NI_MAXSERV,
|
||||||
0);
|
flags);
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
status = getnameinfo(&*((struct sockaddr_in6*) results->ai_addr),
|
status = getnameinfo(&*((struct sockaddr_in6*) results->ai_addr),
|
||||||
sizeof(*((struct sockaddr_in6*) results->ai_addr)),
|
sizeof(*((struct sockaddr_in6*) results->ai_addr)),
|
||||||
host,
|
host,
|
||||||
sizeof(host),
|
sizeof(host),
|
||||||
NULL,
|
service,
|
||||||
NULL,
|
NI_MAXSERV,
|
||||||
0);
|
flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -385,7 +431,7 @@ char* ResolveIP(const char* ip, const char* port)
|
||||||
// Did we succeed?
|
// Did we succeed?
|
||||||
if (status != 0)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -399,18 +445,22 @@ char* ResolveIP(const char* ip, const char* port)
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get address information
|
// Protocol-independent translation from an ANSI host name to an address
|
||||||
void ResolveHost(AddressInformation* outaddr, const char* address, const char* port, SocketType socketType)
|
//
|
||||||
|
// 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
|
// Variables
|
||||||
int status; // Status value to return (0) is success
|
int status; // Status value to return (0) is success
|
||||||
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
|
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
|
||||||
struct addrinfo* results; // A pointer to the resulting address list
|
struct addrinfo* results; // A pointer to the resulting address list
|
||||||
|
|
||||||
// Set the hints
|
// Set the hints
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
|
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)
|
hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
|
||||||
|
|
||||||
// When the address is NULL, populate the IP for me
|
// When the address is NULL, populate the IP for me
|
||||||
|
|
@ -421,8 +471,8 @@ void ResolveHost(AddressInformation* outaddr, const char* address, const char* p
|
||||||
|
|
||||||
// Populate address information
|
// Populate address information
|
||||||
status = getaddrinfo(address, // e.g. "www.example.com" or IP
|
status = getaddrinfo(address, // e.g. "www.example.com" or IP
|
||||||
port, // e.g. "http" or port number
|
port, // e.g. "http" or port number
|
||||||
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM
|
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM
|
||||||
&results // The struct to populate
|
&results // The struct to populate
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -442,7 +492,7 @@ void ResolveHost(AddressInformation* outaddr, const char* address, const char* p
|
||||||
for (iterator = outaddr; iterator != NULL; iterator = iterator->ai_next)
|
for (iterator = outaddr; iterator != NULL; iterator = iterator->ai_next)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_DEBUG, "GetAddressInformation");
|
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,
|
PrintSocket(iterator->ai_addr,
|
||||||
iterator->ai_family,
|
iterator->ai_family,
|
||||||
iterator->ai_socktype,
|
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);
|
TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Free the pointer to the data returned by addrinfo
|
||||||
freeaddrinfo(results);
|
freeaddrinfo(results);
|
||||||
|
|
||||||
|
// Return the resulting hostname
|
||||||
|
return SocketAddressToString(outaddr->ai_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to open a socket, according to the configuration stored in
|
// This here is the bread and butter of the socket API, This function will
|
||||||
* CFG. Returns whether the the socket opened; further details will be
|
// attempt to open a socket, bind and listen to it based on the config passed in
|
||||||
* stored in RES. */
|
//
|
||||||
bool SocketOpen(SocketConfig *cfg, SocketResult *res)
|
// 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; }
|
if (config == NULL || result == NULL)
|
||||||
memset(res, 0, sizeof(*res));
|
|
||||||
|
|
||||||
if (!SocketSetDefaults(cfg))
|
|
||||||
{
|
{
|
||||||
res->status = SOCKET_ERROR_CONFIGURATION;
|
return false;
|
||||||
|
}
|
||||||
|
memset(result, 0, sizeof(*result));
|
||||||
|
|
||||||
|
if (!SocketSetDefaults(config))
|
||||||
|
{
|
||||||
|
result->status = SOCKET_ERROR_CONFIGURATION;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateSocket(cfg, res)) { return false; }
|
if (!CreateSocket(config, result))
|
||||||
|
|
||||||
if (cfg->nonblocking)
|
|
||||||
{
|
{
|
||||||
if (!SocketSetNonBlocking(res)) { return false; }
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->nonblocking)
|
||||||
|
{
|
||||||
|
if (!SocketSetNonBlocking(result))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a network socket */
|
// Closes an existing socket
|
||||||
|
//
|
||||||
|
// SocketHandle socket - The id of the socket to close
|
||||||
void SocketClose(SocketHandle socket)
|
void SocketClose(SocketHandle socket)
|
||||||
{
|
{
|
||||||
if (socket)
|
if (socket)
|
||||||
|
|
@ -487,27 +563,25 @@ void SocketClose(SocketHandle socket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accept an incoming connection on the given server socket.
|
// The accept function permits an incoming connection attempt on a socket.
|
||||||
The newly created socket is returned, or NULL if there was an error.
|
//
|
||||||
*/
|
|
||||||
bool SocketAccept(SocketHandle listener, SocketResult* out)
|
bool SocketAccept(SocketHandle listener, SocketResult* out)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sock_addr;
|
struct sockaddr_in sock_addr;
|
||||||
socklen_t sock_alen;
|
socklen_t sock_alen;
|
||||||
sock_alen = sizeof(sock_addr);
|
sock_alen = sizeof(sock_addr);
|
||||||
out->socket.handle = accept(listener, (struct sockaddr *)&sock_addr,
|
out->socket.handle = accept(listener, (struct sockaddr*) &sock_addr, &sock_alen);
|
||||||
&sock_alen);
|
|
||||||
if (out->socket.handle == INVALID_SOCKET)
|
if (out->socket.handle == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
/* Save errno, but will be clobbered if others succeed. */
|
/* Save errno, but will be clobbered if others succeed. */
|
||||||
out->status = SOCKET_ERROR_ACCEPT;
|
out->status = SOCKET_ERROR_ACCEPT;
|
||||||
out->saved_errno = SocketGetLastError();
|
out->saved_errno = SocketGetLastError();
|
||||||
SocketSetError(0);
|
SocketSetError(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(&out->addrinfo, &sock_addr, sizeof(struct sockaddr));
|
memcpy(&out->addrinfo, &sock_addr, sizeof(struct sockaddr));
|
||||||
out->socket.remoteAddress.host = sock_addr.sin_addr.s_addr;
|
out->socket.host.host = sock_addr.sin_addr.s_addr;
|
||||||
out->socket.remoteAddress.port = sock_addr.sin_port;
|
out->socket.host.port = sock_addr.sin_port;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -517,10 +591,10 @@ bool SocketAccept(SocketHandle listener, SocketResult* out)
|
||||||
is less than the amount of data sent, then either the remote connection was
|
is less than the amount of data sent, then either the remote connection was
|
||||||
closed, or an unknown socket error occurred.
|
closed, or an unknown socket error occurred.
|
||||||
*/
|
*/
|
||||||
int SocketSend(Socket* socket, const void *datap, int len)
|
int SocketSend(Socket* socket, const void* datap, int len)
|
||||||
{
|
{
|
||||||
const unsigned char *data = (const unsigned char *)datap; /* For pointer arithmetic */
|
const unsigned char* data = (const unsigned char*) datap; /* For pointer arithmetic */
|
||||||
int sent, left;
|
int sent, left;
|
||||||
|
|
||||||
// /* Server sockets are for accepting connections only */
|
// /* Server sockets are for accepting connections only */
|
||||||
if (socket->sflag)
|
if (socket->sflag)
|
||||||
|
|
@ -528,7 +602,7 @@ int SocketSend(Socket* socket, const void *datap, int len)
|
||||||
// out->status = SOCKET_ERROR_SEND;
|
// out->status = SOCKET_ERROR_SEND;
|
||||||
// out->saved_errno = SocketGetLastError();
|
// out->saved_errno = SocketGetLastError();
|
||||||
// SocketSetError(0);
|
// SocketSetError(0);
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep sending data until it's sent or an error occurs */
|
/* Keep sending data until it's sent or an error occurs */
|
||||||
|
|
@ -537,17 +611,16 @@ int SocketSend(Socket* socket, const void *datap, int len)
|
||||||
SocketSetError(0);
|
SocketSetError(0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
len = send(socket->handle, (const char *)data, left, 0);
|
len = send(socket->handle, (const char*) data, left, 0);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
sent += len;
|
sent += len;
|
||||||
left -= len;
|
left -= len;
|
||||||
data += len;
|
data += len;
|
||||||
}
|
}
|
||||||
}
|
} while ((left > 0) && ((len > 0) || (SocketGetLastError() == EINTR)));
|
||||||
while ((left > 0) && ((len > 0) || (SocketGetLastError() == EINTR)));
|
|
||||||
|
|
||||||
return(sent);
|
return (sent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
|
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
|
||||||
|
|
@ -556,7 +629,7 @@ int SocketSend(Socket* socket, const void *datap, int len)
|
||||||
value is less than or equal to zero, then either the remote connection was
|
value is less than or equal to zero, then either the remote connection was
|
||||||
closed, or an unknown socket error occurred.
|
closed, or an unknown socket error occurred.
|
||||||
*/
|
*/
|
||||||
int SocketReceive(Socket* socket, void *data, int maxlen)
|
int SocketReceive(Socket* socket, void* data, int maxlen)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
|
@ -566,48 +639,49 @@ int SocketReceive(Socket* socket, void *data, int maxlen)
|
||||||
// out->status = SOCKET_ERROR_RECEIVE;
|
// out->status = SOCKET_ERROR_RECEIVE;
|
||||||
// out->saved_errno = SocketGetLastError();
|
// out->saved_errno = SocketGetLastError();
|
||||||
// SocketSetError(0);
|
// SocketSetError(0);
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketSetError(0);
|
SocketSetError(0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
len = recv(socket->handle, (char *)data, maxlen, 0);
|
len = recv(socket->handle, (char*) data, maxlen, 0);
|
||||||
}
|
} while (SocketGetLastError() == EINTR);
|
||||||
while (SocketGetLastError() == EINTR);
|
|
||||||
|
|
||||||
// sock->ready = 0;
|
// sock->ready = 0;
|
||||||
return(len);
|
return (len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct an error message in BUF, based on the status codes
|
/* Construct an error message in BUF, based on the status codes
|
||||||
* in *RES. This has the same return value and general behavior
|
* in *RES. This has the same return value and general behavior
|
||||||
* as snprintf -- if the return value is >= buf_size, the string
|
* as snprintf -- if the return value is >= buf_size, the string
|
||||||
* has been truncated. Returns -1 if either BUF or RES are NULL. */
|
* has been truncated. Returns -1 if either BUF or RES are NULL. */
|
||||||
int SocketGetError(char *buf, size_t buf_size, SocketResult *res)
|
int SocketGetError(char* buf, size_t buf_size, SocketResult* res)
|
||||||
{
|
{
|
||||||
if (buf == NULL || res == NULL) { return 0; }
|
if (buf == NULL || res == NULL)
|
||||||
return snprintf(buf, buf_size, "%s: %ls",
|
{
|
||||||
SocketStatusToString(res->status),
|
return 0;
|
||||||
(res->status == SOCKET_ERROR_GETADDRINFO
|
}
|
||||||
? gai_strerror(res->getaddrinfo_error)
|
return snprintf(buf, buf_size, "%s: %ls", SocketStatusToString(res->status), (res->status == SOCKET_ERROR_GETADDRINFO ? gai_strerror(res->getaddrinfo_error) : strerror(res->saved_errno)));
|
||||||
: strerror(res->saved_errno)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print an error message based on the status contained in *RES. */
|
/* Print an error message based on the status contained in *RES. */
|
||||||
void SocketPrintError(SocketResult *res)
|
void SocketPrintError(SocketResult* res)
|
||||||
{
|
{
|
||||||
if (res == NULL) { return; }
|
if (res == NULL)
|
||||||
printf("%s: %ls\n", SocketStatusToString(res->status),
|
{
|
||||||
(res->status == SOCKET_ERROR_GETADDRINFO
|
return;
|
||||||
? gai_strerror(res->getaddrinfo_error)
|
}
|
||||||
: strerror(res->saved_errno)));
|
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. */
|
/* Set "hints" in an addrinfo struct, to be passed to getaddrinfo. */
|
||||||
void SocketSetHints(SocketConfig *cfg, struct addrinfo *hints)
|
void SocketSetHints(SocketConfig* cfg, struct addrinfo* hints)
|
||||||
{
|
{
|
||||||
if (cfg == NULL || hints == NULL) { return; }
|
if (cfg == NULL || hints == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
memset(hints, 0, sizeof(*hints));
|
memset(hints, 0, sizeof(*hints));
|
||||||
|
|
||||||
/* if .IPv4 or .IPv6 are used, set and use that instead of *host */
|
/* if .IPv4 or .IPv6 are used, set and use that instead of *host */
|
||||||
|
|
@ -657,72 +731,72 @@ void PrintSocket(struct SocketAddress* addr, const int family, const int socktyp
|
||||||
switch (family)
|
switch (family)
|
||||||
{
|
{
|
||||||
case AF_UNSPEC:
|
case AF_UNSPEC:
|
||||||
{
|
{
|
||||||
TraceLog(LOG_DEBUG, "Family: Unspecified");
|
TraceLog(LOG_DEBUG, "\tFamily: Unspecified");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
{
|
{
|
||||||
TraceLog(LOG_DEBUG, "Family: AF_INET (IPv4)");
|
TraceLog(LOG_DEBUG, "\tFamily: AF_INET (IPv4)");
|
||||||
TraceLog(LOG_INFO, "- IPv4 address %s", SocketAddressToString(addr, ip));
|
TraceLog(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr, ip));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
{
|
{
|
||||||
TraceLog(LOG_DEBUG, "Family: AF_INET6 (IPv6)");
|
TraceLog(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)");
|
||||||
TraceLog(LOG_INFO, "- IPv6 address %s", SocketAddressToString(addr, ip));
|
TraceLog(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr, ip));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AF_NETBIOS:
|
case AF_NETBIOS:
|
||||||
{
|
{
|
||||||
TraceLog(LOG_DEBUG, "Family: AF_NETBIOS (NetBIOS)");
|
TraceLog(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
TraceLog(LOG_DEBUG, "Family: Other %ld", family);
|
TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TraceLog(LOG_DEBUG, "Socket type:");
|
TraceLog(LOG_DEBUG, "\tSocket type:");
|
||||||
switch (socktype)
|
switch (socktype)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
TraceLog(LOG_DEBUG, "- Unspecified");
|
TraceLog(LOG_DEBUG, "\t- Unspecified");
|
||||||
break;
|
break;
|
||||||
case SOCK_STREAM:
|
case SOCK_STREAM:
|
||||||
TraceLog(LOG_DEBUG, "- SOCK_STREAM (stream)");
|
TraceLog(LOG_DEBUG, "\t- SOCK_STREAM (stream)");
|
||||||
break;
|
break;
|
||||||
case SOCK_DGRAM:
|
case SOCK_DGRAM:
|
||||||
TraceLog(LOG_DEBUG, "- SOCK_DGRAM (datagram)");
|
TraceLog(LOG_DEBUG, "\t- SOCK_DGRAM (datagram)");
|
||||||
break;
|
break;
|
||||||
case SOCK_RAW:
|
case SOCK_RAW:
|
||||||
TraceLog(LOG_DEBUG, "- SOCK_RAW (raw)");
|
TraceLog(LOG_DEBUG, "\t- SOCK_RAW (raw)");
|
||||||
break;
|
break;
|
||||||
case SOCK_RDM:
|
case SOCK_RDM:
|
||||||
TraceLog(LOG_DEBUG, "- SOCK_RDM (reliable message datagram)");
|
TraceLog(LOG_DEBUG, "\t- SOCK_RDM (reliable message datagram)");
|
||||||
break;
|
break;
|
||||||
case SOCK_SEQPACKET:
|
case SOCK_SEQPACKET:
|
||||||
TraceLog(LOG_DEBUG, "- SOCK_SEQPACKET (pseudo-stream packet)");
|
TraceLog(LOG_DEBUG, "\t- SOCK_SEQPACKET (pseudo-stream packet)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TraceLog(LOG_DEBUG, "- Other %ld", socktype);
|
TraceLog(LOG_DEBUG, "\t- Other %ld", socktype);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TraceLog(LOG_DEBUG, "Protocol:");
|
TraceLog(LOG_DEBUG, "\tProtocol:");
|
||||||
switch (protocol)
|
switch (protocol)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
TraceLog(LOG_DEBUG, "- Unspecified");
|
TraceLog(LOG_DEBUG, "\t- Unspecified");
|
||||||
break;
|
break;
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
TraceLog(LOG_DEBUG, "- IPPROTO_TCP (TCP)");
|
TraceLog(LOG_DEBUG, "\t- IPPROTO_TCP (TCP)");
|
||||||
break;
|
break;
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
TraceLog(LOG_DEBUG, "- IPPROTO_UDP (UDP)");
|
TraceLog(LOG_DEBUG, "\t- IPPROTO_UDP (UDP)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TraceLog(LOG_DEBUG, "- Other %ld", protocol);
|
TraceLog(LOG_DEBUG, "\t- Other %ld", protocol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -733,20 +807,20 @@ char* SocketAddressToString(struct SocketAddress* sockaddr, char buffer[])
|
||||||
switch (sockaddr->family)
|
switch (sockaddr->family)
|
||||||
{
|
{
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
{
|
{
|
||||||
return inet_ntop(AF_INET, &((struct sockaddr_in*) sockaddr)->sin_addr, buffer, INET_ADDRSTRLEN);
|
return inet_ntop(AF_INET, &((struct sockaddr_in*) sockaddr)->sin_addr, buffer, INET_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
{
|
{
|
||||||
return inet_ntop(AF_INET6, &((struct sockaddr_in6*) sockaddr)->sin6_addr, buffer, INET6_ADDRSTRLEN);
|
return inet_ntop(AF_INET6, &((struct sockaddr_in6*) sockaddr)->sin6_addr, buffer, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -797,13 +871,13 @@ unsigned int PackData(unsigned char* buf, char* format, ...)
|
||||||
{
|
{
|
||||||
case 'c': // 8-bit
|
case 'c': // 8-bit
|
||||||
size += 1;
|
size += 1;
|
||||||
c = (signed char)va_arg(ap, int); // promoted
|
c = (signed char) va_arg(ap, int); // promoted
|
||||||
*buf++ = c;
|
*buf++ = c;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C': // 8-bit unsigned
|
case 'C': // 8-bit unsigned
|
||||||
size += 1;
|
size += 1;
|
||||||
C = (unsigned char)va_arg(ap, unsigned int); // promoted
|
C = (unsigned char) va_arg(ap, unsigned int); // promoted
|
||||||
*buf++ = C;
|
*buf++ = C;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -851,15 +925,15 @@ unsigned int PackData(unsigned char* buf, char* format, ...)
|
||||||
|
|
||||||
case 'f': // float-16
|
case 'f': // float-16
|
||||||
size += 2;
|
size += 2;
|
||||||
f = (float)va_arg(ap, double); // promoted
|
f = (float) va_arg(ap, double); // promoted
|
||||||
fhold = pack754_16(f); // convert to IEEE 754
|
fhold = pack754_16(f); // convert to IEEE 754
|
||||||
packi16(buf, fhold);
|
packi16(buf, fhold);
|
||||||
buf += 2;
|
buf += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': // float-32
|
case 'd': // float-32
|
||||||
size += 4;
|
size += 4;
|
||||||
d = va_arg(ap, double);
|
d = va_arg(ap, double);
|
||||||
fhold = pack754_32(d); // convert to IEEE 754
|
fhold = pack754_32(d); // convert to IEEE 754
|
||||||
packi32(buf, fhold);
|
packi32(buf, fhold);
|
||||||
buf += 4;
|
buf += 4;
|
||||||
|
|
@ -867,14 +941,14 @@ unsigned int PackData(unsigned char* buf, char* format, ...)
|
||||||
|
|
||||||
case 'g': // float-64
|
case 'g': // float-64
|
||||||
size += 8;
|
size += 8;
|
||||||
g = va_arg(ap, long double);
|
g = va_arg(ap, long double);
|
||||||
fhold = pack754_64(g); // convert to IEEE 754
|
fhold = pack754_64(g); // convert to IEEE 754
|
||||||
packi64(buf, fhold);
|
packi64(buf, fhold);
|
||||||
buf += 8;
|
buf += 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's': // string
|
case 's': // string
|
||||||
s = va_arg(ap, char*);
|
s = va_arg(ap, char*);
|
||||||
len = strlen(s);
|
len = strlen(s);
|
||||||
size += len + 2;
|
size += len + 2;
|
||||||
packi16(buf, len);
|
packi16(buf, len);
|
||||||
|
|
@ -942,75 +1016,75 @@ void UnpackData(unsigned char* buf, char* format, ...)
|
||||||
} // re-sign
|
} // re-sign
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*c = -1 - (unsigned char)(0xffu - *buf);
|
*c = -1 - (unsigned char) (0xffu - *buf);
|
||||||
}
|
}
|
||||||
buf++;
|
buf++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C': // 8-bit unsigned
|
case 'C': // 8-bit unsigned
|
||||||
C = va_arg(ap, unsigned char*);
|
C = va_arg(ap, unsigned char*);
|
||||||
*C = *buf++;
|
*C = *buf++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h': // 16-bit
|
case 'h': // 16-bit
|
||||||
h = va_arg(ap, int*);
|
h = va_arg(ap, int*);
|
||||||
*h = unpacki16(buf);
|
*h = unpacki16(buf);
|
||||||
buf += 2;
|
buf += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'H': // 16-bit unsigned
|
case 'H': // 16-bit unsigned
|
||||||
H = va_arg(ap, unsigned int*);
|
H = va_arg(ap, unsigned int*);
|
||||||
*H = unpacku16(buf);
|
*H = unpacku16(buf);
|
||||||
buf += 2;
|
buf += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l': // 32-bit
|
case 'l': // 32-bit
|
||||||
l = va_arg(ap, long int*);
|
l = va_arg(ap, long int*);
|
||||||
*l = unpacki32(buf);
|
*l = unpacki32(buf);
|
||||||
buf += 4;
|
buf += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L': // 32-bit unsigned
|
case 'L': // 32-bit unsigned
|
||||||
L = va_arg(ap, unsigned long int*);
|
L = va_arg(ap, unsigned long int*);
|
||||||
*L = unpacku32(buf);
|
*L = unpacku32(buf);
|
||||||
buf += 4;
|
buf += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q': // 64-bit
|
case 'q': // 64-bit
|
||||||
q = va_arg(ap, long long int*);
|
q = va_arg(ap, long long int*);
|
||||||
*q = unpacki64(buf);
|
*q = unpacki64(buf);
|
||||||
buf += 8;
|
buf += 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Q': // 64-bit unsigned
|
case 'Q': // 64-bit unsigned
|
||||||
Q = va_arg(ap, unsigned long long int*);
|
Q = va_arg(ap, unsigned long long int*);
|
||||||
*Q = unpacku64(buf);
|
*Q = unpacku64(buf);
|
||||||
buf += 8;
|
buf += 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f': // float
|
case 'f': // float
|
||||||
f = va_arg(ap, float*);
|
f = va_arg(ap, float*);
|
||||||
fhold = unpacku16(buf);
|
fhold = unpacku16(buf);
|
||||||
*f = unpack754_16(fhold);
|
*f = unpack754_16(fhold);
|
||||||
buf += 2;
|
buf += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': // float-32
|
case 'd': // float-32
|
||||||
d = va_arg(ap, double*);
|
d = va_arg(ap, double*);
|
||||||
fhold = unpacku32(buf);
|
fhold = unpacku32(buf);
|
||||||
*d = unpack754_32(fhold);
|
*d = unpack754_32(fhold);
|
||||||
buf += 4;
|
buf += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g': // float-64
|
case 'g': // float-64
|
||||||
g = va_arg(ap, long double*);
|
g = va_arg(ap, long double*);
|
||||||
fhold = unpacku64(buf);
|
fhold = unpacku64(buf);
|
||||||
*g = unpack754_64(fhold);
|
*g = unpack754_64(fhold);
|
||||||
buf += 8;
|
buf += 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's': // string
|
case 's': // string
|
||||||
s = va_arg(ap, char*);
|
s = va_arg(ap, char*);
|
||||||
len = unpacku16(buf);
|
len = unpacku16(buf);
|
||||||
buf += 2;
|
buf += 2;
|
||||||
if (maxstrlen > 0 && len > maxstrlen)
|
if (maxstrlen > 0 && len > maxstrlen)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user