clib/ssocket.h

372 lines
9.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _SSOCKET_H_
#define _SSOCKET_H_
#include <stdio.h>
#include <string.h>
#define SSOCKET_VERSION_MAJOR 1
#define SSOCKET_VERSION_MINOR 0
#define SSOCKET_VERSION_PATCH 2
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#define _OS_WIN 1
//define something for Windows (32-bit and 64-bit, this part is common)
#ifdef _WIN64
#define _OS_WIN64 1
//define something for Windows (64-bit only)
#else
#define _OS_WIN32 1
//define something for Windows (32-bit only)
#endif
#elif __APPLE__
#define _OS_APPLE 1
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
#define _OS_APPLE_SIM 1
// iOS, tvOS, or watchOS Simulator
#elif TARGET_OS_MACCATALYST
#define _OS_APPLE_CATA 1
// Mac's Catalyst (ports iOS API into Mac, like UIKit).
#elif TARGET_OS_IPHONE
#define _OS_APPLE_PHO 1
// iOS, tvOS, or watchOS device
#elif TARGET_OS_MAC
#define _OS_APPLE_MAC 1
// Other kinds of Apple platforms
#else
# error "Unknown Apple platform"
#endif
#elif __linux__
#define _OS_LINUX 1
// linux
#elif __unix__ // all unices not caught above
#define _OS_UNIX 1
// Unix
#elif defined(_POSIX_VERSION)
#define _OS_POSIX 1
// POSIX
#else
# error "Unknown compiler"
#endif
#if _OS_WIN
#define WIN_PART 1
#elif _OS_LINUX
#define LINUX_PART 1
#else
#error "Not Supported Operator System"
#endif
#if WIN_PART
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define socklen_t int
#elif LINUX_PART
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <strings.h>
#define SOCKET long long int
//#define INVALID_SOCKET (SOCKET)(~0)
#endif
#ifndef ZZY_SLEEP
#define ZZY_SLEEP
#if WIN_PART
#define sleeps(s) Sleep(s*1000)
#define sleepms(ms) Sleep(ms)
#elif LINUX_PART
#define sleeps(s) sleep(s)
#define sleepms(ms) usleep(ms*1000)
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum {
ERR_SOCK_SUCCESS,
ERR_SOCK_MALLOC,
ERR_SOCK_NULLPTR,
ERR_SOCK_WSAStartup,
ERR_SOCK_DETERMINE_AGREEMENT,
ERR_SOCK_CREATE_SOCKET,
ERR_SOCK_BIND,
ERR_SOCK_LISTEN,
ERR_SOCK_ACCEPT,
ERR_SOCK_CONNECT,
ERR_SOCK_ADDRINFO,
//getaddrinfo
ERR_SOCK_EAI_MAPPING_NOT_EXIST,
ERR_SOCK_EAI_AGAIN,
ERR_SOCK_EAI_BADFLAGS,
ERR_SOCK_EAI_FAIL,
ERR_SOCK_EAI_FAMILY,
ERR_SOCK_EAI_MEMORY,
ERR_SOCK_EAI_NONAME,
ERR_SOCK_EAI_SERVICE,
ERR_SOCK_EAI_SOCKTYPE,
};
static inline int make_sock(SOCKET* sock);
static inline int sock_connect(SOCKET sock, const char* connect_ip, unsigned short port);
static inline int sock_bindlisten(SOCKET sock, const char* server_ip, unsigned short port);
static inline int sock_accpet(SOCKET sock,SOCKET* client, char** accept_ip, unsigned short* port);
static inline int make_server_sock(SOCKET* sock, const char* server_ip, unsigned short port);
static inline int make_client_sock(SOCKET* sock, const char* connect_ip, unsigned short port);
static inline void close_sock(SOCKET sock);
static inline void out_sock_err(FILE* output, int errcode);
static inline void get_sock_err(char* buff_128, size_t buff_len, int errcode);
static inline void sock_thread(void(*thread_func)(void*), void* data);
#define _SOCKET_TEST_IP "127.0.0.1"
#define _SOCKET_TEST_PORT 6789
static inline int _socket(SOCKET* sock, const char* ip, const char* port);
static inline int _connect(SOCKET sock, const char* ip, const char* port);
static inline int _bind(SOCKET sock, const char* ip, const char* port);
static inline int _bindlisten(SOCKET sock, const char* ip, const char* port);
static inline int _sock(SOCKET* sock, int af, int type);
static inline int make_sock(SOCKET* sock) { return make_sock_tcp4(sock); };
static inline int make_sock_tcp4(SOCKET* sock) { return _sock(sock, AF_INET, SOCK_STREAM); }
static inline int make_sock_tcp6(SOCKET* sock) { return _sock(sock, AF_INET6, SOCK_STREAM); }
static inline int make_sock_udp4(SOCKET* sock) { return _sock(sock, AF_INET, SOCK_DGRAM); }
static inline int make_sock_udp6(SOCKET* sock) { return _sock(sock, AF_INET6, SOCK_DGRAM); }
static inline int _sock(SOCKET* sock, int af, int type) {
#ifdef WIN_PART
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
return ERR_SOCK_WSAStartup;
}
if (HIBYTE(wsaData.wVersion) != 2 || \
LOBYTE(wsaData.wVersion) != 2) {
return ERR_SOCK_DETERMINE_AGREEMENT;
}
#endif
*sock = socket(af, type, 0);
if (*sock == INVALID_SOCKET) {
return ERR_SOCK_CREATE_SOCKET;
}
return ERR_SOCK_SUCCESS;
}
static inline int _sock_eai_res_map(int res) {
switch (res) {
case EAI_AGAIN: return ERR_SOCK_EAI_AGAIN;
case EAI_BADFLAGS: return ERR_SOCK_EAI_BADFLAGS;
case EAI_FAIL: return ERR_SOCK_EAI_FAIL;
case EAI_FAMILY: return ERR_SOCK_EAI_FAMILY;
case EAI_MEMORY: return ERR_SOCK_EAI_MEMORY;
case EAI_NONAME: return ERR_SOCK_EAI_NONAME;
case EAI_SERVICE: return ERR_SOCK_EAI_SERVICE;
case EAI_SOCKTYPE: return ERR_SOCK_EAI_SOCKTYPE;
default: return ERR_SOCK_EAI_MAPPING_NOT_EXIST;
}
}
static inline int _socket(SOCKET* sock, const char* ip, const char* port) {
struct addrinfo inf = { 0 };
struct addrinfo* res_addr = NULL;
int res = getaddrinfo(ip, port, &inf, &res_addr);
if (res != 0) {
return _sock_eai_res_map(res);
}
for (struct addrinfo* p = res_addr; p != NULL; p = p->ai_next) {
if (*sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) {
if (*sock == INVALID_SOCKET) {
return ERR_SOCK_CREATE_SOCKET;
}
freeaddrinfo(res_addr);
return ERR_SOCK_SUCCESS;
}
}
freeaddrinfo(res_addr);
return ERR_SOCK_CONNECT;
}
static inline int _connect(SOCKET sock, const char* ip, const char* port) {
struct addrinfo inf = { 0 };
struct addrinfo* res_addr = NULL;
int res = getaddrinfo(ip, port, &inf, &res_addr);
if (res != 0) {
return _sock_eai_res_map(res);
}
for (struct addrinfo* p = res_addr; p != NULL; p = p->ai_next) {
if (connect(sock, p->ai_addr, p->ai_addrlen) == 0) {
freeaddrinfo(res_addr);
return ERR_SOCK_SUCCESS;
}
}
freeaddrinfo(res_addr);
return ERR_SOCK_CONNECT;
}
static inline int _bind(SOCKET sock, const char* ip, const char* port) {
struct addrinfo inf = { 0 };
struct addrinfo* res_addr = NULL;
int res = getaddrinfo(ip, port, &inf, &res_addr);
if (res != 0) {
return ERR_SOCK_ADDRINFO;
}
for (struct addrinfo* p = res_addr; p != NULL; p = p->ai_next) {
if (bind(sock, p->ai_addr, p->ai_addrlen) == 0) {
freeaddrinfo(res_addr);
return ERR_SOCK_SUCCESS;
}
}
freeaddrinfo(res_addr);
return ERR_SOCK_CONNECT;
}
static inline int _bindlisten(SOCKET sock, const char* ip, const char* port) {
int res = _bind(sock, ip, port);
if(res == ERR_SOCK_SUCCESS){
if (listen(sock, SOMAXCONN) == 0) {
return ERR_SOCK_SUCCESS;
}
return ERR_SOCK_LISTEN;
}
return res;
}
static inline int sock_connect(SOCKET sock, const char* connect_ip, unsigned short port) {
char buf[8] = { 0 };
sprintf(buf, "%u", port);
return _connect(sock, connect_ip, buf);
}
static inline int sock_bindlisten(SOCKET sock, const char* server_ip, unsigned short port) {
char buf[8] = { 0 };
sprintf(buf, "%u", port);
return _bindlisten(sock, server_ip, buf);
}
static inline int sock_accpet(SOCKET sock,SOCKET* client, char** accept_ip, unsigned short* port) {
struct sockaddr_in caddr = { 0 };
socklen_t addrLen = sizeof(struct sockaddr_in);
if(client == NULL) {
return ERR_SOCK_NULLPTR;
}
*client = accept(sock,(struct sockaddr*) &caddr, &addrLen);
if (*client == -1) {
return ERR_SOCK_ACCEPT;
}
char* ip = (char*)malloc(32);
if(ip == NULL) {
return ERR_SOCK_MALLOC;
}
int buffLen = strlen( inet_ntoa(caddr.sin_addr) );
if(accept_ip != NULL) {
strncpy(ip, inet_ntoa(caddr.sin_addr), buffLen);
ip[buffLen] = '\0';
*accept_ip = ip;
}
if(port != NULL) {
*port = ntohs(caddr.sin_port);
}
return ERR_SOCK_SUCCESS;
}
static inline int make_server_sock(SOCKET* sock, const char* server_ip, unsigned short port) {
int res = make_sock(sock);
if(res != ERR_SOCK_SUCCESS) {
return res;
}
res = sock_bindlisten(*sock, server_ip, port);
if(res != ERR_SOCK_SUCCESS) {
return res;
}
return ERR_SOCK_SUCCESS;
}
static inline int make_client_sock(SOCKET* sock, const char* connect_ip, unsigned short port) {
int res = make_sock(sock);
if(res != ERR_SOCK_SUCCESS) {
return res;
}
if(connect_ip) {
res = sock_connect(*sock, connect_ip, port);
if(res != ERR_SOCK_SUCCESS) {
return res;
}
}
return ERR_SOCK_SUCCESS;
}
static inline void close_sock(SOCKET sock) {
if(sock == -1) {
return;
}
#if WIN_PART
closesocket(sock);
#elif LINUX_PART
close(sock);
#endif
}
static inline void out_sock_err(FILE* output, int errcode) {
fprintf(output, "%d", errcode);
}
static inline void get_sock_err(char* buff_128, size_t buff_len, int errcode) {
if(buff_len < 128) {
return;
}
// enum {
// ERR_SOCK_SUCCESS,
// ERR_SOCK_MALLOC,
// ERR_SOCK_NULLPTR,
// ERR_SOCK_WSAStartup,
// ERR_SOCK_DETERMINE_AGREEMENT,
// ERR_SOCK_CREATE_SOCKET,
// ERR_SOCK_BIND,
// ERR_SOCK_LISTEN,
// ERR_SOCK_ACCEPT,
// ERR_SOCK_CONNECT,
// };
//https://learn.microsoft.com/zh-cn/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo?redirectedfrom=MSDN
//<2F><><EFBFBD><EFBFBD>ֵ WSA <20><>Ч<EFBFBD><D0A7> ˵<><CBB5>
//EAI_AGAIN WSATRY_AGAIN <09><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD>ʱʧ<CAB1>ܡ<EFBFBD>
//EAI_BADFLAGS WSAEINVAL Ϊ pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ai_flags <20><>Ա<EFBFBD><EFBFBD><E1B9A9><EFBFBD><EFBFBD>Чֵ<D0A7><D6B5>
//EAI_FAIL WSANO_RECOVERY <09><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>з<EFBFBD><D0B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɻָ<C9BB><D6B8><EFBFBD>ʧ<EFBFBD>ܡ<EFBFBD>
//EAI_FAMILY WSAEAFNOSUPPORT <09><>֧<EFBFBD><D6A7> pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ai_family <20><>Ա<EFBFBD><D4B1>
//EAI_MEMORY WSA_NOT_ENOUGH_MEMORY <09>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܡ<EFBFBD>
//EAI_NONAME WSAHOST_NOT_FOUND <09><><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>ṩ pNodeName <20><> pServiceName <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//EAI_SERVICE WSATYPE_NOT_FOUND pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ai_socktype<70><65>Ա<EFBFBD><D4B1>֧<EFBFBD><D6A7> pServiceName <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//EAI_SOCKTYPE WSAESOCKTNOSUPPORT <09><>֧<EFBFBD><D6A7> pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ai_socktype <20><>Ա<EFBFBD><D4B1>
sprintf(buff_128, "%3d", errcode);
}
static inline void sock_thread(void(*thread_func)(void*), void* data) {
#if WIN_PART
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL);
#elif LINUX_PART
pthread_t pid;
pthread_create(&pid, 0, (void*(*)(void*))thread_func, data);
#endif
}
#ifdef __cplusplus
}
#endif
#endif