666 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			666 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#pragma once
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <kinc/global.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*! \file socket.h
							 | 
						||
| 
								 | 
							
								    \brief Provides low-level network-communication via UDP or TCP-sockets.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								extern "C" {
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef enum kinc_socket_protocol { KINC_SOCKET_PROTOCOL_UDP, KINC_SOCKET_PROTOCOL_TCP } kinc_socket_protocol_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef enum kinc_socket_family { KINC_SOCKET_FAMILY_IP4, KINC_SOCKET_FAMILY_IP6 } kinc_socket_family_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_MICROSOFT
							 | 
						||
| 
								 | 
							
								#if defined(_WIN64)
							 | 
						||
| 
								 | 
							
								typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#if !defined _W64
							 | 
						||
| 
								 | 
							
								#define _W64
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								typedef UINT_PTR SOCKET;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct kinc_socket {
							 | 
						||
| 
								 | 
							
								#ifdef KINC_MICROSOFT
							 | 
						||
| 
								 | 
							
									SOCKET handle;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									int handle;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									uint32_t host;
							 | 
						||
| 
								 | 
							
									uint32_t port;
							 | 
						||
| 
								 | 
							
									kinc_socket_protocol_t protocol;
							 | 
						||
| 
								 | 
							
									kinc_socket_family_t family;
							 | 
						||
| 
								 | 
							
									bool connected;
							 | 
						||
| 
								 | 
							
								} kinc_socket_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct kinc_socket_options {
							 | 
						||
| 
								 | 
							
									bool non_blocking;
							 | 
						||
| 
								 | 
							
									bool broadcast;
							 | 
						||
| 
								 | 
							
									bool tcp_no_delay;
							 | 
						||
| 
								 | 
							
								} kinc_socket_options_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Initializes a socket-options-object to the default options
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="options">The new default options</param>
							 | 
						||
| 
								 | 
							
								KINC_FUNC void kinc_socket_options_set_defaults(kinc_socket_options_t *options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Initializes a socket-object. To set the host and port use kinc_socket_set.
							 | 
						||
| 
								 | 
							
								/// Host will be localhost
							 | 
						||
| 
								 | 
							
								/// Port will be 8080
							 | 
						||
| 
								 | 
							
								/// Family will be IPv4
							 | 
						||
| 
								 | 
							
								/// Protocol will be TCP
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="socket">The socket to initialize</param>
							 | 
						||
| 
								 | 
							
								KINC_FUNC void kinc_socket_init(kinc_socket_t *socket);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Sets the sockets properties.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="socket">The socket-object to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="host">The host to use as IP or URL</param>
							 | 
						||
| 
								 | 
							
								/// <param name="port">The port to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="family">The IP-family to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="protocol">The protocol to use</param>
							 | 
						||
| 
								 | 
							
								/// <returns>Whether the socket was set correctly</returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_set(kinc_socket_t *socket, const char *host, int port, kinc_socket_family_t family, kinc_socket_protocol_t protocol);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Destroys a socket-object.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="socket">The socket to destroy</param>
							 | 
						||
| 
								 | 
							
								KINC_FUNC void kinc_socket_destroy(kinc_socket_t *socket);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Opens a socket-connection.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="socket">The socket-object to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="protocol">The protocol to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="port">The port to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="options">The options to use</param>
							 | 
						||
| 
								 | 
							
								/// <returns>Whether the socket-connection could be opened</returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_open(kinc_socket_t *socket, kinc_socket_options_t *options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// For use with non-blocking sockets to try to see if we are connected.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="socket">The socket-object to use</param>
							 | 
						||
| 
								 | 
							
								/// <param name="waittime">The amount of time in seconds the select function will timeout.</param>
							 | 
						||
| 
								 | 
							
								/// <param name="read">Check if the socket is ready to be read from.</param>
							 | 
						||
| 
								 | 
							
								/// <param name="write">Check if the socket is ready to be written to.</param>
							 | 
						||
| 
								 | 
							
								/// <returns>Whether the socket-connection can read or write or checks both.</returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_select(kinc_socket_t *socket, uint32_t waittime, bool read, bool write);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*Typically these are server actions.*/
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_bind(kinc_socket_t *socket);
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_listen(kinc_socket_t *socket, int backlog);
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_accept(kinc_socket_t *socket, kinc_socket_t *new_socket, unsigned *remote_address, unsigned *remote_port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*Typically this is a client action.*/
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_connect(kinc_socket_t *socket);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KINC_FUNC int kinc_socket_send(kinc_socket_t *socket, const uint8_t *data, int size);
							 | 
						||
| 
								 | 
							
								KINC_FUNC int kinc_socket_send_address(kinc_socket_t *socket, unsigned address, int port, const uint8_t *data, int size);
							 | 
						||
| 
								 | 
							
								KINC_FUNC int kinc_socket_send_url(kinc_socket_t *socket, const char *url, int port, const uint8_t *data, int size);
							 | 
						||
| 
								 | 
							
								KINC_FUNC int kinc_socket_receive(kinc_socket_t *socket, uint8_t *data, int maxSize, unsigned *from_address, unsigned *from_port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Resolves a DNS-entry to an IP and returns its integer representation.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="url"></param>
							 | 
						||
| 
								 | 
							
								/// <param name="port"></param>
							 | 
						||
| 
								 | 
							
								/// <returns></returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC unsigned kinc_url_to_int(const char *url, int port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_IMPLEMENTATION_NETWORK
							 | 
						||
| 
								 | 
							
								#define KINC_IMPLEMENTATION
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_IMPLEMENTATION
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef KINC_IMPLEMENTATION
							 | 
						||
| 
								 | 
							
								#include <kinc/libs/stb_sprintf.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/log.h>
							 | 
						||
| 
								 | 
							
								#define KINC_IMPLEMENTATION
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <errno.h>
							 | 
						||
| 
								 | 
							
								#include <stdbool.h>
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Windows 7
							 | 
						||
| 
								 | 
							
								#define WINVER 0x0601
							 | 
						||
| 
								 | 
							
								#define _WIN32_WINNT 0x0601
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define NOATOM
							 | 
						||
| 
								 | 
							
								#define NOCLIPBOARD
							 | 
						||
| 
								 | 
							
								#define NOCOLOR
							 | 
						||
| 
								 | 
							
								#define NOCOMM
							 | 
						||
| 
								 | 
							
								#define NOCTLMGR
							 | 
						||
| 
								 | 
							
								#define NODEFERWINDOWPOS
							 | 
						||
| 
								 | 
							
								#define NODRAWTEXT
							 | 
						||
| 
								 | 
							
								#define NOGDI
							 | 
						||
| 
								 | 
							
								#define NOGDICAPMASKS
							 | 
						||
| 
								 | 
							
								#define NOHELP
							 | 
						||
| 
								 | 
							
								#define NOICONS
							 | 
						||
| 
								 | 
							
								#define NOKANJI
							 | 
						||
| 
								 | 
							
								#define NOKEYSTATES
							 | 
						||
| 
								 | 
							
								#define NOMB
							 | 
						||
| 
								 | 
							
								#define NOMCX
							 | 
						||
| 
								 | 
							
								#define NOMEMMGR
							 | 
						||
| 
								 | 
							
								#define NOMENUS
							 | 
						||
| 
								 | 
							
								#define NOMETAFILE
							 | 
						||
| 
								 | 
							
								#define NOMINMAX
							 | 
						||
| 
								 | 
							
								#define NOMSG
							 | 
						||
| 
								 | 
							
								#define NONLS
							 | 
						||
| 
								 | 
							
								#define NOOPENFILE
							 | 
						||
| 
								 | 
							
								#define NOPROFILER
							 | 
						||
| 
								 | 
							
								#define NORASTEROPS
							 | 
						||
| 
								 | 
							
								#define NOSCROLL
							 | 
						||
| 
								 | 
							
								#define NOSERVICE
							 | 
						||
| 
								 | 
							
								#define NOSHOWWINDOW
							 | 
						||
| 
								 | 
							
								#define NOSOUND
							 | 
						||
| 
								 | 
							
								#define NOSYSCOMMANDS
							 | 
						||
| 
								 | 
							
								#define NOSYSMETRICS
							 | 
						||
| 
								 | 
							
								#define NOTEXTMETRIC
							 | 
						||
| 
								 | 
							
								#define NOUSER
							 | 
						||
| 
								 | 
							
								#define NOVIRTUALKEYCODES
							 | 
						||
| 
								 | 
							
								#define NOWH
							 | 
						||
| 
								 | 
							
								#define NOWINMESSAGES
							 | 
						||
| 
								 | 
							
								#define NOWINOFFSETS
							 | 
						||
| 
								 | 
							
								#define NOWINSTYLES
							 | 
						||
| 
								 | 
							
								#define WIN32_LEAN_AND_MEAN
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <Ws2tcpip.h>
							 | 
						||
| 
								 | 
							
								#include <winsock2.h>
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_POSIX) || defined(KINC_EMSCRIPTEN)
							 | 
						||
| 
								 | 
							
								#include <arpa/inet.h> // for inet_addr()
							 | 
						||
| 
								 | 
							
								#include <ctype.h>
							 | 
						||
| 
								 | 
							
								#include <fcntl.h>
							 | 
						||
| 
								 | 
							
								#include <netdb.h>
							 | 
						||
| 
								 | 
							
								#include <netinet/in.h>
							 | 
						||
| 
								 | 
							
								#include <netinet/tcp.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								#include <sys/socket.h>
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(KINC_EMSCRIPTEN)
							 | 
						||
| 
								 | 
							
								#include <emscripten.h>
							 | 
						||
| 
								 | 
							
								#include <emscripten/posix_socket.h>
							 | 
						||
| 
								 | 
							
								#include <emscripten/threading.h>
							 | 
						||
| 
								 | 
							
								#include <emscripten/websocket.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static EMSCRIPTEN_WEBSOCKET_T bridgeSocket = 0;
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
								#include <sys/select.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int counter = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
								// Important: Must be cleaned with freeaddrinfo(address) later if the result is 0 in order to prevent memory leaks
							 | 
						||
| 
								 | 
							
								static int resolveAddress(const char *url, int port, struct addrinfo **result) {
							 | 
						||
| 
								 | 
							
									struct addrinfo hints = {0};
							 | 
						||
| 
								 | 
							
									hints.ai_family = AF_INET;
							 | 
						||
| 
								 | 
							
									hints.ai_socktype = SOCK_DGRAM;
							 | 
						||
| 
								 | 
							
									hints.ai_protocol = IPPROTO_UDP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									char serv[6];
							 | 
						||
| 
								 | 
							
									sprintf(serv, "%u", port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return getaddrinfo(url, serv, &hints, result);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KINC_FUNC bool kinc_socket_bind(kinc_socket_t *sock) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									struct sockaddr_in address;
							 | 
						||
| 
								 | 
							
									address.sin_family = sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6;
							 | 
						||
| 
								 | 
							
									address.sin_addr.s_addr = sock->host;
							 | 
						||
| 
								 | 
							
									address.sin_port = sock->port;
							 | 
						||
| 
								 | 
							
									if (bind(sock->handle, (const struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Could not bind socket: %s", strerror(errno));
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KINC_FUNC void kinc_socket_options_set_defaults(kinc_socket_options_t *options) {
							 | 
						||
| 
								 | 
							
									options->non_blocking = true;
							 | 
						||
| 
								 | 
							
									options->broadcast = false;
							 | 
						||
| 
								 | 
							
									options->tcp_no_delay = false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_socket_init(kinc_socket_t *sock) {
							 | 
						||
| 
								 | 
							
									sock->handle = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									sock->host = INADDR_ANY;
							 | 
						||
| 
								 | 
							
									sock->port = htons((unsigned short)8080);
							 | 
						||
| 
								 | 
							
									sock->protocol = KINC_SOCKET_PROTOCOL_TCP;
							 | 
						||
| 
								 | 
							
									sock->family = KINC_SOCKET_FAMILY_IP4;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									sock->connected = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									if (counter == 0) {
							 | 
						||
| 
								 | 
							
										WSADATA WsaData;
							 | 
						||
| 
								 | 
							
										WSAStartup(MAKEWORD(2, 2), &WsaData);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#if defined(KINC_EMSCRIPTEN)
							 | 
						||
| 
								 | 
							
									if (!bridgeSocket) {
							 | 
						||
| 
								 | 
							
										bridgeSocket = emscripten_init_websocket_to_posix_socket_bridge("ws://localhost:8080");
							 | 
						||
| 
								 | 
							
										// Synchronously wait until connection has been established.
							 | 
						||
| 
								 | 
							
										uint16_t readyState = 0;
							 | 
						||
| 
								 | 
							
										do {
							 | 
						||
| 
								 | 
							
											emscripten_websocket_get_ready_state(bridgeSocket, &readyState);
							 | 
						||
| 
								 | 
							
											emscripten_thread_sleep(100);
							 | 
						||
| 
								 | 
							
										} while (readyState == 0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									++counter;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_socket_open(kinc_socket_t *sock, struct kinc_socket_options *options) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									switch (sock->protocol) {
							 | 
						||
| 
								 | 
							
									case KINC_SOCKET_PROTOCOL_UDP:
							 | 
						||
| 
								 | 
							
										sock->handle = socket(sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case KINC_SOCKET_PROTOCOL_TCP:
							 | 
						||
| 
								 | 
							
										sock->handle = socket(sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6, SOCK_STREAM, IPPROTO_TCP);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Unsupported socket protocol.");
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (sock->handle <= 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Could not create socket.");
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
										int errorCode = WSAGetLastError();
							 | 
						||
| 
								 | 
							
										switch (errorCode) {
							 | 
						||
| 
								 | 
							
										case (WSANOTINITIALISED):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "A successful WSAStartup call must occur before using this function.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAENETDOWN):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "The network subsystem or the associated service provider has failed.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEAFNOSUPPORT):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR,
							 | 
						||
| 
								 | 
							
											         "The specified address family is not supported.For example, an application tried to create a socket for the AF_IRDA address "
							 | 
						||
| 
								 | 
							
											         "family but an infrared adapter and device driver is not installed on the local computer.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEINPROGRESS):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR,
							 | 
						||
| 
								 | 
							
											         "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEMFILE):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "No more socket descriptors are available.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEINVAL):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR,
							 | 
						||
| 
								 | 
							
											         "An invalid argument was supplied.This error is returned if the af parameter is set to AF_UNSPEC and the type and protocol "
							 | 
						||
| 
								 | 
							
											         "parameter are unspecified.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAENOBUFS):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "No buffer space is available.The socket cannot be created.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEPROTONOSUPPORT):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "The specified protocol is not supported.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEPROTOTYPE):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "The specified protocol is the wrong type for this socket.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEPROVIDERFAILEDINIT):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR,
							 | 
						||
| 
								 | 
							
											         "The service provider failed to initialize.This error is returned if a layered service provider(LSP) or namespace provider was "
							 | 
						||
| 
								 | 
							
											         "improperly installed or the provider fails to operate correctly.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAESOCKTNOSUPPORT):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "The specified socket type is not supported in this address family.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEINVALIDPROVIDER):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "The service provider returned a version other than 2.2.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case (WSAEINVALIDPROCTABLE):
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "The service provider returned an invalid or incomplete procedure table to the WSPStartup.");
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										default:
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Unknown error.");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_POSIX) && !defined(KINC_EMSCRIPTEN)
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "%s", strerror(errno));
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (options) {
							 | 
						||
| 
								 | 
							
										if (options->non_blocking) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
											DWORD value = 1;
							 | 
						||
| 
								 | 
							
											if (ioctlsocket(sock->handle, FIONBIO, &value) != 0) {
							 | 
						||
| 
								 | 
							
												kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set non-blocking mode.");
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
											int value = 1;
							 | 
						||
| 
								 | 
							
											if (fcntl(sock->handle, F_SETFL, O_NONBLOCK, value) == -1) {
							 | 
						||
| 
								 | 
							
												kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set non-blocking mode.");
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (options->broadcast) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
											int value = 1;
							 | 
						||
| 
								 | 
							
											if (setsockopt(sock->handle, SOL_SOCKET, SO_BROADCAST, (const char *)&value, sizeof(value)) < 0) {
							 | 
						||
| 
								 | 
							
												kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set broadcast mode.");
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (options->tcp_no_delay) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
											int value = 1;
							 | 
						||
| 
								 | 
							
											if (setsockopt(sock->handle, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(value)) != 0) {
							 | 
						||
| 
								 | 
							
												kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set no-delay mode.");
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_socket_destroy(kinc_socket_t *sock) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									closesocket(sock->handle);
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									close(sock->handle);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memset(sock, 0, sizeof(kinc_socket_t));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									--counter;
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									if (counter == 0) {
							 | 
						||
| 
								 | 
							
										WSACleanup();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_socket_select(kinc_socket_t *sock, uint32_t waittime, bool read, bool write) {
							 | 
						||
| 
								 | 
							
								#if !defined(KINC_EMSCRIPTEN) && (defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX))
							 | 
						||
| 
								 | 
							
									fd_set r_fds, w_fds;
							 | 
						||
| 
								 | 
							
									struct timeval timeout;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									FD_ZERO(&r_fds);
							 | 
						||
| 
								 | 
							
									FD_ZERO(&w_fds);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									FD_SET(sock->handle, &r_fds);
							 | 
						||
| 
								 | 
							
									FD_SET(sock->handle, &w_fds);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									timeout.tv_sec = waittime;
							 | 
						||
| 
								 | 
							
									timeout.tv_usec = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (select(0, &r_fds, &w_fds, NULL, &timeout) < 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "kinc_socket_select didn't work: %s", strerror(errno));
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (read && write) {
							 | 
						||
| 
								 | 
							
										return FD_ISSET(sock->handle, &w_fds) && FD_ISSET(sock->handle, &r_fds);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if (read) {
							 | 
						||
| 
								 | 
							
										return FD_ISSET(sock->handle, &r_fds);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if (write) {
							 | 
						||
| 
								 | 
							
										return FD_ISSET(sock->handle, &w_fds);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Calling kinc_socket_select with both read and write set to false is useless.");
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_socket_set(kinc_socket_t *sock, const char *host, int port, kinc_socket_family_t family, kinc_socket_protocol_t protocol) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									sock->family = family;
							 | 
						||
| 
								 | 
							
									sock->protocol = protocol;
							 | 
						||
| 
								 | 
							
									sock->port = htons((unsigned short)port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (host == NULL)
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (isdigit(host[0]) || (family == KINC_SOCKET_FAMILY_IP6 && host[4] == ':')) { // Is IPv4 or IPv6 string
							 | 
						||
| 
								 | 
							
										struct in_addr addr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (inet_pton(sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6, host, &addr) == 0) {
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Invalid %s address: %s\n", sock->family == KINC_SOCKET_FAMILY_IP4 ? "IPv4" : "IPv6", host);
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										sock->host = addr.s_addr;
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										struct addrinfo *address = NULL;
							 | 
						||
| 
								 | 
							
										int res = resolveAddress(host, port, &address);
							 | 
						||
| 
								 | 
							
										if (res != 0) {
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Could not resolve address.");
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#if defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
										sock->host = ((struct sockaddr_in *)address->ai_addr)->sin_addr.s_addr;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										sock->host = ((struct sockaddr_in *)address->ai_addr)->sin_addr.S_un.S_addr;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										freeaddrinfo(address);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_socket_listen(kinc_socket_t *socket, int backlog) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									int res = listen(socket->handle, backlog);
							 | 
						||
| 
								 | 
							
									return (res == 0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_socket_accept(kinc_socket_t *sock, kinc_socket_t *newSocket, unsigned *remoteAddress, unsigned *remotePort) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									typedef int socklen_t;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									struct sockaddr_in addr;
							 | 
						||
| 
								 | 
							
									socklen_t addrLength = sizeof(addr);
							 | 
						||
| 
								 | 
							
									newSocket->handle = accept(sock->handle, (struct sockaddr *)&addr, &addrLength);
							 | 
						||
| 
								 | 
							
									if (newSocket->handle <= 0) {
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									newSocket->connected = sock->connected = true;
							 | 
						||
| 
								 | 
							
									newSocket->host = addr.sin_addr.s_addr;
							 | 
						||
| 
								 | 
							
									newSocket->port = addr.sin_port;
							 | 
						||
| 
								 | 
							
									newSocket->family = sock->family;
							 | 
						||
| 
								 | 
							
									newSocket->protocol = sock->protocol;
							 | 
						||
| 
								 | 
							
									*remoteAddress = ntohl(addr.sin_addr.s_addr);
							 | 
						||
| 
								 | 
							
									*remotePort = ntohs(addr.sin_port);
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_socket_connect(kinc_socket_t *sock) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									struct sockaddr_in addr;
							 | 
						||
| 
								 | 
							
									addr.sin_family = sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6;
							 | 
						||
| 
								 | 
							
									addr.sin_addr.s_addr = sock->host;
							 | 
						||
| 
								 | 
							
									addr.sin_port = sock->port;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int res = connect(sock->handle, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
							 | 
						||
| 
								 | 
							
									return sock->connected = (res == 0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_socket_send(kinc_socket_t *sock, const uint8_t *data, int size) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									typedef int socklen_t;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									if (sock->protocol == KINC_SOCKET_PROTOCOL_UDP) {
							 | 
						||
| 
								 | 
							
										struct sockaddr_in addr;
							 | 
						||
| 
								 | 
							
										addr.sin_family = sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6;
							 | 
						||
| 
								 | 
							
										addr.sin_addr.s_addr = sock->host;
							 | 
						||
| 
								 | 
							
										addr.sin_port = sock->port;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										size_t sent = sendto(sock->handle, (const char *)data, size, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
							 | 
						||
| 
								 | 
							
										if (sent != size) {
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
							 | 
						||
| 
								 | 
							
											return -1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return (int)sent;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										if (!sock->connected) {
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Call kinc_sockect_connect/bind before send/recv can be called for TCP sockets.");
							 | 
						||
| 
								 | 
							
											return -1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										size_t sent = send(sock->handle, (const char *)data, size, 0);
							 | 
						||
| 
								 | 
							
										if (sent != size) {
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return (int)sent;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_socket_send_address(kinc_socket_t *sock, unsigned address, int port, const uint8_t *data, int size) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									struct sockaddr_in addr;
							 | 
						||
| 
								 | 
							
									addr.sin_family = AF_INET;
							 | 
						||
| 
								 | 
							
									addr.sin_addr.s_addr = htonl(address);
							 | 
						||
| 
								 | 
							
									addr.sin_port = htons(port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									size_t sent = sendto(sock->handle, (const char *)data, size, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
							 | 
						||
| 
								 | 
							
									if (sent != size) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return (int)sent;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_socket_send_url(kinc_socket_t *sock, const char *url, int port, const uint8_t *data, int size) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
									struct addrinfo *address = NULL;
							 | 
						||
| 
								 | 
							
									int res = resolveAddress(url, port, &address);
							 | 
						||
| 
								 | 
							
									if (res != 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Could not resolve address.");
							 | 
						||
| 
								 | 
							
										return 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									size_t sent = sendto(sock->handle, (const char *)data, size, 0, address->ai_addr, sizeof(struct sockaddr_in));
							 | 
						||
| 
								 | 
							
									if (sent != size) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									freeaddrinfo(address);
							 | 
						||
| 
								 | 
							
									return (int)sent;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_socket_receive(kinc_socket_t *sock, uint8_t *data, int maxSize, unsigned *fromAddress, unsigned *fromPort) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									typedef int socklen_t;
							 | 
						||
| 
								 | 
							
									typedef int ssize_t;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP) || defined(KINC_POSIX)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (sock->protocol == KINC_SOCKET_PROTOCOL_UDP) {
							 | 
						||
| 
								 | 
							
										struct sockaddr_in from;
							 | 
						||
| 
								 | 
							
										socklen_t fromLength = sizeof(from);
							 | 
						||
| 
								 | 
							
										ssize_t bytes = recvfrom(sock->handle, (char *)data, maxSize, 0, (struct sockaddr *)&from, &fromLength);
							 | 
						||
| 
								 | 
							
										if (bytes <= 0) {
							 | 
						||
| 
								 | 
							
											return (int)bytes;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										*fromAddress = ntohl(from.sin_addr.s_addr);
							 | 
						||
| 
								 | 
							
										*fromPort = ntohs(from.sin_port);
							 | 
						||
| 
								 | 
							
										return (int)bytes;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (!sock->connected) {
							 | 
						||
| 
								 | 
							
											kinc_log(KINC_LOG_LEVEL_ERROR, "Call kinc_sockect_connect/bind before send/recv can be called for TCP sockets.");
							 | 
						||
| 
								 | 
							
											return -1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										ssize_t bytes = recv(sock->handle, (char *)data, maxSize, 0);
							 | 
						||
| 
								 | 
							
										*fromAddress = ntohl(sock->host);
							 | 
						||
| 
								 | 
							
										*fromPort = ntohs(sock->port);
							 | 
						||
| 
								 | 
							
										return (int)bytes;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unsigned kinc_url_to_int(const char *url, int port) {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
							 | 
						||
| 
								 | 
							
									struct addrinfo *address = NULL;
							 | 
						||
| 
								 | 
							
									int res = resolveAddress(url, port, &address);
							 | 
						||
| 
								 | 
							
									if (res != 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Could not resolve address.");
							 | 
						||
| 
								 | 
							
										return -1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									unsigned fromAddress = ntohl(((struct sockaddr_in *)address->ai_addr)->sin_addr.S_un.S_addr);
							 | 
						||
| 
								 | 
							
									freeaddrinfo(address);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return fromAddress;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 |