first commit
This commit is contained in:
commit
efd4d9c750
13 changed files with 1950 additions and 0 deletions
277
socket.c
Normal file
277
socket.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
#include "socket.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#undef INVALID_SOCKET
|
||||
#undef SOCKET_ERROR
|
||||
|
||||
#if SOCK_WINDOWS
|
||||
#include <winsock2.h>
|
||||
|
||||
static bool _win_skInit();
|
||||
static bool _win_skCleanup();
|
||||
static int _win_skGetError();
|
||||
static const char *_win_skGetErrorString();
|
||||
|
||||
#define SOCK_CALL(fun) _win_##fun
|
||||
|
||||
#elif SOCK_POSIX
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h> // strerror
|
||||
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKET_ERROR (-1)
|
||||
|
||||
static bool _posix_skInit();
|
||||
static bool _posix_skCleanup();
|
||||
static int _posix_skGetError();
|
||||
static const char *_posix_skGetErrorString();
|
||||
|
||||
#define SOCK_CALL(fun) _posix_##fun
|
||||
|
||||
#endif
|
||||
|
||||
bool skInit() {
|
||||
return SOCK_CALL(skInit());
|
||||
}
|
||||
|
||||
bool skCleanup() {
|
||||
return SOCK_CALL(skCleanup());
|
||||
}
|
||||
|
||||
socket_t skOpen() {
|
||||
return skOpenPro(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
socket_t skOpenEx(const char *protocol) {
|
||||
struct protoent *proto = getprotobyname(protocol);
|
||||
if(!proto) {
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
return skOpenPro(AF_INET, SOCK_STREAM, proto->p_proto);
|
||||
}
|
||||
|
||||
socket_t skOpenPro(int af, int type, int protocol) {
|
||||
return socket(af, type, protocol);
|
||||
}
|
||||
|
||||
bool skClose(socket_t sock) {
|
||||
#if SOCK_WINDOWS
|
||||
int error = closesocket(sock);
|
||||
#elif SOCK_POSIX
|
||||
int error = close(sock);
|
||||
#endif
|
||||
sock = INVALID_SOCKET;
|
||||
return error != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
bool skBind(socket_t sock, const char *ip, uint16_t port) {
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr(ip);
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
return skBindPro(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||
}
|
||||
|
||||
bool skBindPro(socket_t sock, const struct sockaddr *name, socket_len_t namelen) {
|
||||
return bind(sock, name, namelen) != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
bool skListen(socket_t sock) {
|
||||
return skListenPro(sock, 1);
|
||||
}
|
||||
|
||||
bool skListenPro(socket_t sock, int backlog) {
|
||||
return listen(sock, backlog) != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
socket_t skAccept(socket_t sock) {
|
||||
struct sockaddr_in addr;
|
||||
socket_len_t addr_size = (socket_len_t)sizeof(addr);
|
||||
return skAcceptPro(sock, (struct sockaddr *) &addr, &addr_size);
|
||||
}
|
||||
|
||||
socket_t skAcceptPro(socket_t sock, struct sockaddr *addr, socket_len_t *addrlen) {
|
||||
return accept(sock, addr, addrlen);
|
||||
}
|
||||
|
||||
bool skConnect(socket_t sock, const char *server, unsigned short server_port) {
|
||||
struct hostent *host = gethostbyname(server);
|
||||
// if gethostbyname fails, inet_addr will also fail and return an easier to debug error
|
||||
const char *address = server;
|
||||
if(host) {
|
||||
address = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]);
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr(address);
|
||||
addr.sin_port = htons(server_port);
|
||||
|
||||
return skConnectPro(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||
}
|
||||
|
||||
bool skConnectPro(socket_t sock, const struct sockaddr *name, socket_len_t namelen) {
|
||||
return connect(sock, name, namelen) != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
int skSend(socket_t sock, char *buf, int len) {
|
||||
return send(sock, buf, len, 0);
|
||||
}
|
||||
|
||||
int skReceive(socket_t sock, char *buf, int len) {
|
||||
return recv(sock, buf, len, 0);
|
||||
}
|
||||
|
||||
bool skIsValid(socket_t sock) {
|
||||
return sock != INVALID_SOCKET;
|
||||
}
|
||||
|
||||
int skGetError() {
|
||||
return SOCK_CALL(skGetError());
|
||||
}
|
||||
|
||||
const char *skGetErrorString() {
|
||||
return SOCK_CALL(skGetErrorString());
|
||||
}
|
||||
|
||||
#ifdef SOCK_WINDOWS
|
||||
static bool _win_skInit() {
|
||||
WSADATA w;
|
||||
int error = WSAStartup(0x0202, &w);
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
static bool _win_skCleanup() {
|
||||
return WSACleanup() == 0;
|
||||
}
|
||||
|
||||
static int _win_skGetError() {
|
||||
return WSAGetLastError();
|
||||
}
|
||||
|
||||
static const char *_win_skGetErrorString() {
|
||||
switch(_win_skGetError()) {
|
||||
case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
|
||||
case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
|
||||
case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
|
||||
case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
|
||||
case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
|
||||
case WSA_IO_PENDING: return "Overlapped operations will complete later.";
|
||||
case WSAEINTR: return "Interrupted function call.";
|
||||
case WSAEBADF: return "File handle is not valid.";
|
||||
case WSAEACCES: return "Permission denied.";
|
||||
case WSAEFAULT: return "Bad address.";
|
||||
case WSAEINVAL: return "Invalid argument.";
|
||||
case WSAEMFILE: return "Too many open files.";
|
||||
case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
|
||||
case WSAEINPROGRESS: return "Operation now in progress.";
|
||||
case WSAEALREADY: return "Operation already in progress.";
|
||||
case WSAENOTSOCK: return "Socket operation on nonsocket.";
|
||||
case WSAEDESTADDRREQ: return "Destination address required.";
|
||||
case WSAEMSGSIZE: return "Message too long.";
|
||||
case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
|
||||
case WSAENOPROTOOPT: return "Bad protocol option.";
|
||||
case WSAEPROTONOSUPPORT: return "Protocol not supported.";
|
||||
case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
|
||||
case WSAEOPNOTSUPP: return "Operation not supported.";
|
||||
case WSAEPFNOSUPPORT: return "Protocol family not supported.";
|
||||
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
|
||||
case WSAEADDRINUSE: return "Address already in use.";
|
||||
case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
|
||||
case WSAENETDOWN: return "Network is down.";
|
||||
case WSAENETUNREACH: return "Network is unreachable.";
|
||||
case WSAENETRESET: return "Network dropped connection on reset.";
|
||||
case WSAECONNABORTED: return "Software caused connection abort.";
|
||||
case WSAECONNRESET: return "Connection reset by peer.";
|
||||
case WSAENOBUFS: return "No buffer space available.";
|
||||
case WSAEISCONN: return "Socket is already connected.";
|
||||
case WSAENOTCONN: return "Socket is not connected.";
|
||||
case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
|
||||
case WSAETOOMANYREFS: return "Too many references.";
|
||||
case WSAETIMEDOUT: return "Connection timed out.";
|
||||
case WSAECONNREFUSED: return "Connection refused.";
|
||||
case WSAELOOP: return "Cannot translate name.";
|
||||
case WSAENAMETOOLONG: return "Name too long.";
|
||||
case WSAEHOSTDOWN: return "Host is down.";
|
||||
case WSAEHOSTUNREACH: return "No route to host.";
|
||||
case WSAENOTEMPTY: return "Directory not empty.";
|
||||
case WSAEPROCLIM: return "Too many processes.";
|
||||
case WSAEUSERS: return "User quota exceeded.";
|
||||
case WSAEDQUOT: return "Disk quota exceeded.";
|
||||
case WSAESTALE: return "Stale file handle reference.";
|
||||
case WSAEREMOTE: return "Item is remote.";
|
||||
case WSASYSNOTREADY: return "Network subsystem is unavailable.";
|
||||
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
|
||||
case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
|
||||
case WSAEDISCON: return "Graceful shutdown in progress.";
|
||||
case WSAENOMORE: return "No more results.";
|
||||
case WSAECANCELLED: return "Call has been canceled.";
|
||||
case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid.";
|
||||
case WSAEINVALIDPROVIDER: return "Service provider is invalid.";
|
||||
case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize.";
|
||||
case WSASYSCALLFAILURE: return "System call failure.";
|
||||
case WSASERVICE_NOT_FOUND: return "Service not found.";
|
||||
case WSATYPE_NOT_FOUND: return "Class type not found.";
|
||||
case WSA_E_NO_MORE: return "No more results.";
|
||||
case WSA_E_CANCELLED: return "Call was canceled.";
|
||||
case WSAEREFUSED: return "Database query was refused.";
|
||||
case WSAHOST_NOT_FOUND: return "Host not found.";
|
||||
case WSATRY_AGAIN: return "Nonauthoritative host not found.";
|
||||
case WSANO_RECOVERY: return "This is a nonrecoverable error.";
|
||||
case WSANO_DATA: return "Valid name, no data record of requested type.";
|
||||
case WSA_QOS_RECEIVERS: return "QoS receivers.";
|
||||
case WSA_QOS_SENDERS: return "QoS senders.";
|
||||
case WSA_QOS_NO_SENDERS: return "No QoS senders.";
|
||||
case WSA_QOS_NO_RECEIVERS: return "QoS no receivers.";
|
||||
case WSA_QOS_REQUEST_CONFIRMED: return "QoS request confirmed.";
|
||||
case WSA_QOS_ADMISSION_FAILURE: return "QoS admission error.";
|
||||
case WSA_QOS_POLICY_FAILURE: return "QoS policy failure.";
|
||||
case WSA_QOS_BAD_STYLE: return "QoS bad style.";
|
||||
case WSA_QOS_BAD_OBJECT: return "QoS bad object.";
|
||||
case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QoS traffic control error.";
|
||||
case WSA_QOS_GENERIC_ERROR: return "QoS generic error.";
|
||||
case WSA_QOS_ESERVICETYPE: return "QoS service type error.";
|
||||
case WSA_QOS_EFLOWSPEC: return "QoS flowspec error.";
|
||||
case WSA_QOS_EPROVSPECBUF: return "Invalid QoS provider buffer.";
|
||||
case WSA_QOS_EFILTERSTYLE: return "Invalid QoS filter style.";
|
||||
case WSA_QOS_EFILTERTYPE: return "Invalid QoS filter type.";
|
||||
case WSA_QOS_EFILTERCOUNT: return "Incorrect QoS filter count.";
|
||||
case WSA_QOS_EOBJLENGTH: return "Invalid QoS object length.";
|
||||
case WSA_QOS_EFLOWCOUNT: return "Incorrect QoS flow count.";
|
||||
case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QoS object.";
|
||||
case WSA_QOS_EPOLICYOBJ: return "Invalid QoS policy object.";
|
||||
case WSA_QOS_EFLOWDESC: return "Invalid QoS flow descriptor.";
|
||||
case WSA_QOS_EPSFLOWSPEC: return "Invalid QoS provider-specific flowspec.";
|
||||
case WSA_QOS_EPSFILTERSPEC: return "Invalid QoS provider-specific filterspec.";
|
||||
case WSA_QOS_ESDMODEOBJ: return "Invalid QoS shape discard mode object.";
|
||||
case WSA_QOS_ESHAPERATEOBJ: return "Invalid QoS shaping rate object.";
|
||||
case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QoS element type.";
|
||||
}
|
||||
|
||||
return "(nothing)";
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool _posix_skInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _posix_skCleanup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int _posix_skGetError() {
|
||||
return errno;
|
||||
}
|
||||
|
||||
static const char *_posix_skGetErrorString() {
|
||||
return strerror(errno);
|
||||
}
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue