Comments and examples
This commit is contained in:
parent
97d01fe36d
commit
bde0b6cd75
|
|
@ -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())
|
||||
|
|
|
|||
56
src/raylib.h
56
src/raylib.h
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
336
src/rnet.c
336
src/rnet.c
|
|
@ -62,15 +62,15 @@
|
|||
#define DEF_BACKLOG_SIZE SOMAXCONN
|
||||
#define PORT_STR_BUFSZ 6
|
||||
|
||||
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 const char *SocketStatusToString(enum SocketStatus s);
|
||||
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 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
|
||||
}
|
||||
|
||||
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 */
|
||||
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();
|
||||
|
|
@ -106,10 +119,10 @@ static bool SocketStatusToError(SocketResult *out, enum SocketStatus status)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool CreateSocket(SocketConfig *cfg, SocketResult *out)
|
||||
static bool CreateSocket(SocketConfig* cfg, SocketResult* out)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo* res = NULL;
|
||||
|
||||
int fd = -1;
|
||||
char port_str[PORT_STR_BUFSZ];
|
||||
|
|
@ -117,19 +130,18 @@ 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;
|
||||
struct addrinfo* ai = NULL;
|
||||
int addr_res = getaddrinfo(cfg->host, port_str, &hints, &res);
|
||||
if (addr_res != 0)
|
||||
{
|
||||
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,53 +226,54 @@ 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;
|
||||
}
|
||||
|
||||
static bool SocketSetNonBlocking(SocketResult *out)
|
||||
static bool SocketSetNonBlocking(SocketResult* out)
|
||||
{
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
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)
|
||||
SocketOpt* opt = &cfg->sockopts[i];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *SocketStatusToString(enum SocketStatus s)
|
||||
static const char* SocketStatusToString(enum SocketStatus s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
|
|
@ -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 (!SocketSetDefaults(cfg))
|
||||
if (config == NULL || result == NULL)
|
||||
{
|
||||
res->status = SOCKET_ERROR_CONFIGURATION;
|
||||
return false;
|
||||
}
|
||||
memset(result, 0, sizeof(*result));
|
||||
|
||||
if (!SocketSetDefaults(config))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -517,9 +591,9 @@ bool SocketAccept(SocketHandle listener, SocketResult* out)
|
|||
is less than the amount of data sent, then either the remote connection was
|
||||
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;
|
||||
|
||||
// /* Server sockets are for accepting connections only */
|
||||
|
|
@ -528,7 +602,7 @@ int SocketSend(Socket* socket, const void *datap, int len)
|
|||
// out->status = SOCKET_ERROR_SEND;
|
||||
// out->saved_errno = SocketGetLastError();
|
||||
// SocketSetError(0);
|
||||
return(-1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
do
|
||||
{
|
||||
len = send(socket->handle, (const char *)data, left, 0);
|
||||
len = send(socket->handle, (const char*) data, left, 0);
|
||||
if (len > 0)
|
||||
{
|
||||
sent += len;
|
||||
left -= 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',
|
||||
|
|
@ -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
|
||||
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;
|
||||
|
||||
|
|
@ -566,48 +639,49 @@ int SocketReceive(Socket* socket, void *data, int maxlen)
|
|||
// out->status = SOCKET_ERROR_RECEIVE;
|
||||
// out->saved_errno = SocketGetLastError();
|
||||
// SocketSetError(0);
|
||||
return(-1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
SocketSetError(0);
|
||||
do
|
||||
{
|
||||
len = recv(socket->handle, (char *)data, maxlen, 0);
|
||||
}
|
||||
while (SocketGetLastError() == EINTR);
|
||||
len = recv(socket->handle, (char*) data, maxlen, 0);
|
||||
} while (SocketGetLastError() == EINTR);
|
||||
|
||||
// sock->ready = 0;
|
||||
return(len);
|
||||
return (len);
|
||||
}
|
||||
|
||||
/* Construct an error message in BUF, based on the status codes
|
||||
* in *RES. This has the same return value and general behavior
|
||||
* as snprintf -- if the return value is >= buf_size, the string
|
||||
* 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; }
|
||||
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)
|
||||
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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -797,13 +871,13 @@ unsigned int PackData(unsigned char* buf, char* format, ...)
|
|||
{
|
||||
case 'c': // 8-bit
|
||||
size += 1;
|
||||
c = (signed char)va_arg(ap, int); // promoted
|
||||
c = (signed char) va_arg(ap, int); // promoted
|
||||
*buf++ = c;
|
||||
break;
|
||||
|
||||
case 'C': // 8-bit unsigned
|
||||
size += 1;
|
||||
C = (unsigned char)va_arg(ap, unsigned int); // promoted
|
||||
C = (unsigned char) va_arg(ap, unsigned int); // promoted
|
||||
*buf++ = C;
|
||||
break;
|
||||
|
||||
|
|
@ -851,7 +925,7 @@ unsigned int PackData(unsigned char* buf, char* format, ...)
|
|||
|
||||
case 'f': // float-16
|
||||
size += 2;
|
||||
f = (float)va_arg(ap, double); // promoted
|
||||
f = (float) va_arg(ap, double); // promoted
|
||||
fhold = pack754_16(f); // convert to IEEE 754
|
||||
packi16(buf, fhold);
|
||||
buf += 2;
|
||||
|
|
@ -942,7 +1016,7 @@ void UnpackData(unsigned char* buf, char* format, ...)
|
|||
} // re-sign
|
||||
else
|
||||
{
|
||||
*c = -1 - (unsigned char)(0xffu - *buf);
|
||||
*c = -1 - (unsigned char) (0xffu - *buf);
|
||||
}
|
||||
buf++;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user