MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxsocket.c
Go to the documentation of this file.
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#ifdef _WIN32
6#ifndef _WIN32_WINNT
7#define _WIN32_WINNT 0x0600
8#endif
9#include <afunix.h>
10#include <winsock2.h>
11#include <ws2tcpip.h>
12#else
13#include <errno.h>
14#include <fcntl.h>
15#include <signal.h>
16#include <sys/select.h>
17#include <unistd.h>
18
19#endif
20
21static void mx_socket_store_inet_address(MXSocket *sock, const struct sockaddr *addr, socklen_t addrlen) {
22 if (sock == nullptr || addr == nullptr)
23 return;
24
25 sock->addrlen = addrlen;
26 if (addr->sa_family == AF_INET6) {
27 size_t len_size = ((size_t)addrlen > sizeof(sock->inet6)) ? sizeof(sock->inet6) : (size_t)addrlen;
28 memcpy(&sock->inet6, addr, len_size);
29 } else if (addr->sa_family == AF_INET) {
30 size_t len_size = ((size_t)addrlen > sizeof(sock->inet)) ? sizeof(sock->inet) : (size_t)addrlen;
31 memcpy(&sock->inet, addr, len_size);
32 }
33}
34
35static bool mx_socket_inet_listen(MXSocket *sock, const char *port, int backlog, int type, int family) {
36 if (port == nullptr)
37 return false;
38
39 if (!mx_socket_init(sock))
40 return false;
41
42 struct addrinfo hints;
43 struct addrinfo *rt, *rp;
45 int optval = 1;
46
47 memset(&hints, 0, sizeof(struct addrinfo));
48 hints.ai_canonname = nullptr;
49 hints.ai_addr = nullptr;
50 hints.ai_next = nullptr;
51 hints.ai_socktype = type;
52 hints.ai_family = family;
53 hints.ai_flags = AI_PASSIVE;
54 s = getaddrinfo(nullptr, port, &hints, &rt);
55 if (s != 0)
56 return false;
57
58 for (rp = rt; rp != NULL; rp = rp->ai_next) {
59 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
60#ifdef _WIN32
61 if (sfd == INVALID_SOCKET)
62#else
63 if (sfd == -1)
64#endif
65 continue;
66
67#ifdef _WIN32
68 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(optval)) == -1) {
69#else
70 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
71#endif
72 mx_close_socket(sfd);
73 freeaddrinfo(rt);
74 return false;
75 }
76
77 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
78 break;
79
80 if (sfd != NULL_SOCKET)
81 mx_close_socket(sfd);
82 sfd = NULL_SOCKET;
83 }
84
85 if (sfd == NULL_SOCKET) {
86 freeaddrinfo(rt);
87 return false;
88 }
89
90 if (rp != nullptr && sfd != NULL_SOCKET) {
91 if (listen(sfd, backlog) == -1) {
92 freeaddrinfo(rt);
93 mx_close_socket(sfd);
94 return false;
95 }
96 sock->sockfd = sfd;
97 mx_socket_store_inet_address(sock, rp->ai_addr, rp->ai_addrlen);
98 } else {
99 if (sfd != NULL_SOCKET)
100 mx_close_socket(sfd);
101 freeaddrinfo(rt);
102 return false;
103 }
104
105 freeaddrinfo(rt);
106 return true;
107}
108
109static bool mx_socket_inet_connect(MXSocket *sock, const char *host, const char *port, int type, int family) {
110 if (host == nullptr || port == nullptr)
111 return false;
112
113 if (!mx_socket_init(sock))
114 return false;
115
116 struct addrinfo hints;
117 struct addrinfo *rt, *rp;
118 mx_socket_fd sfd = NULL_SOCKET, s;
119 memset(&hints, 0, sizeof(struct addrinfo));
120 hints.ai_canonname = nullptr;
121 hints.ai_addr = nullptr;
122 hints.ai_next = nullptr;
123 hints.ai_family = family;
124 hints.ai_socktype = type;
125 s = getaddrinfo(host, port, &hints, &rt);
126 if (s != 0) {
127 errno = ENOSYS;
128 return false;
129 }
130 for (rp = rt; rp != nullptr; rp = rp->ai_next) {
131 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
132#ifdef _WIN32
133 if (sfd == INVALID_SOCKET)
134#else
135 if (sfd == -1)
136#endif
137 continue;
138
139 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
140 break;
141
142 if (sfd != NULL_SOCKET) {
143 mx_close_socket(sfd);
144 sfd = NULL_SOCKET;
145 }
146 }
147
148 if (rp != nullptr) {
149 sock->sockfd = sfd;
150 mx_socket_store_inet_address(sock, rp->ai_addr, rp->ai_addrlen);
151 } else {
152 freeaddrinfo(rt);
153 if (sfd != NULL_SOCKET)
154 mx_close_socket(sfd);
155 return false;
156 }
157
158 freeaddrinfo(rt);
159 return true;
160}
161
162static bool mx_socket_inet_bind(MXSocket *sock, const char *port, int family) {
163 if (!mx_socket_init(sock) || port == nullptr)
164 return false;
165
166 mx_socket_fd sockfd = NULL_SOCKET;
167 struct addrinfo hints = {};
168 struct addrinfo *result = nullptr;
169 struct addrinfo *rp = nullptr;
170 hints.ai_family = family;
171 hints.ai_socktype = SOCK_DGRAM;
172 hints.ai_flags = AI_PASSIVE;
173 int s = getaddrinfo(nullptr, port, &hints, &result);
174 if (s != 0) {
175 return false;
176 }
177 bool set_value = false;
178 for (rp = result; rp != nullptr; rp = rp->ai_next) {
179 sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
180#ifdef _WIN32
181 if (sockfd == INVALID_SOCKET)
182#else
183 if (sockfd == -1)
184#endif
185 continue;
186
187 if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) == 0) {
188 mx_socket_store_inet_address(sock, rp->ai_addr, rp->ai_addrlen);
189 set_value = true;
190 break;
191 }
192 mx_close_socket(sockfd);
193 sockfd = NULL_SOCKET;
194 }
195 freeaddrinfo(result);
196 if (!set_value)
197 return false;
198 sock->sockfd = sockfd;
199 return true;
200}
201
202[[nodiscard]] bool mx_socket_unix_listen(MXSocket *sock, const char *path, int backlog, int type) {
203 if (path == nullptr)
204 return false;
205 if (!mx_socket_init(sock))
206 return false;
207 struct sockaddr_un addr;
208 mx_socket_fd sockfd = socket(AF_UNIX, type, 0);
209#ifdef _WIN32
210 if (sockfd == INVALID_SOCKET) {
211#else
212 if (sockfd == -1) {
213#endif
214 perror("socket");
215 return false;
216 }
217 if (remove(path) == -1 && errno == ENOENT) {
218 perror("remove");
219 mx_close_socket(sockfd);
220 return false;
221 }
222 memset(&addr, 0, sizeof(struct sockaddr_un));
223 strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
224 addr.sun_family = AF_UNIX;
225 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
226 perror("bind");
227 mx_close_socket(sockfd);
228 return false;
229 }
230
231 if (listen(sockfd, backlog) == -1) {
232 perror("listen");
233 mx_close_socket(sockfd);
234 return false;
235 }
236 sock->sockfd = sockfd;
237 sock->sun = addr;
238 return true;
239}
240
241[[nodiscard]] bool mx_socket_unix_connect(MXSocket *sock, const char *path, int type) {
242 if (path == nullptr)
243 return false;
244 if (!mx_socket_init(sock))
245 return false;
246 mx_socket_fd sockfd = NULL_SOCKET;
247 struct sockaddr_un addr;
248 memset(&addr, 0, sizeof(struct sockaddr_un));
249 addr.sun_family = AF_UNIX;
250 sockfd = socket(AF_UNIX, type, 0);
251#ifdef _WIN32
252 if (sockfd == INVALID_SOCKET) {
253#else
254 if (sockfd == -1) {
255#endif
256 perror("socket");
257 return false;
258 }
259 strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
260 if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
261 perror("connect");
262 mx_close_socket(sockfd);
263 return false;
264 }
265 sock->sockfd = sockfd;
266 sock->sun = addr;
267 return true;
268}
269
270[[nodiscard]] bool mx_socket_listen(MXSocket *sock, const char *port, int backlog, int type) {
271 return mx_socket_inet_listen(sock, port, backlog, type, AF_INET);
272}
273
274[[nodiscard]] bool mx_socket_ipv6_listen(MXSocket *sock, const char *port, int backlog, int type) {
275 return mx_socket_inet_listen(sock, port, backlog, type, AF_INET6);
276}
277
278[[nodiscard]] bool mx_socket_accept(const MXSocket *input, MXSocket *output) {
279 if (input == nullptr || output == nullptr)
280 return false;
281
282 if (!mx_socket_valid(input))
283 return false;
284
285 mx_socket_fd newfd = accept(input->sockfd, 0, 0);
286#ifdef _WIN32
287 if (newfd == INVALID_SOCKET)
288 return false;
289 u_long mode = input->blocking ? 0 : 1;
290 if (ioctlsocket(newfd, FIONBIO, &mode) != 0) {
291 mx_close_socket(newfd);
292 return false;
293 }
294#else
295 if (newfd == NULL_SOCKET)
296 return false;
297
298 int flags = fcntl(newfd, F_GETFL);
299 if (flags == -1) {
300 close(newfd);
301 return false;
302 }
303 if (input->blocking)
304 flags &= ~O_NONBLOCK;
305 else
306 flags |= O_NONBLOCK;
307 if (fcntl(newfd, F_SETFL, flags) == -1) {
308 mx_close_socket(newfd);
309 return false;
310 }
311#endif
312 if (mx_socket_valid(output))
313 mx_socket_close(output);
314 output->sockfd = newfd;
315 output->addrlen = input->addrlen;
316 output->blocking = input->blocking;
317 output->sun = input->sun;
318 output->inet = input->inet;
319 output->inet6 = input->inet6;
320 return true;
321}
322
324 if (sock == nullptr)
325 return;
326 if (mx_socket_valid(sock))
327 mx_close_socket(sock->sockfd);
328 sock->sockfd = NULL_SOCKET;
329}
330
331[[nodiscard]] bool mx_socket_set_blocking(MXSocket *sock, bool state) {
332 if (sock == nullptr)
333 return false;
334 if (mx_socket_valid(sock)) {
335#ifdef _WIN32
336 u_long mode = state ? 0 : 1;
337 if (ioctlsocket(sock->sockfd, FIONBIO, &mode) != 0) {
338 fprintf(stderr, "Error setting flags for: %d\n", (int)sock->sockfd);
339 return false;
340 }
341#else
342 int flags = fcntl(sock->sockfd, F_GETFL);
343 if (flags == -1) {
344 fprintf(stderr, "Error getting flags for: %d\n", sock->sockfd);
345 return false;
346 }
347 if (state)
348 flags &= ~O_NONBLOCK;
349 else
350 flags |= O_NONBLOCK;
351 if (fcntl(sock->sockfd, F_SETFL, flags) == -1) {
352 fprintf(stderr, "Error setting flags for: %d\n", sock->sockfd);
353 return false;
354 }
355#endif
356 sock->blocking = state;
357 } else
358 return false;
359 return true;
360}
361
362[[nodiscard]] bool mx_socket_connect(MXSocket *sock, const char *host, const char *port, int type) {
363 return mx_socket_inet_connect(sock, host, port, type, AF_INET);
364}
365
366[[nodiscard]] bool mx_socket_ipv6_connect(MXSocket *sock, const char *host, const char *port, int type) {
367 return mx_socket_inet_connect(sock, host, port, type, AF_INET6);
368}
369
370[[nodiscard]] bool mx_socket_bind(MXSocket *sock, const char *port) {
371 return mx_socket_inet_bind(sock, port, AF_INET);
372}
373
374[[nodiscard]] bool mx_socket_ipv6_bind(MXSocket *sock, const char *port) {
375 return mx_socket_inet_bind(sock, port, AF_INET6);
376}
377
378[[nodiscard]] bool mx_socket_unix_bind(MXSocket *s, const char *path) {
379 if (!mx_socket_init(s) || path == nullptr)
380 return false;
381
382 mx_socket_fd sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
383#ifdef _WIN32
384 if (sockfd == INVALID_SOCKET) {
385#else
386 if (sockfd == -1) {
387#endif
388 perror("socket");
389 return false;
390 }
391 remove(path);
392 struct sockaddr_un caddy;
393 memset(&caddy, 0, sizeof(struct sockaddr_un));
394 caddy.sun_family = AF_UNIX;
395 strncpy(caddy.sun_path, path, sizeof(caddy.sun_path) - 1);
396 if (bind(sockfd, (struct sockaddr *)&caddy, sizeof(caddy)) == -1) {
397 perror("bind");
398 mx_close_socket(sockfd);
399 return false;
400 }
401 s->sun = caddy;
402 s->addrlen = sizeof(caddy);
403 s->sockfd = sockfd;
404 return true;
405}
406
407[[nodiscard]] bool mx_socket_init(MXSocket *sock) {
408 if (sock == nullptr)
409 return false;
410 memset(sock, 0, sizeof(MXSocket));
411 sock->sockfd = NULL_SOCKET;
412 sock->blocking = true;
413 return true;
414}
415
416[[nodiscard]] bool mx_socket_valid(const MXSocket *sock) {
417 if (sock == nullptr)
418 return false;
419 return sock->sockfd != NULL_SOCKET;
420}
421
422ssize_t mx_socket_read(MXSocket *sock, void *buf, size_t len, int flags) {
423 if (sock == nullptr || buf == nullptr || len == 0)
424 return -1;
425 if (!mx_socket_valid(sock)) {
426 mx_set_err(EBADF);
427 return -1;
428 }
429 return recv(sock->sockfd, (char *)buf, MX_LEN(len), flags);
430}
431
432ssize_t mx_socket_send(MXSocket *sock, const void *buf, size_t len, int flags) {
433 if (sock == nullptr || buf == nullptr || len == 0)
434 return -1;
435 if (!mx_socket_valid(sock)) {
436 mx_set_err(EBADF);
437 return -1;
438 }
439 return send(sock->sockfd, (const char *)buf, MX_LEN(len), flags);
440}
441
442[[nodiscard]] bool mx_socket_is_open(const MXSocket *sock) {
443 if (sock == nullptr || !mx_socket_valid(sock))
444 return false;
445 char c = 0;
446#ifdef _WIN32
447 ssize_t r = recv(sock->sockfd, &c, 1, MSG_PEEK);
448#elif defined(MX_HAVE_MSG_DONTWAIT)
449 ssize_t r = recv(sock->sockfd, &c, 1, MSG_PEEK | MSG_DONTWAIT);
450#else
451 fd_set readfds;
452 FD_ZERO(&readfds);
453 FD_SET(sock->sockfd, &readfds);
454
455 struct timeval timeout = {0, 0};
456 const int ready = select((int)(sock->sockfd + 1), &readfds, nullptr, nullptr, &timeout);
457 if (ready < 0)
458 return false;
459 if (ready == 0)
460 return true;
461
462 ssize_t r = recv(sock->sockfd, &c, 1, MSG_PEEK);
463#endif
464 if (r == 0)
465 return false;
466 if (r > 0)
467 return true;
468 if (r < 0 && (SOCK_ERRNO == SOCK_EAGAIN || SOCK_ERRNO == SOCK_EWOULDBLOCK)) {
469 return true;
470 }
471 return false;
472}
473
474[[nodiscard]] bool mx_socket_readline(MXSocket *sock, char **buffer, size_t *size) {
475 if (sock == nullptr || buffer == nullptr || size == nullptr)
476 return false;
477
478 if (!mx_socket_valid(sock)) {
479 mx_set_err(EBADF);
480 return false;
481 }
482
483 *buffer = nullptr;
484 *size = 0;
485
486 size_t init_size = 4096;
487 char *temp = (char *)malloc(init_size + 1);
488 if (temp == nullptr)
489 return false;
490 char c = 0;
491 size_t index = 0;
492 while (1) {
493 ssize_t read_val = recv(sock->sockfd, &c, 1, 0);
494 if (read_val > 0) {
495 if (c == '\n')
496 break;
497 if (index >= init_size) {
498 size_t new_init_size = init_size * 2;
499 char *t = (char *)realloc(temp, new_init_size + 1);
500 if (t == nullptr) {
501 free(temp);
502 return false;
503 }
504 temp = t;
505 init_size = new_init_size;
506 }
507 temp[index++] = c;
508 continue;
509 }
510 if (read_val == 0) {
511 if (index == 0) {
512 free(temp);
513 return false;
514 }
515 break;
516 }
517
518 if (SOCK_ERRNO == SOCK_EINTR)
519 continue;
520
522 if (!sock->blocking)
523 break;
524 continue;
525 }
526 free(temp);
527 return false;
528 }
529 temp[index] = 0;
530 *buffer = temp;
531 *size = index;
532 return true;
533}
534
535ssize_t mx_socket_write_all(MXSocket *sock, const void *buf, size_t bytes) {
536 if (sock == nullptr || buf == nullptr || bytes == 0)
537 return -1;
538
539 const char *ptr = (const char *)buf;
540 size_t left = bytes;
541 while (left > 0) {
542 ssize_t written = send(sock->sockfd, (const char *)ptr, MX_LEN(left), 0);
543 if (written == -1) {
544 if (SOCK_ERRNO == SOCK_EINTR) {
545 continue;
546 }
547 return -1;
548 }
549 left -= (size_t)written;
550 ptr += written;
551 }
552 return (ssize_t)bytes;
553}
554
555ssize_t mx_socket_read_all(MXSocket *sock, void *buf, size_t bytes) {
556 if (sock == nullptr || buf == nullptr || bytes == 0)
557 return -1;
558
559 char *ptr = (char *)buf;
560 size_t left = bytes;
561 while (left > 0) {
562 ssize_t bytes_read = recv(sock->sockfd, (char *)ptr, MX_LEN(left), 0);
563 if (bytes_read == -1) {
564 if (SOCK_ERRNO == SOCK_EINTR) {
565 continue;
566 }
567 return -1;
568 }
569 if (bytes_read == 0)
570 break;
571 left -= (size_t)bytes_read;
572 ptr += bytes_read;
573 }
574 return (ssize_t)(bytes - left);
575}
576
578#ifndef _WIN32
579 signal(SIGPIPE, SIG_IGN);
580#endif
581}
582
583ssize_t mx_socket_sendto(MXSocket *sock, const void *buf, size_t src_bytes) {
584 if (sock == nullptr || buf == nullptr || src_bytes == 0)
585 return -1;
586
587 ssize_t bytes = 0;
588 bytes = sendto(sock->sockfd, (const char *)buf, MX_LEN(src_bytes), 0, (struct sockaddr *)&sock->inet, sock->addrlen);
589 return bytes;
590}
591
592ssize_t mx_socket_ipv6_sendto(MXSocket *sock, const void *buf, size_t src_bytes) {
593 if (sock == nullptr || buf == nullptr || src_bytes == 0)
594 return -1;
595
596 ssize_t bytes = 0;
597 bytes = sendto(sock->sockfd, (const char *)buf, MX_LEN(src_bytes), 0, (struct sockaddr *)&sock->inet6, sock->addrlen);
598 return bytes;
599}
600
601ssize_t mx_socket_recvfrom(MXSocket *sock, void *buf, size_t src_bytes) {
602 if (sock == nullptr || buf == nullptr || src_bytes == 0)
603 return -1;
604
605 ssize_t bytes = 0;
606 socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
607 struct sockaddr_storage caddr;
608 bytes = recvfrom(sock->sockfd, (char *)buf, MX_LEN(src_bytes), 0, (struct sockaddr *)&caddr, &len);
609 if (bytes >= 0)
610 mx_socket_store_inet_address(sock, (const struct sockaddr *)&caddr, len);
611 return bytes;
612}
613
614ssize_t mx_socket_recvfrom_address(MXSocket *sock, void *buf, size_t src_bytes, MXSocketAddress *address) {
615 if (sock == nullptr || buf == nullptr || src_bytes == 0 || address == nullptr)
616 return -1;
617 address->length = (socklen_t)sizeof(address->storage);
618 ssize_t bytes = recvfrom(sock->sockfd, (char *)buf, MX_LEN(src_bytes), 0,
619 (struct sockaddr *)&address->storage, &address->length);
620 if (bytes >= 0)
621 mx_socket_store_inet_address(sock, (const struct sockaddr *)&address->storage, address->length);
622 return bytes;
623}
624
625ssize_t mx_socket_sendto_address(MXSocket *sock, const void *buf, size_t src_bytes, const MXSocketAddress *address) {
626 if (sock == nullptr || buf == nullptr || src_bytes == 0 || address == nullptr || address->length == 0)
627 return -1;
628 return sendto(sock->sockfd, (const char *)buf, MX_LEN(src_bytes), 0,
629 (const struct sockaddr *)&address->storage, address->length);
630}
631
632ssize_t mx_socket_ipv6_recvfrom(MXSocket *sock, void *buf, size_t src_bytes) {
633 if (sock == nullptr || buf == nullptr || src_bytes == 0)
634 return -1;
635
636 ssize_t bytes = 0;
637 socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
638 struct sockaddr_storage caddr;
639 bytes = recvfrom(sock->sockfd, (char *)buf, MX_LEN(src_bytes), 0, (struct sockaddr *)&caddr, &len);
640 if (bytes >= 0)
641 mx_socket_store_inet_address(sock, (const struct sockaddr *)&caddr, len);
642 return bytes;
643}
644
645ssize_t mx_socket_unix_sendto(MXSocket *sock, const void *buf, size_t src_bytes) {
646 if (sock == nullptr || buf == nullptr || src_bytes == 0)
647 return -1;
648
649 ssize_t bytes = 0;
650 bytes = sendto(sock->sockfd, (const char *)buf, MX_LEN(src_bytes), 0, (struct sockaddr *)&sock->sun, sock->addrlen);
651 return bytes;
652}
653ssize_t mx_socket_unix_recvfrom(MXSocket *sock, void *buf, size_t src_bytes) {
654 if (sock == nullptr || buf == nullptr || src_bytes == 0)
655 return -1;
656
657 ssize_t bytes = 0;
658 socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
659 struct sockaddr_storage caddr;
660 bytes = recvfrom(sock->sockfd, (char *)buf, MX_LEN(src_bytes), 0, (struct sockaddr *)&caddr, &len);
661 return bytes;
662}
bool mx_socket_unix_listen(MXSocket *sock, const char *path, int backlog, int type)
Create and bind a UNIX-domain socket for listening.
Definition mxsocket.c:202
ssize_t mx_socket_send(MXSocket *sock, const void *buf, size_t len, int flags)
Write data to a socket.
Definition mxsocket.c:432
bool mx_socket_unix_bind(MXSocket *s, const char *path)
Bind a UNIX-domain socket to a local path.
Definition mxsocket.c:378
ssize_t mx_socket_read_all(MXSocket *sock, void *buf, size_t bytes)
Read the requested number of bytes from a socket.
Definition mxsocket.c:555
ssize_t mx_socket_recvfrom(MXSocket *sock, void *buf, size_t src_bytes)
Receive a datagram using an Internet socket.
Definition mxsocket.c:601
bool mx_socket_valid(const MXSocket *sock)
Check whether the socket handle is valid.
Definition mxsocket.c:416
ssize_t mx_socket_recvfrom_address(MXSocket *sock, void *buf, size_t src_bytes, MXSocketAddress *address)
Definition mxsocket.c:614
ssize_t mx_socket_sendto_address(MXSocket *sock, const void *buf, size_t src_bytes, const MXSocketAddress *address)
Definition mxsocket.c:625
bool mx_socket_readline(MXSocket *sock, char **buffer, size_t *size)
Read a line of text from a socket.
Definition mxsocket.c:474
bool mx_socket_ipv6_listen(MXSocket *sock, const char *port, int backlog, int type)
Create and bind an IPv6 Internet socket for listening.
Definition mxsocket.c:274
ssize_t mx_socket_unix_recvfrom(MXSocket *sock, void *buf, size_t src_bytes)
Receive a datagram using a UNIX-domain socket.
Definition mxsocket.c:653
bool mx_socket_ipv6_bind(MXSocket *sock, const char *port)
Bind an IPv6 Internet socket to a local port.
Definition mxsocket.c:374
void mx_socket_ignore_pipe_signal()
Ignore SIGPIPE on platforms that require it.
Definition mxsocket.c:577
bool mx_socket_bind(MXSocket *sock, const char *port)
Bind an Internet socket to a local port.
Definition mxsocket.c:370
void mx_socket_close(MXSocket *sock)
Close a socket if it is open.
Definition mxsocket.c:323
ssize_t mx_socket_write_all(MXSocket *sock, const void *buf, size_t bytes)
Write the requested number of bytes to a socket.
Definition mxsocket.c:535
ssize_t mx_socket_ipv6_sendto(MXSocket *sock, const void *buf, size_t src_bytes)
Send a datagram using an IPv6 Internet socket.
Definition mxsocket.c:592
bool mx_socket_listen(MXSocket *sock, const char *port, int backlog, int type)
Create and bind an Internet socket for listening.
Definition mxsocket.c:270
bool mx_socket_connect(MXSocket *sock, const char *host, const char *port, int type)
Connect an Internet socket to a remote host.
Definition mxsocket.c:362
ssize_t mx_socket_read(MXSocket *sock, void *buf, size_t len, int flags)
Read data from a socket.
Definition mxsocket.c:422
ssize_t mx_socket_sendto(MXSocket *sock, const void *buf, size_t src_bytes)
Send a datagram using an Internet socket.
Definition mxsocket.c:583
bool mx_socket_set_blocking(MXSocket *sock, bool state)
Toggle blocking mode for a socket.
Definition mxsocket.c:331
bool mx_socket_accept(const MXSocket *input, MXSocket *output)
Accept an incoming connection.
Definition mxsocket.c:278
bool mx_socket_unix_connect(MXSocket *sock, const char *path, int type)
Connect a UNIX-domain socket to a local path.
Definition mxsocket.c:241
bool mx_socket_init(MXSocket *sock)
Initialize a socket structure with default values.
Definition mxsocket.c:407
bool mx_socket_ipv6_connect(MXSocket *sock, const char *host, const char *port, int type)
Connect an IPv6 Internet socket to a remote host.
Definition mxsocket.c:366
ssize_t mx_socket_unix_sendto(MXSocket *sock, const void *buf, size_t src_bytes)
Send a datagram using a UNIX-domain socket.
Definition mxsocket.c:645
ssize_t mx_socket_ipv6_recvfrom(MXSocket *sock, void *buf, size_t src_bytes)
Receive a datagram using an IPv6 Internet socket.
Definition mxsocket.c:632
bool mx_socket_is_open(const MXSocket *sock)
Check whether the socket is open.
Definition mxsocket.c:442
int mx_socket_fd
Definition mxsocket.h:48
#define mx_close_socket(s)
Definition mxsocket.h:49
#define SOCK_ERRNO
Definition mxsocket.h:51
#define mx_set_err(e)
Definition mxsocket.h:50
#define SOCK_EWOULDBLOCK
Definition mxsocket.h:54
#define SOCK_EAGAIN
Definition mxsocket.h:53
#define NULL_SOCKET
Definition mxsocket.h:62
#define SOCK_EINTR
Definition mxsocket.h:52
#define MX_LEN(x)
Definition mxsocket.h:61
socklen_t length
Definition mxsocket.h:79
struct sockaddr_storage storage
Definition mxsocket.h:78
Cross-platform socket state used by the C API.
Definition mxsocket.h:68
struct sockaddr_in6 inet6
IPv6 address storage.
Definition mxsocket.h:74
bool blocking
True when the socket is in blocking mode.
Definition mxsocket.h:71
struct sockaddr_in inet
IPv4 address storage.
Definition mxsocket.h:73
struct sockaddr_un sun
UNIX-domain address storage.
Definition mxsocket.h:72
mx_socket_fd sockfd
Underlying socket handle.
Definition mxsocket.h:69
socklen_t addrlen
Length of the active address structure.
Definition mxsocket.h:70