31#if __BYTE_ORDER == __LITTLE_ENDIAN
32 if (
sizeof(
size_t) == 4) {
33 return (
size_t)htonl((uint32_t)value);
34 }
else if (
sizeof(
size_t) == 8) {
35 return ((
size_t)htonl((uint32_t)(value >> 32)) |
36 ((
size_t)htonl((uint32_t)value) << 32));
48#if __BYTE_ORDER == __LITTLE_ENDIAN
49 if (
sizeof(
size_t) == 4) {
50 return (
size_t)ntohl((uint32_t)value);
51 }
else if (
sizeof(
size_t) == 8) {
52 return ((
size_t)ntohl((uint32_t)(value >> 32)) |
53 ((
size_t)ntohl((uint32_t)value) << 32));
66char* wchar_to_char(
const wchar_t* pwchar) {
68 int currentCharIndex = 0;
69 char currentChar = pwchar[currentCharIndex];
70 char* filePathC = NULL;
72 while (currentChar !=
'\0') {
74 currentChar = pwchar[currentCharIndex];
77 const int charCount = currentCharIndex + 1;
80 Malloc(filePathC,
char, charCount);
83 for (
int i = 0; i < charCount; i++) {
85 char character = pwchar[i];
87 *filePathC = character;
89 filePathC +=
sizeof(char);
93 filePathC -= (
sizeof(char) * charCount);
99#define neterrno WSAGetLastError()
102#define netstrerror(code) ({ \
104 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
106 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \
107 (LPWSTR) & s, 0, NULL); \
108 char* netstr = wchar_to_char(s); \
113#if __GNUC__ <= 6 && __GNUC_MINOR__ <= 3
147size_t strlcpy(
char* dst,
const char* src,
size_t siz) {
155 if ((*d++ = *s++) ==
'\0')
167 return (s - src - 1);
192static char* inet_ntop4(
const unsigned char* src,
char* dst, socklen_t size);
193static char* inet_ntop6(
const unsigned char* src,
char* dst, socklen_t size);
203char* inet_ntop(
int af,
const void* src,
char* dst, socklen_t size) {
206 return (inet_ntop4((
const unsigned char*)src, dst, size));
208 return (inet_ntop6((
const unsigned char*)src, dst, size));
226static char* inet_ntop4(
const unsigned char* src,
char* dst, socklen_t size) {
227 static const char fmt[] =
"%u.%u.%u.%u";
228 char tmp[
sizeof "255.255.255.255"];
231 l = snprintf(tmp,
sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
232 if (l <= 0 || (socklen_t)l >= size) {
235 strlcpy(dst, tmp, size);
245static char* inet_ntop6(
const unsigned char* src,
char* dst, socklen_t size) {
253 char tmp[
sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
258#define NS_IN6ADDRSZ 16
260 u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
268 memset(words,
'\0',
sizeof words);
269 for (i = 0; i < NS_IN6ADDRSZ; i++)
270 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
275 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
278 cur.base = i, cur.len = 1;
282 if (cur.base != -1) {
283 if (best.base == -1 || cur.len > best.len)
289 if (cur.base != -1) {
290 if (best.base == -1 || cur.len > best.len)
293 if (best.base != -1 && best.len < 2)
300 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
302 if (best.base != -1 && i >= best.base &&
303 i < (best.base + best.len)) {
312 if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 7 && words[7] != 0x0001) || (best.len == 5 && words[5] == 0xffff))) {
313 if (!inet_ntop4(src + 12, tp,
sizeof tmp - (tp - tmp)))
318 tp += sprintf(tp,
"%x", words[i]);
321 if (best.base != -1 && (best.base + best.len) ==
322 (NS_IN6ADDRSZ / NS_INT16SZ))
329 if ((socklen_t)(tp - tmp) > size) {
358static int inet_pton4(
const char* src, u_char* dst);
359static int inet_pton6(
const char* src, u_char* dst);
372int inet_pton(
int af,
const char* src,
void* dst) {
375 return (inet_pton4(src, (
unsigned char*)dst));
377 return (inet_pton6(src, (
unsigned char*)dst));
394static int inet_pton4(
const char* src, u_char* dst) {
395 static const char digits[] =
"0123456789";
396 int saw_digit, octets, ch;
398 u_char tmp[NS_INADDRSZ], *tp;
403 while ((ch = *src++) !=
'\0') {
406 if ((pch = strchr(digits, ch)) != NULL) {
407 u_int uiNew = *tp * 10 + (pch - digits);
409 if (saw_digit && *tp == 0)
419 }
else if (ch ==
'.' && saw_digit) {
429 memcpy(dst, tmp, NS_INADDRSZ);
446static int inet_pton6(
const char* src, u_char* dst) {
447 static const char xdigits_l[] =
"0123456789abcdef",
448 xdigits_u[] =
"0123456789ABCDEF";
449#define NS_IN6ADDRSZ 16
451 u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
453 int ch, seen_xdigits;
456 memset((tp = tmp),
'\0', NS_IN6ADDRSZ);
457 endp = tp + NS_IN6ADDRSZ;
466 while ((ch = *src++) !=
'\0') {
467 const char* xdigits :
const char* pch;
469 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
470 pch = strchr((xdigits = xdigits_u), ch);
473 val |= (pch - xdigits);
474 if (++seen_xdigits > 4)
485 }
else if (*src ==
'\0') {
488 if (tp + NS_INT16SZ > endp)
490 *tp++ = (u_char)(val >> 8) & 0xff;
491 *tp++ = (u_char)val & 0xff;
496 if (ch ==
'.' && ((tp + NS_INADDRSZ) <= endp) &&
497 inet_pton4(curtok, tp) > 0) {
505 if (tp + NS_INT16SZ > endp)
507 *tp++ = (u_char)(val >> 8) & 0xff;
508 *tp++ = (u_char)val & 0xff;
510 if (colonp != NULL) {
515 const int n = tp - colonp;
520 for (i = 1; i <= n; i++) {
521 endp[-i] = colonp[n - i];
528 memcpy(dst, tmp, NS_IN6ADDRSZ);
536#include <sys/types.h>
540#define neterrno errno
555#define netstrerror(code) ({ \
556 char* __errmsg = NULL; \
558 __errmsg = strdup(strerror(code)); \
559 if (errno == ENOMEM) { \
592 memset(&
netw->
link.
raddr, 0,
sizeof(
struct sockaddr_storage));
627 n_log(
LOG_ERR,
"Error when creating receive list with %d item limit", recv_list_limit);
633 n_log(
LOG_ERR,
"Error when creating send list with %d item limit", send_list_limit);
681 return sa->sa_family == AF_INET
682 ? (
char*)&(((
struct sockaddr_in*)sa)->sin_addr)
683 : (
char*)&(((
struct sockaddr_in6*)sa)->sin6_addr);
694 int compiler_warning_suppressor = 0;
695#if !defined(__linux__) && !defined(__sun) && !defined(_AIX)
696 static WSADATA WSAdata;
697 static int WSA_IS_INITIALIZED = 0;
703 return WSA_IS_INITIALIZED;
707 if (WSA_IS_INITIALIZED == 1)
709 if ((WSAStartup(MAKEWORD(v1, v2), &WSAdata)) != 0) {
710 WSA_IS_INITIALIZED = 0;
713 WSA_IS_INITIALIZED = 1;
719 if (WSA_IS_INITIALIZED == 0)
721 if (WSACleanup() == 0) {
722 WSA_IS_INITIALIZED = 0;
728 compiler_warning_suppressor =
mode + v1 + v2;
729 compiler_warning_suppressor = TRUE;
730 return compiler_warning_suppressor;
745#if defined(__linux__) || defined(__sun)
749 if ((flags & O_NONBLOCK) && !is_blocking) {
756 if (!(flags & O_NONBLOCK) && is_blocking) {
763 if (fcntl(
netw->
link.
sock, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags | O_NONBLOCK) == -1) {
771 unsigned long int blocking = 1 - is_blocking;
772 int res = ioctlsocket(
netw->
link.
sock, FIONBIO, &blocking);
774 if (res != NO_ERROR) {
776 n_log(
LOG_ERR,
"ioctlsocket failed with error: %ld , neterrno: %s", res,
_str(errmsg));
804 if (setsockopt(
netw->
link.
sock, IPPROTO_TCP, TCP_NODELAY, (
const char*)&value,
sizeof(value)) == -1) {
817 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_SNDBUF, (
const char*)&value,
sizeof(value)) == -1) {
829 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_RCVBUF, (
const char*)&value,
sizeof(value)) == -1) {
841 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_REUSEADDR, (
char*)&value,
sizeof(value)) == -1) {
867 }
else if (value == 0) {
872 ling.l_linger = value;
875 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_LINGER, &ling,
sizeof(ling)) == -1) {
883 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_LINGER, (
const char*)&ling,
sizeof(ling)) == -1) {
900 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_RCVTIMEO, (
const char*)&tv,
sizeof tv) == -1) {
909 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_RCVTIMEO, (
const char*)&value,
sizeof value) == -1) {
928 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_SNDTIMEO, (
const char*)&tv,
sizeof tv) == -1) {
937 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_SNDTIMEO, (
const char*)&value,
sizeof value) == -1) {
961 case TCP_USER_TIMEOUT:
963 if (setsockopt(
netw->
link.
sock, IPPROTO_TCP, TCP_USER_TIMEOUT, (
const char*)&value,
sizeof value) == -1) {
973 if (setsockopt(
netw->
link.
sock, IPPROTO_TCP, TCP_QUICKACK, &value,
sizeof(value)) < 0) {
983 if (setsockopt(
netw->
link.
sock, SOL_SOCKET, SO_KEEPALIVE, (
const char*)&value,
sizeof value) == -1) {
994 n_log(
LOG_ERR,
"%d is not a supported setsockopt", optname);
1003 BIO* bio = BIO_new(BIO_s_mem());
1008 ERR_print_errors(bio);
1011 size_t len = (size_t)BIO_get_mem_data(bio, &buf);
1014 char* error_str = malloc(len + 1);
1016 memcpy(error_str, buf, len);
1017 error_str[len] =
'\0';
1026 unsigned long error = 0;
1027 while ((error = ERR_get_error())) {
1028 n_log(
LOG_ERR,
"socket %d: %s", socket, ERR_reason_error_string(error));
1071__attribute__((unused))
static void netw_ssl_lock_callback(
int mode,
int type,
char* file,
int line) {
1074 if (
mode & CRYPTO_LOCK) {
1081__attribute__((unused))
static unsigned long thread_id(
void) {
1084 ret = (
unsigned long)pthread_self();
1091 size_t lock_count = (size_t)CRYPTO_num_locks();
1092 netw_ssl_lockarray = (pthread_mutex_t*)OPENSSL_malloc((
size_t)(lock_count *
sizeof(pthread_mutex_t)));
1094 for (i = 0; i < CRYPTO_num_locks(); i++) {
1098 CRYPTO_set_id_callback((
unsigned long (*)())thread_id);
1099 CRYPTO_set_locking_callback((
void (*)())netw_ssl_lock_callback);
1105 CRYPTO_set_locking_callback(NULL);
1106 for (i = 0; i < CRYPTO_num_locks(); i++)
1117 static int OPENSSL_IS_INITIALIZED = 0;
1119 if (OPENSSL_IS_INITIALIZED == 1)
1123 SSL_load_error_strings();
1125#if OPENSSL_VERSION_NUMBER < 0x10100000L
1126 ERR_load_BIO_strings();
1128 OpenSSL_add_all_algorithms();
1131 OPENSSL_IS_INITIALIZED = 1;
1141 static int OPENSSL_IS_INITIALIZED = 0;
1143 if (OPENSSL_IS_INITIALIZED == 0)
1149 OPENSSL_IS_INITIALIZED = 0;
1163 if (
key && strlen(
key) > 0) {
1166 if (certificate && strlen(certificate) > 0) {
1169 if (
key && certificate) {
1171#if OPENSSL_VERSION_NUMBER >= 0x10100000L
1185 if (SSL_CTX_load_verify_locations(
netw->
ctx, NULL,
"/etc/ssl/certs/") != 1) {
1190 if (SSL_CTX_use_certificate_file(
netw->
ctx, certificate, SSL_FILETYPE_PEM) <= 0) {
1194 if (SSL_CTX_use_PrivateKey_file(
netw->
ctx,
key, SSL_FILETYPE_PEM) <= 0) {
1225 (void)ssl_cert_file;
1226 int error = 0, net_status = 0;
1227 char* errmsg = NULL;
1231 n_log(
LOG_ERR,
"Unable to allocate (*netw), already existing. You must use empty NETWORK *structs.");
1236 (*netw) =
netw_new(send_list_limit, recv_list_limit);
1248 (*netw)->link.hints.ai_family = AF_INET;
1250 (*netw)->link.hints.ai_family = AF_INET6;
1253 (*netw)->link.hints.ai_family = AF_UNSPEC;
1256 (*netw)->link.hints.ai_socktype = SOCK_STREAM;
1257 (*netw)->link.hints.ai_protocol = IPPROTO_TCP;
1258 (*netw)->link.hints.ai_flags = AI_PASSIVE;
1259 (*netw)->link.hints.ai_canonname = NULL;
1260 (*netw)->link.hints.ai_next = NULL;
1265 error = getaddrinfo(host,
port, &(*netw)->link.hints, &(*netw)->link.rhost);
1267 n_log(
LOG_ERR,
"Error when resolving %s:%s getaddrinfo: %s", host,
port, gai_strerror(error));
1271 (*netw)->addr_infos_loaded = 1;
1272 Malloc((*netw)->link.ip,
char, 64);
1276 struct addrinfo* rp = NULL;
1277 for (rp = (*netw)->link.rhost; rp != NULL; rp = rp->ai_next) {
1278 int sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
1287 (*netw)->link.sock = sock;
1289 net_status = connect(sock, rp->ai_addr, rp->ai_addrlen);
1290 if (net_status == -1) {
1296 (*netw)->link.sock = -1;
1300 if (!inet_ntop(rp->ai_family,
get_in_addr(rp->ai_addr), (*netw)->link.ip, 64)) {
1311 n_log(
LOG_ERR,
"Couldn't connect to %s:%s : no address succeeded", host,
port);
1316 (*netw)->link.port = strdup(
port);
1319 if (ssl_key_file && ssl_cert_file) {
1328 (*netw)->ssl = SSL_new((*netw)->ctx);
1329 SSL_set_fd((*netw)->ssl, (*netw)->link.sock);
1332 if (SSL_connect((*netw)->ssl) <= 0) {
1338 n_log(
LOG_DEBUG,
"SSL-Connected to %s:%s", (*netw)->link.ip, (*netw)->link.port);
1340 n_log(
LOG_ERR,
"%s:%s trying to configure SSL but application was compiled without SSL support !", (*netw)->link.ip, (*netw)->link.port);
1343 n_log(
LOG_DEBUG,
"Connected to %s:%s", (*netw)->link.ip, (*netw)->link.port);
1393 if (thr_engine_status)
1473#if defined(__linux__)
1474 int outstanding = 0;
1478 for (
int it = 0; it < timeout; it += 100) {
1480 if (ioctl(fd, SIOCOUTQ, &outstanding) == -1) {
1482 n_log(
LOG_ERR,
"ioctl SIOCOUTQ returned -1: %s for socket %d", strerror(error), fd);
1506 int thr_engine_status = 0;
1510 if ((*netw)->deplete_queues_timeout > 0) {
1511 countdown = (*netw)->deplete_queues_timeout * 1000000;
1515 pthread_mutex_lock(&(*netw)->eventbolt);
1516 nb_running = (*netw)->nb_running_threads;
1517 pthread_mutex_unlock(&(*netw)->eventbolt);
1519 if (countdown < 100000)
1522 countdown -= 100000;
1523 }
while (nb_running > 0 && countdown > 0);
1525 if (countdown == 0 && nb_running > 0) {
1526 n_log(
LOG_ERR,
"netw %d: %d threads are still running after %d seconds, netw is in state %s (%" PRIu32
")", (*netw)->link.sock, nb_running, (*netw)->deplete_queues_timeout,
N_ENUM_ENTRY(
__netw_code_type, toString)(state), state);
1531 if ((*netw)->link.sock != INVALID_SOCKET) {
1533 if (remaining > 0) {
1534 n_log(
LOG_ERR,
"socket %d (%s:%s) %d octets still in send buffer before closing after a wait of %d msecs", (*netw)->link.sock, (*netw)->link.ip, (*netw)->link.port, remaining, (*netw)->deplete_socket_timeout);
1549 if ((*netw)->link.sock != INVALID_SOCKET) {
1553 int shutdown_res = SSL_shutdown((*netw)->ssl);
1554 if (shutdown_res == 0) {
1556 shutdown_res = SSL_shutdown((*netw)->ssl);
1558 if (shutdown_res < 0) {
1559 int err = SSL_get_error((*netw)->ssl, shutdown_res);
1562 SSL_shutdown((*netw)->ssl);
1563 SSL_free((*netw)->ssl);
1565 n_log(
LOG_ERR,
"SSL handle of socket %d was already NULL", (*netw)->link.sock);
1571 shutdown((*netw)->link.sock, SHUT_WR);
1573 if ((*netw)->wait_close_timeout > 0) {
1575 char buffer[4096] =
"";
1577 for (
int it = 0; it < ((*netw)->wait_close_timeout * 1000000); it += 100000) {
1578 ssize_t res = recv((*netw)->link.sock, buffer, 4096, NETFLAGS);
1583 if (error != ENOTCONN && error != 10057 && error != EINTR && error != ECONNRESET)
1586 n_log(
LOG_ERR,
"read returned error %d when closing socket %d (%s:%s): %s", error, (*netw)->link.sock,
_str((*netw)->link.ip), (*netw)->link.port,
_str(errmsg));
1589 n_log(
LOG_DEBUG,
"wait close: connection gracefully closed on socket %d (%s:%s)", (*netw)->link.sock,
_str((*netw)->link.ip), (*netw)->link.port);
1598 closesocket((*netw)->link.sock);
1604 SSL_CTX_free((*netw)->ctx);
1606 n_log(
LOG_ERR,
"SSL context of socket %d was already NULL", (*netw)->link.sock);
1618 if ((*netw)->link.rhost) {
1619 freeaddrinfo((*netw)->link.rhost);
1625 pthread_mutex_destroy(&(*netw)->recvbolt);
1626 pthread_mutex_destroy(&(*netw)->sendbolt);
1627 pthread_mutex_destroy(&(*netw)->eventbolt);
1628 sem_destroy(&(*netw)->send_blocker);
1648 char* errmsg = NULL;
1651 n_log(
LOG_ERR,
"Cannot use an allocated network. Please pass a NULL network to modify");
1662 (*netw)->link.port = strdup(
port);
1665 (*netw)->link.hints.ai_family = AF_INET;
1667 (*netw)->link.hints.ai_family = AF_INET6;
1670 (*netw)->link.hints.ai_family = AF_UNSPEC;
1673 (*netw)->link.hints.ai_flags = AI_PASSIVE;
1675 (*netw)->link.hints.ai_socktype = SOCK_STREAM;
1676 (*netw)->link.hints.ai_protocol = IPPROTO_TCP;
1677 (*netw)->link.hints.ai_canonname = NULL;
1678 (*netw)->link.hints.ai_next = NULL;
1680 error = getaddrinfo(
addr,
port, &(*netw)->link.hints, &(*netw)->link.rhost);
1686 (*netw)->addr_infos_loaded = 1;
1692 struct addrinfo* rp = NULL;
1693 for (rp = (*netw)->link.rhost; rp != NULL; rp = rp->ai_next) {
1694 (*netw)->link.sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
1695 if ((*netw)->link.sock == INVALID_SOCKET) {
1704 if (bind((*netw)->link.sock, rp->ai_addr, rp->ai_addrlen) == 0) {
1712 if (!inet_ntop(rp->ai_family,
get_in_addr(rp->ai_addr), ip, 64)) {
1719 (*netw)->link.ip = ip;
1726 closesocket((*netw)->link.sock);
1736 (*netw)->nb_pending = nbpending;
1737 listen((*netw)->link.sock, (*netw)->nb_pending);
1754 int tmp = 0, error = 0;
1755 char* errmsg = NULL;
1757#if defined(__linux__) || defined(__sun) || defined(_AIX)
1758 socklen_t sin_size = 0;
1778 int secs = blocking / 1000;
1779 int usecs = (blocking % 1000) * 1000;
1780 struct timeval select_timeout = {secs, usecs};
1783 FD_SET(from->
link.
sock, &accept_set);
1784 FD_ZERO(&accept_set);
1786 int ret = select(from->
link.
sock + 1, &accept_set, NULL, NULL, &select_timeout);
1792 n_log(
LOG_DEBUG,
"error on select with timeout %ds (%d.%ds), neterrno: %s", blocking, secs, usecs,
_str(errmsg));
1796 }
else if (ret == 0) {
1802 if (FD_ISSET(from->
link.
sock, &accept_set)) {
1821 }
else if (blocking == -1) {
1830 if (error != EINTR) {
1831 n_log(
LOG_ERR,
"accept returned an invalid socket (-1), neterrno: %s", strerror(error));
1888 if (SSL_accept(
netw->
ssl) <= 0) {
1936 n_log(
LOG_ERR,
"Empty messages are not supported. msg(%p)->lenght=%d", msg, msg->
length);
1973 n_log(
LOG_ERR,
"Empty messages are not supported. msg(%p)->lenght=%d", str, length);
2019 N_STR* nstrptr = NULL;
2021 unsigned int secs = 0;
2022 unsigned int usecs = 0;
2027 if (refresh > 999999) {
2028 secs = refresh / 1000000;
2029 usecs = refresh % 1000000;
2035 n_log(
LOG_DEBUG,
"wait from socket %d, refresh: %zu usec (%zu secs, %zu usecs), timeout %zu usec",
netw->
link.
sock, refresh, secs, usecs, timeout);
2044 if (timed >= refresh)
2046 if (timed == 0 || timed < refresh) {
2107 ssize_t net_status = 0;
2122 int message_sent = 0;
2123 while (message_sent == 0 && !
DONE) {
2133 memcpy(nboct, &nboctet,
sizeof(uint32_t));
2144 if (ptr->
written <= UINT_MAX) {
2148 nboctet = htonl(state);
2149 memcpy(nboct, &nboctet,
sizeof(uint32_t));
2158 nboctet = htonl((uint32_t)ptr->
written);
2159 memcpy(nboct, &nboctet,
sizeof(uint32_t));
2180 n_log(
LOG_ERR,
"discarded packet of size %zu which is greater than %" PRIu32, ptr->
written, UINT_MAX);
2215#if !defined(__linux__)
2227 ssize_t net_status = 0;
2229 uint32_t nboctet = 0,
2235 N_STR* recvdmsg = NULL;
2253 if (net_status < 0) {
2256 memcpy(&nboctet, nboct,
sizeof(uint32_t));
2257 tmpstate = ntohl(nboctet);
2266 if (net_status < 0) {
2269 memcpy(&nboctet, nboct,
sizeof(uint32_t));
2270 tmpstate = ntohl(nboctet);
2279 if (!recvdmsg->
data) {
2282 recvdmsg->
length = nboctet + 1;
2287 if (net_status < 0) {
2332#if !defined(__linux__)
2345 int thr_engine_status = 0;
2352 n_log(
LOG_ERR,
"Thread engine status already stopped for network %p",
netw);
2359 for (
int it = 0; it < 10; it++) {
2388 char* errmsg = NULL;
2395 char* tmp_buf = buf;
2410 }
else if (error == ECONNRESET || error == ENOTCONN) {
2421 send(s, NULL, 0, 0);
2439 char* errmsg = NULL;
2446 char* tmp_buf = buf;
2461 }
else if (br == 0) {
2467 n_log(
LOG_ERR,
"socket %d recv returned %d, error: %s", s, br,
_str(errmsg));
2494 char* errmsg = NULL;
2504#if OPENSSL_VERSION_NUMBER < 0x1010107fL
2505 int status = SSL_write(ssl, buf, (
int)(n - bcount));
2506 bs = (status > 0) ? (
size_t)status : 0;
2508 int status = SSL_write_ex(ssl, buf, (
size_t)(n - bcount), &bs);
2512 bcount += (ssize_t)bs;
2515 int ssl_error = SSL_get_error(ssl, status);
2516 if (ssl_error == SSL_ERROR_WANT_READ || ssl_error == SSL_ERROR_WANT_WRITE) {
2521 switch (ssl_error) {
2522 case SSL_ERROR_SYSCALL:
2524 n_log(
LOG_ERR,
"socket %d SSL_read syscall error: connection closed by peer", s);
2528 n_log(
LOG_ERR,
"socket %d SSL_read returned %d, error: %s", s, bs, ERR_reason_error_string(ERR_get_error()));
2532 n_log(
LOG_ERR,
"socket %d SSL_read returned %d, errno: %s", s, bs,
_str(errmsg));
2559 char* errmsg = NULL;
2566 while (bcount < n) {
2569#if OPENSSL_VERSION_NUMBER < 0x10101000L
2570 int status = SSL_read(ssl, buf, (
int)(n - bcount));
2571 br = (status > 0) ? (
size_t)status : 0;
2573 int status = SSL_read_ex(ssl, buf, (
size_t)(n - bcount), &br);
2577 bcount += (ssize_t)br;
2580 int ssl_error = SSL_get_error(ssl, status);
2581 if (ssl_error == SSL_ERROR_WANT_READ || ssl_error == SSL_ERROR_WANT_WRITE) {
2586 switch (ssl_error) {
2587 case SSL_ERROR_SYSCALL:
2589 n_log(
LOG_ERR,
"socket %d SSL_read syscall error: connection closed by peer", s);
2593 n_log(
LOG_ERR,
"socket %d SSL_read returned %d, error: %s", s, br, ERR_reason_error_string(ERR_get_error()));
2597 n_log(
LOG_ERR,
"socket %d SSL_read returned %d, errno: %s", s, br,
_str(errmsg));
2621 char* errmsg = NULL;
2637 bs = send(s, ptr, (
size_t)(
HEAD_SIZE - bcount), NETFLAGS);
2645 n_log(
LOG_ERR,
"Socket %d sending Error %d when sending head size, neterrno: %s", s, bs,
_str(errmsg));
2656 bs = send(s, ptr, (
size_t)(
HEAD_CODE - bcount), NETFLAGS);
2663 n_log(
LOG_ERR,
"Socket %d sending Error %d when sending head code, neterrno: %s", s, bs,
_str(errmsg));
2674 bs = send(s, buf, (
size_t)(n - bcount), NETFLAGS);
2682 n_log(
LOG_ERR,
"Socket %d sending Error %d when sending message of size %d, neterrno: %s", s, bs, n,
_str(errmsg));
2702 long int tmpnb = 0, size = 0;
2706 char* errmsg = NULL;
2716 br = recv(s, ptr, (
size_t)(
HEAD_SIZE - bcount), NETFLAGS);
2722 if (br == 0 && bcount == (
HEAD_SIZE - bcount))
2732 tmpnb = strtol(head, NULL, 10);
2733 if (tmpnb == LONG_MIN || tmpnb == LONG_MAX) {
2734 n_log(
LOG_ERR,
"Size received ( %ld ) can not be determined on socket %d", tmpnb, s);
2745 br = recv(s, ptr, (
size_t)(
HEAD_CODE - bcount), NETFLAGS);
2751 if (br == 0 && bcount == (
HEAD_CODE - bcount))
2755 n_log(
LOG_ERR,
"Socket %d receive %d Error , neterrno: %s", s, br,
_str(errmsg));
2761 tmpnb = strtol(code, NULL, 10);
2762 if (tmpnb <= INT_MIN || tmpnb >= INT_MAX) {
2763 n_log(
LOG_ERR,
"Code received ( %ld ) too big or too little to be valid code on socket %d", tmpnb, s);
2767 (*_code) = (int)tmpnb;
2773 Malloc((*buf),
char, (
size_t)(size + 1));
2782 while (bcount < size) {
2784 br = recv(s, ptr, (
size_t)(size - bcount), NETFLAGS);
2790 if (br == 0 && bcount == (size - bcount))
2794 n_log(
LOG_ERR,
"Socket %d receive %d Error neterrno: %s", s, br,
_str(errmsg));
2849 __n_assert(netw_pool && (*netw_pool),
return FALSE);
2852 if ((*netw_pool)->pool)
2854 unlock((*netw_pool)->rwlock);
3015 N_STR* tmpstr = NULL;
3034 N_STR* tmpstr = NULL;
3058 N_STR* tmpstr = NULL;
3080 N_STR* tmpstr = NULL;
3100 N_STR* tmpstr = NULL;
3118 N_STR* tmpstr = NULL;
3135 size_t encoded_size = 0;
3137 for (
size_t i = 0; i < len; i++) {
3138 unsigned char c = (
unsigned char)str[i];
3139 if (isalnum(c) || c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~') {
3146 return encoded_size;
3158 static const char* hex =
"0123456789ABCDEF";
3160 char* encoded = (
char*)malloc(encoded_size + 1);
3166 char* pbuf = encoded;
3168 for (
size_t i = 0; i < len; i++) {
3169 unsigned char c = (
unsigned char)str[i];
3170 if (isalnum(c) || c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~') {
3174 *pbuf++ = hex[c >> 4];
3175 *pbuf++ = hex[c & 0xF];
3191 const char* space = strchr(request,
' ');
3193 if (space == NULL) {
3199 size_t method_length = (size_t)(space - request);
3202 char* method = (
char*)malloc(method_length + 1);
3204 if (method == NULL) {
3210 strncpy(method, request, method_length);
3211 method[method_length] =
'\0';
3233 const char* content_type_header = strstr(request,
"Content-Type:");
3234 if (content_type_header) {
3235 const char* start = content_type_header + strlen(
"Content-Type: ");
3236 const char* end = strstr(start,
"\r\n");
3238 size_t length = (size_t)(end - start);
3248 const char* content_length_header = strstr(request,
"Content-Length:");
3249 if (content_length_header) {
3250 const char* start = content_length_header + strlen(
"Content-Length: ");
3252 unsigned long tmp_cl = strtoul(start, NULL, 10);
3256#if ULONG_MAX > SIZE_MAX
3257 if (error == ERANGE || tmp_cl > SIZE_MAX) {
3259 if (error == ERANGE) {
3261 n_log(
LOG_ERR,
"could not get content_length for request %p, returned %s", request, strerror(error));
3269 const char* body_start = strstr(request,
"\r\n\r\n");
3304 __n_assert(request && strlen(request) > 0,
return FALSE);
3308 strncpy(url,
"/", size - 1);
3309 url[size - 1] =
'\0';
3312 const char* first_space = strchr(request,
' ');
3318 const char* second_space = strchr(first_space + 1,
' ');
3319 if (!second_space) {
3324 size_t len = (size_t)(second_space - first_space - 1);
3329 strncpy(url, first_space + 1, len);
3342 char* decoded = malloc(strlen(str) + 1);
3348 if (isxdigit((
unsigned char)str[1]) && isxdigit((
unsigned char)str[2])) {
3350 if (sscanf(str + 1,
"%2x", &value) >= 1) {
3354 n_log(
LOG_ERR,
"sscanf could not parse char *str (%p) for a %%2x", str);
3361 }
else if (*str ==
'+') {
3381 char* data = strdup(post_data);
3385 char* ampersand_pos;
3389 while (pair != NULL) {
3391 ampersand_pos = strchr(pair,
'&');
3394 if (ampersand_pos != NULL) {
3395 *ampersand_pos =
'\0';
3399 char* equal_pos = strchr(pair,
'=');
3400 if (equal_pos != NULL) {
3403 char* value = equal_pos + 1;
3409 free(decoded_value);
3412 pair = (ampersand_pos != NULL) ? (ampersand_pos + 1) : NULL;
3416 return post_data_table;
3428 char url_copy[1024];
3429 strncpy(url_copy, url,
sizeof(url_copy) - 1);
3430 url_copy[
sizeof(url_copy) - 1] =
'\0';
3433 char* query_start = strchr(url_copy,
'?');
3435 *query_start =
'\0';
3439 const char* ext = strrchr(url_copy,
'.');
3447 if (strcmp(ext,
".html") == 0 || strcmp(ext,
".htm") == 0) {
3449 }
else if (strcmp(ext,
".txt") == 0) {
3450 return "text/plain";
3451 }
else if (strcmp(ext,
".jpg") == 0 || strcmp(ext,
".jpeg") == 0) {
3452 return "image/jpeg";
3453 }
else if (strcmp(ext,
".png") == 0) {
3455 }
else if (strcmp(ext,
".gif") == 0) {
3457 }
else if (strcmp(ext,
".css") == 0) {
3459 }
else if (strcmp(ext,
".js") == 0) {
3460 return "application/javascript";
3461 }
else if (strcmp(ext,
".json") == 0) {
3462 return "application/json";
3463 }
else if (strcmp(ext,
".xml") == 0) {
3464 return "application/xml";
3465 }
else if (strcmp(ext,
".pdf") == 0) {
3466 return "application/pdf";
3467 }
else if (strcmp(ext,
".zip") == 0) {
3468 return "application/zip";
3469 }
else if (strcmp(ext,
".mp4") == 0) {
3471 }
else if (strcmp(ext,
".mp3") == 0) {
3472 return "audio/mpeg";
3473 }
else if (strcmp(ext,
".wav") == 0) {
3475 }
else if (strcmp(ext,
".ogg") == 0) {
3489 switch (status_code) {
3493 return "No Content";
3495 return "Not Modified";
3499 return "Internal Server Error";
3514 const time_t now = time(NULL);
3517 if (gmtime_s(&gmt, &now) != 0) {
3522 if (!gmtime_r(&now, &gmt)) {
3527 if (strftime(buffer, buffer_size,
"%a, %d %b %Y %H:%M:%S GMT", &gmt) == 0) {
3547 __n_assert(additional_headers,
return FALSE);
3550 const char* connection_type =
"close";
3553 char date_buffer[128] =
"";
3556 if ((*http_response)) {
3557 (*http_response)->written = 0;
3560 if (!body || body->
written == 0) {
3563 "HTTP/1.1 %d %s\r\n"
3566 "Content-Length: 0\r\n"
3568 "Connection: %s\r\n\r\n",
3569 status_code, status_message, date_buffer, server_name, additional_headers, connection_type);
3574 "HTTP/1.1 %d %s\r\n"
3577 "Content-Type: %s\r\n"
3578 "Content-Length: %zu\r\n"
3580 "Connection: %s\r\n\r\n",
3581 status_code, status_message, date_buffer, server_name, content_type, body->
written, additional_headers, connection_type);
3582 nstrcat((*http_response), body);
int mode
Network for managing conenctions.
NETWORK * netw
Network for server mode, accepting incomming.
#define init_lock(__rwlock_mutex)
Macro for initializing a rwlock.
#define FreeNoLog(__ptr)
Free Handler without log.
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
#define __n_assert(__ptr, __ret)
macro to assert things
#define _str(__PTR)
define true
#define rw_lock_destroy(__rwlock_mutex)
Macro to destroy rwlock mutex.
#define CALL_RETRY(__retvar, __expression, __max_tries, __delay)
TEMP_FAILURE gnu macro portable version.
#define unlock(__rwlock_mutex)
Macro for releasing read/write lock a rwlock mutex.
#define write_lock(__rwlock_mutex)
Macro for acquiring a write lock on a rwlock mutex.
#define Free(__ptr)
Free Handler to get errors.
#define read_lock(__rwlock_mutex)
Macro for acquiring a read lock on a rwlock mutex.
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
#define N_ENUM_DEFINE(MACRO_DEFINITION, enum_name)
Macro to define an N_ENUM.
#define N_ENUM_ENTRY(class, method)
helper to build an N_ENUM
size_t nb_keys
total number of used keys in the table
int ht_get_ptr(HASH_TABLE *table, const char *key, void **val)
get pointer at 'key' from 'table'
#define ht_foreach(__ITEM_, __HASH_)
ForEach macro helper (classic / old)
int destroy_ht(HASH_TABLE **table)
empty a table and destroy it
int ht_remove(HASH_TABLE *table, const char *key)
remove and delete node at key in table
HASH_TABLE * new_ht(size_t size)
Create a hash table with the given size.
int ht_put_string(HASH_TABLE *table, const char *key, char *string)
put a string value (copy/dup) with given key in the targeted hash table
int ht_put_ptr(HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr))
put a pointer to the string value with given key in the targeted hash table
#define hash_val(node, type)
Cast a HASH_NODE element.
structure of a hash table node
structure of a hash table
size_t nb_items
number of item currently in the list
#define list_shift(__LIST_, __TYPE_)
Shift macro helper for void pointer casting.
int list_empty(LIST *list)
Empty a LIST list of pointers.
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
#define remove_list_node(__LIST_, __NODE_, __TYPE_)
Remove macro helper for void pointer casting.
int list_destroy(LIST **list)
Empty and Free a list container.
LIST_NODE * list_search(LIST *list, void *ptr)
search ptr in list
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Structure of a generic list node.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
#define LOG_INFO
informational
size_t written
size of the written data inside the string
size_t length
length of string (in case we wanna keep information after the 0 end of string value)
void free_nstr_ptr(void *ptr)
Free a N_STR pointer structure.
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
#define nstrcat(__nstr_dst, __nstr_src)
Macro to quickly concatenate two N_STR.
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
A box including a string and his lenght.
void u_sleep(unsigned int usec)
wrapper around usleep for API consistency
N_STR * netmsg_make_position_msg(int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp)
make a network NETMSG_POSITION message with given parameters
N_STR * netmsg_make_ident(int type, int id, N_STR *name, N_STR *passwd)
Add a formatted NETWMSG_IDENT message to the specified network.
N_STR * netmsg_make_quit_msg(void)
make a generic network NETMSG_QUIT message
N_STR * netmsg_make_ping(int type, int id_from, int id_to, int time)
Make a ping message to send to a network.
N_STR * netmsg_make_string_msg(int id_from, int id_to, N_STR *name, N_STR *chan, N_STR *txt, int color)
make a network NETMSG_STRING message with given parameters
char * ip
ip of the connected socket
N_SOCKET link
networking socket
char * certificate
openssl certificate file
int threaded_engine_status
Threaded network engine state for this network.
pthread_t send_thr
sending thread
int nb_pending
Nb pending connection,if listening.
int so_reuseaddr
so reuseaddr state
pthread_t recv_thr
receiving thread
pthread_rwlock_t rwlock
thread safety
struct sockaddr_storage raddr
connected remote addr
pthread_mutex_t eventbolt
mutex for threaded access of state event
const SSL_METHOD * method
SSL method container.
int deplete_socket_timeout
deplete socket send buffer timeout ( 0 disabled, > 0 wait for timeout and check unset/unack datas)
int deplete_queues_timeout
deplete network queues timeout ( 0 disabled, > 0 wait for timeout and check unset/unack datas)
int nb_running_threads
nb running threads, if > 0 thread engine is still running
pthread_mutex_t recvbolt
mutex for threaded access of recv buf
pthread_mutex_t sendbolt
mutex for threaded access of send_buf
int send_queue_consecutive_wait
send queue consecutive pool interval, used when there are still items to send, in usec
int so_rcvtimeo
send timeout value
int tcpnodelay
state of naggle algorythm, 0 untouched, 1 forcibly disabled
SOCKET sock
a normal socket
char * port
port of socket
LIST * recv_buf
reveicing buffer (for incomming usage)
int user_id
if part of a user property, id of the user
sem_t send_blocker
block sending func
SSL_CTX * ctx
SSL context holder.
int so_sndbuf
size of the socket send buffer, 0 untouched, else size in bytes
int so_sndtimeo
send timeout value
struct addrinfo hints
address of local machine
int so_keepalive
so keepalive state
netw_func send_data
send func ptr
int addr_infos_loaded
Internal flag to know if we have to free addr infos.
uint32_t state
state of the connection , NETW_RUN, NETW_QUIT, NETW_STOP , NETW_ERR
LIST * pools
pointers to network pools if members of any
char * key
openssl key file
int so_linger
close lingering value (-1 disabled, 0 force close, >0 linger )
unsigned long int is_blocking
flag to quickly check socket mode
int crypto_algo
if encryption is on, which one (flags NETW_ENCRYPT_*)
HASH_TABLE * pool
table of clients
LIST * send_buf
sending buffer (for outgoing queuing )
int mode
NETWORK mode , 1 listening, 0 connecting.
int so_rcvbuf
size of the socket recv buffer, 0 untouched, else size in bytes
netw_func recv_data
receive func ptr
int wait_close_timeout
network wait close timeout value ( < 1 disabled, >= 1 timeout sec )
#define NETW_SOCKET_ERROR
code for a socekt error
int netw_send_string_to_all(NETWORK *netw, N_STR *name, N_STR *chan, N_STR *txt, int color)
Add a string to the network, aiming all server-side users.
int netw_pool_broadcast(NETWORK_POOL *netw_pool, NETWORK *from, N_STR *net_msg)
add net_msg to all network in netork pool
N_STR * netw_get_msg(NETWORK *netw)
Get a message from aimed NETWORK.
int netw_add_msg(NETWORK *netw, N_STR *msg)
Add a message to send in aimed NETWORK.
ssize_t send_ssl_data(void *netw, char *buf, uint32_t n)
send data onto the socket
char * netw_extract_http_request_type(const char *request)
function to extract the request method from an http request
int netw_get_queue_status(NETWORK *netw, size_t *nb_to_send, size_t *nb_to_read)
retrieve network send queue status
int netw_init_wsa(int mode, int v1, int v2)
Do not directly use, internal api.
ssize_t send_php(SOCKET s, int _code, char *buf, int n)
send data onto the socket
int netw_stop_thr_engine(NETWORK *netw)
Stop a NETWORK connection sending and receing thread.
char * netw_urlencode(const char *str, size_t len)
function to perform URL encoding
void * netw_send_func(void *NET)
Thread send function.
NETWORK * netw_accept_nonblock_from(NETWORK *from, int blocking)
make a normal blocking 'accept' .
int netw_get_url_from_http_request(const char *request, char *url, size_t size)
Helper function to extract the URL from the HTTP request line.
int netw_set_crypto(NETWORK *netw, char *key, char *certificate)
activate SSL encryption on selected network, using key and certificate
#define NETWORK_IPV6
Flag to force IPV6
int netw_get_http_date(char *buffer, size_t buffer_size)
helper function to generate the current date in HTTP format
NETWORK_POOL * netw_new_pool(size_t nb_min_element)
return a new network pool of nb_min_element
int netw_set_user_id(NETWORK *netw, int id)
associate an id and a network
ssize_t recv_data(void *netw, char *buf, uint32_t n)
recv data from the socket
int netw_init_openssl(void)
Do not directly use, internal api.
ssize_t recv_ssl_data(void *netw, char *buf, uint32_t n)
recv data from the socket
int netw_make_listening(NETWORK **netw, char *addr, char *port, int nbpending, int ip_version)
Make a NETWORK be a Listening network.
#define HEAD_SIZE
Size of a HEAD message.
int netw_start_thr_engine(NETWORK *netw)
Start the NETWORK netw Threaded Engine.
int netw_destroy_pool(NETWORK_POOL **netw_pool)
free a NETWORK_POOL *pool
#define NETWORK_IPV4
Flag to force IPV4
int netw_build_http_response(N_STR **http_response, int status_code, const char *server_name, const char *content_type, char *additional_headers, N_STR *body)
function to dynamically generate an HTTP response
void * netw_recv_func(void *NET)
To Thread Receiving function.
__netw_code_type size_t htonst(size_t value)
host to network size_t
int netw_unload_openssl(void)
Do not directly use, internal api.
#define HEAD_CODE
Code of a HEAD message.
size_t ntohst(size_t value)
network to host size_t
#define NETWORK_CONSECUTIVE_SEND_WAIT
Flag to set consecutive send waiting timeout
size_t netw_pool_nbclients(NETWORK_POOL *netw_pool)
return the number of networks in netw_pool
NETWORK * netw_accept_from_ex(NETWORK *from, size_t send_list_limit, size_t recv_list_limit, int blocking, int *retval)
make a normal 'accept' .
int netw_connect_ex(NETWORK **netw, char *host, char *port, size_t send_list_limit, size_t recv_list_limit, int ip_version, char *ssl_key_file, char *ssl_cert_file)
Use this to connect a NETWORK to any listening one.
int SOCKET
default socket declaration
#define NETW_SOCKET_DISCONNECTED
Code for a disconnected recv.
#define NETWORK_WAIT_CLOSE_TIMEOUT
Flag to set network closing wait timeout.
int netw_setsockopt(NETWORK *netw, int optname, int value)
Modify common socket options on the given netw.
int netw_set(NETWORK *netw, int flag)
Restart or reset the specified network ability.
ssize_t send_data(void *netw, char *buf, uint32_t n)
send data onto the socket
int netw_get_state(NETWORK *netw, uint32_t *state, int *thr_engine_status)
Get the state of a network.
void netw_pool_netw_close(void *netw_ptr)
close a network from a network pool
size_t netw_calculate_urlencoded_size(const char *str, size_t len)
function to calculate the required size for the URL-encoded string
#define NETW_RETRY_DELAY
Send or recv delay between retries in usec.
int deplete_send_buffer(int fd, int timeout)
wait until the socket is empty or timeout, checking each 100 msec.
NETWORK * netw_accept_from(NETWORK *from)
make a normal blocking 'accept' .
#define NETW_MAX_RETRIES
Send or recv max number of retries.
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
int netw_send_quit(NETWORK *netw)
Add a formatted NETMSG_QUIT message to the specified network.
const char * netw_get_http_status_message(int status_code)
helper function to convert status code to a human-readable message
int netw_set_blocking(NETWORK *netw, unsigned long int is_blocking)
Modify blocking socket mode.
N_STR * netw_wait_msg(NETWORK *netw, unsigned int refresh, size_t timeout)
Wait a message from aimed NETWORK.
int netw_send_string_to(NETWORK *netw, int id_to, N_STR *name, N_STR *chan, N_STR *txt, int color)
Add a string to the network, aiming a specific user.
int netw_send_ping(NETWORK *netw, int type, int id_from, int id_to, int time)
Add a ping reply to the network.
int netw_ssl_connect(NETWORK **netw, char *host, char *port, int ip_version, char *ssl_key_file, char *ssl_cert_file)
Use this to connect a NETWORK to any listening one, unrestricted send/recv lists.
NETWORK_HTTP_INFO netw_extract_http_info(char *request)
extract a lot of informations, mostly as pointers, and populate a NETWORK_HTTP_INFO structure
int netw_connect(NETWORK **netw, char *host, char *port, int ip_version)
Use this to connect a NETWORK to any listening one, unrestricted send/recv lists.
__netw_code_type
Network codes declaration.
#define NETWORK_DEPLETE_SOCKET_TIMEOUT
Flag to set send buffer depletion timeout
int netw_send_ident(NETWORK *netw, int type, int id, N_STR *name, N_STR *passwd)
Add a formatted NETWMSG_IDENT message to the specified network.
char * netw_urldecode(const char *str)
Function to decode URL-encoded data.
#define NETWORK_DEPLETE_QUEUES_TIMEOUT
Flag to set network queues depletion timeout
int netw_pool_add(NETWORK_POOL *netw_pool, NETWORK *netw)
add a NETWORK *netw to a NETWORK_POOL *pool
int netw_info_destroy(NETWORK_HTTP_INFO http_request)
destroy a NETWORK_HTTP_INFO loaded informations
HASH_TABLE * netw_parse_post_data(const char *post_data)
Function to parse POST data.
const char * netw_guess_http_content_type(const char *url)
function to guess the content type based on URL extension
ssize_t recv_php(SOCKET s, int *_code, char **buf)
recv data from the socket
int netw_send_position(NETWORK *netw, int id, double X, double Y, double vx, double vy, double acc_x, double acc_y, int time_stamp)
Add a formatted NETWMSG_IDENT message to the specified network.
int netw_pool_remove(NETWORK_POOL *netw_pool, NETWORK *netw)
remove a NETWORK *netw to a NETWORK_POOL *pool
int netw_add_msg_ex(NETWORK *netw, char *str, unsigned int length)
Add a message to send in aimed NETWORK.
@ NETW_THR_ENGINE_STARTED
@ NETW_THR_ENGINE_STOPPED
structure for splitting HTTP requests
structure of a network pool
Hash functions and table.
static void netw_init_locks(void)
void netw_ssl_print_errors(SOCKET socket)
NETWORK * netw_new(size_t send_list_limit, size_t recv_list_limit)
Return an empty allocated network ready to be netw_closed.
N_ENUM_netw_code_type
network error code
#define netstrerror(code)
BSD style errno string NO WORKING ON REDHAT.
#define neterrno
get last socket error code, linux version
static pthread_mutex_t * netw_ssl_lockarray
char * get_in_addr(struct sockaddr *sa)
get sockaddr, IPv4 or IPv6
char * netw_get_openssl_error_string()
static void netw_kill_locks(void)
Network messages , serialization tools.