448 lines
12 KiB
C
448 lines
12 KiB
C
#ifndef _SSOCKET_H_
|
|
#define _SSOCKET_H_
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "sysenv.h"
|
|
|
|
#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 <CoreWindow.h>
|
|
#ifndef strcasecmp
|
|
#define strcasecmp _stricmp
|
|
#endif
|
|
#ifndef strncasecmp
|
|
#define strncasecmp _strnicmp
|
|
#endif
|
|
|
|
#ifndef SHUT_RD
|
|
#define SHUT_RD SD_RECEIVE
|
|
#endif
|
|
#ifndef SHUT_WR
|
|
#define SHUT_WR SD_SEND
|
|
#endif
|
|
#ifndef SHUT_RDWR
|
|
#define SHUT_RDWR SD_BOTH
|
|
#endif
|
|
|
|
//#define socklen_t int
|
|
#elif LINUX_PART
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.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
|
|
|
|
#define _SOCKET_TEST_IP4 "127.0.0.1"
|
|
#define _SOCKET_TEST_IP6 "::1"
|
|
#define _SOCKET_TEST_PORT 26789
|
|
|
|
#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_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 int make_server_sock_ex(SOCKET* sock, const char* server_ip, const char* port,
|
|
struct addrinfo** resaddr);
|
|
static inline int make_client_sock_ex(SOCKET* sock, const char* connect_ip, const char* port,
|
|
struct addrinfo** resaddr);
|
|
|
|
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_bind(SOCKET sock, const char* server_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 _sock(SOCKET* sock, int af, int type);
|
|
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 _getaddrinfo(struct addrinfo* inf, struct addrinfo** resaddr,
|
|
const char* ip, const char* port);
|
|
static inline int _socket(SOCKET* sock, struct addrinfo* resaddr);
|
|
static inline int _connect(SOCKET sock, struct addrinfo* resaddr);
|
|
static inline int _bind(SOCKET sock, struct addrinfo* resaddr);
|
|
static inline int _bindlisten(SOCKET sock, struct addrinfo* resaddr);
|
|
static inline int _accept(SOCKET sock, SOCKET* client, struct addrinfo* inf);
|
|
|
|
//not recommand and it will be remove
|
|
static inline int make_sock(SOCKET* sock) { return make_sock_tcp4(sock); };
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// need to using freeaddrinfo to free <resaddr>
|
|
static inline int _getaddrinfo(struct addrinfo* inf, struct addrinfo** resaddr,
|
|
const char* ip, const char* port) {
|
|
if (resaddr == NULL || ip == NULL || port == NULL) { return ERR_SOCK_NULLPTR; }
|
|
int res = getaddrinfo(ip, port, inf, resaddr);
|
|
if (res != 0) {
|
|
return -(_sock_eai_res_map(res));
|
|
}
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
|
|
static inline int _socket(SOCKET* sock, struct addrinfo* resaddr) {
|
|
for (struct addrinfo* p = resaddr; 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;
|
|
}
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
}
|
|
return -ERR_SOCK_CONNECT;
|
|
}
|
|
|
|
static inline int _connect(SOCKET sock, struct addrinfo* resaddr) {
|
|
for (struct addrinfo* p = resaddr; p != NULL; p = p->ai_next) {
|
|
if (connect(sock, p->ai_addr, p->ai_addrlen) == 0) {
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
}
|
|
return -ERR_SOCK_CONNECT;
|
|
}
|
|
|
|
static inline int _bind(SOCKET sock, struct addrinfo* resaddr) {
|
|
for (struct addrinfo* p = resaddr; p != NULL; p = p->ai_next) {
|
|
if (bind(sock, p->ai_addr, p->ai_addrlen) == 0) {
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
}
|
|
return -ERR_SOCK_CONNECT;
|
|
}
|
|
|
|
static inline int _bindlisten(SOCKET sock, struct addrinfo* resaddr) {
|
|
int res = _bind(sock, resaddr);
|
|
if(res == ERR_SOCK_SUCCESS){
|
|
if (listen(sock, SOMAXCONN) == 0) {
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
return -ERR_SOCK_LISTEN;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static inline int _accept(SOCKET sock, SOCKET* client, struct addrinfo* inf) {
|
|
int res = ERR_SOCK_SUCCESS;
|
|
socklen_t addrLen = sizeof(struct addrinfo);
|
|
|
|
if (client == NULL) {
|
|
return -ERR_SOCK_NULLPTR;
|
|
}
|
|
*client = accept(sock, (struct sockaddr*)inf, &addrLen);
|
|
if (*client == INVALID_SOCKET) {
|
|
return -ERR_SOCK_ACCEPT;
|
|
}
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
|
|
static inline int sock_connect(SOCKET sock, const char* connect_ip, unsigned short port) {
|
|
int res = ERR_SOCK_SUCCESS;
|
|
char buf[8] = { 0 };
|
|
sprintf(buf, "%u", port);
|
|
struct addrinfo inf = { 0 };
|
|
struct addrinfo* resaddr = NULL;
|
|
res = _getaddrinfo(&inf, &resaddr, connect_ip, buf);
|
|
if (res != ERR_SOCK_SUCCESS) goto RES;
|
|
res = _connect(sock, resaddr);
|
|
if (res != ERR_SOCK_SUCCESS) goto RES;
|
|
RES:
|
|
if (resaddr) freeaddrinfo(resaddr);
|
|
return res;
|
|
}
|
|
|
|
static inline int sock_bind(SOCKET sock, const char* server_ip, unsigned short port) {
|
|
int res = ERR_SOCK_SUCCESS;
|
|
char buf[8] = { 0 };
|
|
sprintf(buf, "%u", port);
|
|
struct addrinfo inf = { 0 };
|
|
struct addrinfo* resaddr = NULL;
|
|
res = _getaddrinfo(&inf, &resaddr, server_ip, buf);
|
|
if (res != ERR_SOCK_SUCCESS) goto RES;
|
|
res = _bind(sock, resaddr);
|
|
if (res != ERR_SOCK_SUCCESS) goto RES;
|
|
RES:
|
|
if (resaddr) freeaddrinfo(resaddr);
|
|
return res;
|
|
}
|
|
|
|
static inline int sock_bindlisten(SOCKET sock, const char* server_ip, unsigned short port) {
|
|
int res = ERR_SOCK_SUCCESS;
|
|
char buf[8] = { 0 };
|
|
sprintf(buf, "%u", port);
|
|
struct addrinfo inf = { 0 };
|
|
struct addrinfo* resaddr = NULL;
|
|
res = _getaddrinfo(&inf, &resaddr, server_ip, buf);
|
|
if (res != ERR_SOCK_SUCCESS) goto RES;
|
|
res = _bindlisten(sock, resaddr);
|
|
if (res != ERR_SOCK_SUCCESS) goto RES;
|
|
RES:
|
|
if (resaddr) freeaddrinfo(resaddr);
|
|
return res;
|
|
}
|
|
|
|
static inline int sock_accpet(SOCKET sock,SOCKET* client, char** accept_ip, unsigned short* port) {
|
|
int res = 0;
|
|
struct addrinfo inf;
|
|
if (client == NULL) {
|
|
return -ERR_SOCK_NULLPTR;
|
|
}
|
|
res = _accept(sock, client, &inf);
|
|
if (res != ERR_SOCK_SUCCESS) return res;
|
|
if (accept_ip == NULL) return ERR_SOCK_SUCCESS;
|
|
|
|
char* hostname = (char*)malloc(32);
|
|
char* servInfo = (char*)malloc(8);
|
|
if(hostname == NULL) {
|
|
return -ERR_SOCK_MALLOC;
|
|
}
|
|
if (servInfo == NULL) {
|
|
free(hostname);
|
|
return -ERR_SOCK_MALLOC;
|
|
}
|
|
res = getnameinfo((struct sockaddr*)&inf, sizeof(struct addrinfo),
|
|
hostname, 32, servInfo, 8, NI_NUMERICHOST);// NI_NUMERICHOST NI_NUMERICSERV
|
|
if (res != 0) {
|
|
return -ERR_SOCK_ACCEPT;
|
|
}
|
|
|
|
*accept_ip = hostname;
|
|
if (port != NULL) {
|
|
*port = (unsigned short)atoi(servInfo);
|
|
}
|
|
|
|
return ERR_SOCK_SUCCESS;
|
|
}
|
|
|
|
static inline int make_server_sock(SOCKET* sock, const char* server_ip, unsigned short port) {
|
|
char buf[8] = { 0 };
|
|
sprintf(buf, "%u", port);
|
|
int res = make_server_sock_ex(sock, server_ip, buf, NULL);
|
|
return res;
|
|
}
|
|
|
|
static inline int make_client_sock(SOCKET* sock, const char* connect_ip, unsigned short port) {
|
|
char buf[8] = { 0 };
|
|
sprintf(buf, "%u", port);
|
|
int res = make_client_sock_ex(sock, connect_ip, buf, NULL);
|
|
if (res != ERR_SOCK_SUCCESS) {
|
|
return res;
|
|
}
|
|
res = sock_connect(*sock, connect_ip, port);
|
|
return res;
|
|
}
|
|
|
|
static inline int make_server_sock_ex(SOCKET* sock, const char* server_ip, const char* port,
|
|
struct addrinfo** resaddr) {
|
|
#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
|
|
int res = ERR_SOCK_SUCCESS;
|
|
struct addrinfo inf = { 0 };
|
|
struct addrinfo* addr = NULL;
|
|
res = _getaddrinfo(&inf, &addr, server_ip, port);
|
|
if (res != ERR_SOCK_SUCCESS) goto END;
|
|
|
|
res = _socket(sock, addr);
|
|
if (res != ERR_SOCK_SUCCESS) goto END;
|
|
|
|
res = _bindlisten(*sock, addr);
|
|
if (res != ERR_SOCK_SUCCESS) goto END;
|
|
|
|
END:
|
|
if (resaddr == NULL) {
|
|
freeaddrinfo(addr);
|
|
}
|
|
else {
|
|
*resaddr = addr;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static inline int make_client_sock_ex(SOCKET* sock, const char* connect_ip, const char* port,
|
|
struct addrinfo** resaddr) {
|
|
#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
|
|
int res = ERR_SOCK_SUCCESS;
|
|
struct addrinfo inf = { 0 };
|
|
struct addrinfo* addr = NULL;
|
|
res = _getaddrinfo(&inf, &addr, connect_ip, port);
|
|
if (res != ERR_SOCK_SUCCESS) goto END;
|
|
|
|
res = _socket(sock, addr);
|
|
if (res != ERR_SOCK_SUCCESS) goto END;
|
|
|
|
END:
|
|
if (resaddr == NULL) {
|
|
freeaddrinfo(addr);
|
|
}
|
|
else {
|
|
*resaddr = addr;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
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,
|
|
|
|
// 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,
|
|
// };
|
|
// https://learn.microsoft.com/zh-cn/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo?redirectedfrom=MSDN
|
|
// https://learn.microsoft.com/en-gb/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo?redirectedfrom=MSDN
|
|
// Error value WSA equivalent Description
|
|
// EAI_AGAIN WSATRY_AGAIN A temporary failure in name resolution occurred.
|
|
// EAI_BADFLAGS WSAEINVAL An invalid value was provided for the ai_flags member of the pHints parameter.
|
|
// EAI_FAIL WSANO_RECOVERY A nonrecoverable failure in name resolution occurred.
|
|
// EAI_FAMILY WSAEAFNOSUPPORT The ai_family member of the pHints parameter is not supported.
|
|
// EAI_MEMORY WSA_NOT_ENOUGH_MEMORY A memory allocation failure occurred.
|
|
// EAI_NONAME WSAHOST_NOT_FOUND The name does not resolve for the supplied parameters or the pNodeName and pServiceName parameters were not provided.
|
|
// EAI_SERVICE WSATYPE_NOT_FOUND The pServiceName parameter is not supported for the specified ai_socktype member of the pHints parameter.
|
|
// EAI_SOCKTYPE WSAESOCKTNOSUPPORT The ai_socktype member of the pHints parameter is not supported.
|
|
|
|
sprintf(buff_128, "%3d", errcode);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif //_SSOCKET_H_
|