1 /**
2 * @file
3 * @note This file should fully support ipv6 and any other protocol that is
4 * compatible with the getaddrinfo interface, with the exception of
5 * NET_DatagramBroadcast() which must be amended for each protocol (and
6 * currently supports only ipv4)
7 */
8
9 /*
10 Copyright (C) 2002-2013 UFO: Alien Invasion.
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20
21 See the GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 */
28
29 #include "common.h"
30 #include <errno.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <SDL_thread.h>
35 #ifdef _WIN32
36 #include "../ports/system.h"
37 #endif
38 #include "../shared/scopedmutex.h"
39
40 #define MAX_STREAMS 56
41 #define MAX_DATAGRAM_SOCKETS 7
42
43 #ifdef _WIN32
44 # include <winsock2.h>
45 # include <ws2tcpip.h>
46 # if WINVER < 0x501
47 # include <wspiapi.h>
48 # else
49 # include <ws2spi.h>
50 # endif
51 # define netError WSAGetLastError()
52 # define netStringError netStringErrorWin
53 # define netCloseSocket closesocket
54 # define gai_strerrorA netStringErrorWin
55
56 #else /* WIN32 */
57
58 # include <sys/ioctl.h>
59 # include <sys/select.h>
60 # include <sys/types.h>
61 # include <sys/socket.h>
62 # include <sys/time.h>
63 # include <netdb.h>
64 # include <arpa/inet.h>
65 # include <netinet/in.h>
66 # include <signal.h>
67 typedef int SOCKET;
68 # define INVALID_SOCKET (-1)
69 # define netError errno
70 # define netStringError strerror
71 # define netCloseSocket close
72 # define ioctlsocket ioctl
73 #endif /* WIN32 */
74
75 #ifdef EMSCRIPTEN
76 #define NI_NUMERICHOST 0
77 #define NI_NUMERICSERV 0
78 #define NI_DGRAM 0
79 #define AI_PASSIVE 0
80 #define AI_NUMERICHOST 0
81 #define INADDR_BROADCAST 0
82 #endif
83
84 /**
85 * @todo Move this into the configure script
86 * AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3.
87 * AI_NUMERICSERV is available since glibc 2.3.4.
88 */
89 #ifndef AI_NUMERICSERV
90 #define AI_NUMERICSERV 0
91 #endif
92 #ifndef AI_ADDRCONFIG
93 #define AI_ADDRCONFIG 0
94 #endif
95
96 /**
97 * @brief use an admin local address per default so that
98 * network admins can decide on how to handle traffic.
99 */
100 #define NET_MULTICAST_IP6 "ff04::696f:7175:616b:6533"
101
102 #define dbuffer_len(dbuf) (dbuf ? (dbuf)->length() : 0)
103
104 static cvar_t* net_ipv4;
105 static SDL_mutex *netMutex;
106
107 struct net_stream {
108 void* data;
109
110 bool loopback;
111 bool ready;
112 bool closed;
113 bool finished; /**< finished but maybe not yet closed */
114 SOCKET socket;
115 int index;
116 int family;
117 int addrlen;
118
119 /* these buffers must be used in a thread safe manner
120 * (lock netMutex) because the game thread can also write to it */
121 dbufferptr inbound;
122 dbufferptr outbound;
123
124 stream_onclose_func* onclose;
125 stream_callback_func* func;
126 struct net_stream *loopback_peer;
127 };
128
129 struct datagram {
130 int len;
131 char* msg;
132 char* addr;
133 struct datagram *next;
134 };
135
136 struct datagram_socket {
137 SOCKET socket;
138 int index;
139 int family;
140 int addrlen;
141 struct datagram *queue;
142 struct datagram **queue_tail;
143 datagram_callback_func *func;
144 };
145
146 static fd_set read_fds;
147 static fd_set write_fds;
148 static SOCKET maxfd;
149 static struct net_stream *streams[MAX_STREAMS];
150 static struct datagram_socket* datagram_sockets[MAX_DATAGRAM_SOCKETS];
151
152 static bool loopback_ready = false;
153 static bool server_running = false;
154 static stream_callback_func* server_func = nullptr;
155 static SOCKET server_socket = INVALID_SOCKET;
156 static int server_family, server_addrlen;
157
158 #ifdef _WIN32
netStringErrorWin(int code)159 static const char* netStringErrorWin (int code)
160 {
161 switch (code) {
162 case WSAEINTR: return "WSAEINTR";
163 case WSAEBADF: return "WSAEBADF";
164 case WSAEACCES: return "WSAEACCES";
165 case WSAEDISCON: return "WSAEDISCON";
166 case WSAEFAULT: return "WSAEFAULT";
167 case WSAEINVAL: return "WSAEINVAL";
168 case WSAEMFILE: return "WSAEMFILE";
169 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
170 case WSAEINPROGRESS: return "WSAEINPROGRESS";
171 case WSAEALREADY: return "WSAEALREADY";
172 case WSAENOTSOCK: return "WSAENOTSOCK";
173 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
174 case WSAEMSGSIZE: return "WSAEMSGSIZE";
175 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
176 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
177 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
178 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
179 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
180 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
181 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
182 case WSAEADDRINUSE: return "WSAEADDRINUSE";
183 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
184 case WSAENETDOWN: return "WSAENETDOWN";
185 case WSAENETUNREACH: return "WSAENETUNREACH";
186 case WSAENETRESET: return "WSAENETRESET";
187 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
188 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
189 case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
190 case WSAECONNRESET: return "WSAECONNRESET";
191 case WSAENOBUFS: return "WSAENOBUFS";
192 case WSAEISCONN: return "WSAEISCONN";
193 case WSAENOTCONN: return "WSAENOTCONN";
194 case WSAESHUTDOWN: return "WSAESHUTDOWN";
195 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
196 case WSAETIMEDOUT: return "WSAETIMEDOUT";
197 case WSAECONNREFUSED: return "WSAECONNREFUSED";
198 case WSAELOOP: return "WSAELOOP";
199 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
200 case WSASYSNOTREADY: return "WSASYSNOTREADY";
201 case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
202 case WSANOTINITIALISED: return "WSANOTINITIALISED";
203 case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
204 case WSATRY_AGAIN: return "WSATRY_AGAIN";
205 case WSANO_RECOVERY: return "WSANO_RECOVERY";
206 case WSANO_DATA: return "WSANO_DATA";
207 default: return "NO ERROR";
208 }
209 }
210 #endif
211
NET_StreamGetLength(struct net_stream * s)212 static inline int NET_StreamGetLength (struct net_stream *s)
213 {
214 return s ? dbuffer_len(s->inbound) : 0;
215 }
216
217 /**
218 * @brief
219 * @sa NET_StreamNew
220 * @sa NET_StreamClose
221 * @sa NET_DatagramFindFreeSocket
222 */
NET_StreamGetFree(void)223 static int NET_StreamGetFree (void)
224 {
225 static int start = 0;
226 int i;
227
228 for (i = 0; i < MAX_STREAMS; i++) {
229 const int pos = (i + start) % MAX_STREAMS;
230 if (streams[pos] == nullptr) {
231 start = (pos + 1) % MAX_STREAMS;
232 Com_DPrintf(DEBUG_SERVER, "New stream at index: %i\n", pos);
233 return pos;
234 }
235 }
236 return -1;
237 }
238
239 /**
240 * @sa NET_StreamNew
241 */
NET_DatagramFindFreeSocket(void)242 static int NET_DatagramFindFreeSocket (void)
243 {
244 static int start = 0;
245 int i;
246
247 for (i = 0; i < MAX_DATAGRAM_SOCKETS; i++) {
248 const int pos = (i + start) % MAX_DATAGRAM_SOCKETS;
249 if (datagram_sockets[pos] == nullptr) {
250 start = (pos + 1) % MAX_DATAGRAM_SOCKETS;
251 Com_DPrintf(DEBUG_SERVER, "New datagram at index: %i\n", pos);
252 return pos;
253 }
254 }
255 return -1;
256 }
257
258 /**
259 * @sa NET_StreamGetFree
260 * @sa NET_StreamClose
261 */
NET_StreamNew(int index)262 static struct net_stream *NET_StreamNew (int index)
263 {
264 net_stream* const s = Mem_PoolAllocType(net_stream, com_networkPool);
265 s->data = nullptr;
266 s->loopback_peer = nullptr;
267 s->loopback = false;
268 s->closed = false;
269 s->finished = false;
270 s->ready = false;
271 s->socket = INVALID_SOCKET;
272 s->inbound = dbufferptr();
273 s->outbound = dbufferptr();
274 s->index = index;
275 s->family = 0;
276 s->addrlen = 0;
277 s->func = nullptr;
278 if (streams[index])
279 NET_StreamFree(streams[index]);
280 streams[index] = s;
281 return s;
282 }
283
NET_ShowStreams_f(void)284 static void NET_ShowStreams_f (void)
285 {
286 int i;
287 char buf[256];
288 int cnt = 0;
289
290 for (i = 0; i < MAX_STREAMS; i++) {
291 if (streams[i] == nullptr)
292 continue;
293 Com_Printf("Steam %i is opened: %s on socket %i (closed: %i, finished: %i, outbound: " UFO_SIZE_T ", inbound: " UFO_SIZE_T ")\n", i,
294 NET_StreamPeerToName(streams[i], buf, sizeof(buf), true),
295 streams[i]->socket, streams[i]->closed, streams[i]->finished,
296 dbuffer_len(streams[i]->outbound), dbuffer_len(streams[i]->inbound));
297 cnt++;
298 }
299 Com_Printf("%i/%i streams opened\n", cnt, MAX_STREAMS);
300 }
301
302 /**
303 * @sa NET_Shutdown
304 * @sa Qcommon_Init
305 */
NET_Init(void)306 void NET_Init (void)
307 {
308 int i;
309 #ifdef _WIN32
310 WSADATA winsockdata;
311 #endif
312
313 Com_Printf("\n----- network initialization -------\n");
314
315 #ifdef _WIN32
316 if (WSAStartup(MAKEWORD(2, 0), &winsockdata) != 0)
317 Com_Error(ERR_FATAL, "Winsock initialization failed.");
318 #endif
319
320 maxfd = 0;
321 FD_ZERO(&read_fds);
322 FD_ZERO(&write_fds);
323
324 for (i = 0; i < MAX_STREAMS; i++)
325 streams[i] = nullptr;
326 for (i = 0; i < MAX_DATAGRAM_SOCKETS; i++)
327 datagram_sockets[i] = nullptr;
328
329 #ifndef _WIN32
330 signal(SIGPIPE, SIG_IGN);
331 #endif
332
333 net_ipv4 = Cvar_Get("net_ipv4", "1", CVAR_ARCHIVE, "Only use ipv4");
334 Cmd_AddCommand("net_showstreams", NET_ShowStreams_f, "Show opened streams");
335
336 netMutex = SDL_CreateMutex();
337 }
338
339 /**
340 * @sa NET_Init
341 */
NET_Shutdown(void)342 void NET_Shutdown (void)
343 {
344 #ifdef _WIN32
345 WSACleanup();
346 #endif
347 SDL_DestroyMutex(netMutex);
348 netMutex = nullptr;
349 }
350
351 /**
352 * @sa NET_StreamFinished
353 * @sa NET_StreamNew
354 */
NET_StreamClose(struct net_stream * s)355 static void NET_StreamClose (struct net_stream *s)
356 {
357 if (!s || s->closed)
358 return;
359
360 if (s->socket != INVALID_SOCKET) {
361 if (dbuffer_len(s->outbound))
362 Com_Printf("The outbound buffer for this socket (%d) is not empty\n", s->socket);
363 else if (dbuffer_len(s->inbound))
364 Com_Printf("The inbound buffer for this socket (%d) is not empty\n", s->socket);
365
366 FD_CLR(s->socket, &read_fds);
367 FD_CLR(s->socket, &write_fds);
368 netCloseSocket(s->socket);
369 s->socket = INVALID_SOCKET;
370 }
371 if (s->index >= 0)
372 streams[s->index] = nullptr;
373
374 if (s->loopback_peer) {
375 /* Detach the peer, so that it won't send us anything more */
376 s->loopback_peer->outbound = dbufferptr();
377 s->loopback_peer->loopback_peer = nullptr;
378 }
379
380 s->closed = true;
381 Com_DPrintf(DEBUG_SERVER, "Close stream at index: %i\n", s->index);
382
383 s->outbound = dbufferptr();
384 s->socket = INVALID_SOCKET;
385
386 /* Note that this is potentially invalid after the callback returns */
387 if (s->finished) {
388 s->inbound = dbufferptr();
389 if (s->onclose != nullptr)
390 s->onclose();
391 Mem_Free(s);
392 s = nullptr;
393 } else if (s->func) {
394 s->func(s);
395 }
396
397 if (s != nullptr && s->onclose != nullptr)
398 s->onclose();
399 }
400
do_accept(SOCKET sock)401 static void do_accept (SOCKET sock)
402 {
403 const int index = NET_StreamGetFree();
404 struct net_stream *s;
405 if (index == -1) {
406 Com_Printf("Too many streams open, rejecting inbound connection\n");
407 netCloseSocket(sock);
408 return;
409 }
410
411 s = NET_StreamNew(index);
412 s->socket = sock;
413 s->inbound = dbufferptr(new dbuffer(4096));
414 s->outbound = dbufferptr(new dbuffer(4096));
415 s->family = server_family;
416 s->addrlen = server_addrlen;
417 s->func = server_func;
418
419 maxfd = std::max(sock + 1, maxfd);
420 FD_SET(sock, &read_fds);
421
422 server_func(s);
423 /** @todo close stream? */
424 }
425
426 /**
427 * @sa Qcommon_Frame
428 */
NET_Wait(int timeout)429 void NET_Wait (int timeout)
430 {
431 struct timeval tv;
432 int ready;
433 int i;
434
435 fd_set read_fds_out;
436 fd_set write_fds_out;
437
438 memcpy(&read_fds_out, &read_fds, sizeof(read_fds_out));
439 memcpy(&write_fds_out, &write_fds, sizeof(write_fds_out));
440
441 /* select() won't notice that loopback streams are ready, so we'll
442 * eliminate the delay directly */
443 if (loopback_ready)
444 timeout = 0;
445
446 tv.tv_sec = timeout / 1000;
447 tv.tv_usec = 1000 * (timeout % 1000);
448 #ifdef _WIN32
449 if (read_fds_out.fd_count == 0) {
450 Sys_Sleep(timeout);
451 ready = 0;
452 } else
453 #endif
454 ready = select(maxfd, &read_fds_out, &write_fds_out, nullptr, &tv);
455
456 if (ready == -1) {
457 Com_Printf("select failed: %s\n", netStringError(netError));
458 return;
459 }
460
461 if (ready == 0 && !loopback_ready)
462 return;
463
464 if (server_socket != INVALID_SOCKET && FD_ISSET(server_socket, &read_fds_out)) {
465 const SOCKET client_socket = accept(server_socket, nullptr, 0);
466 if (client_socket == INVALID_SOCKET) {
467 if (errno != EAGAIN)
468 Com_Printf("accept on socket %d failed: %s\n", server_socket, netStringError(netError));
469 } else
470 do_accept(client_socket);
471 }
472
473 for (i = 0; i < MAX_STREAMS; i++) {
474 struct net_stream *s = streams[i];
475
476 if (!s)
477 continue;
478
479 if (s->loopback) {
480 /* If the peer is gone and the buffer is empty, close the stream */
481 if (!s->loopback_peer && NET_StreamGetLength(s) == 0) {
482 NET_StreamClose(s);
483 }
484 /* Note that s is potentially invalid after the callback returns - we'll close dead streams on the next pass */
485 else if (s->ready && s->func) {
486 s->func(s);
487 }
488
489 continue;
490 }
491
492 if (s->socket == INVALID_SOCKET)
493 continue;
494
495 if (FD_ISSET(s->socket, &write_fds_out)) {
496 char buf[4096];
497 int len;
498
499 if (dbuffer_len(s->outbound) == 0) {
500 FD_CLR(s->socket, &write_fds);
501
502 /* Finished streams are closed when their outbound queues empty */
503 if (s->finished)
504 NET_StreamClose(s);
505
506 continue;
507 }
508
509 {
510 const ScopedMutex scopedMutex(netMutex);
511 len = s->outbound->get(buf, sizeof(buf));
512 len = send(s->socket, buf, len, 0);
513
514 s->outbound->remove(len);
515 }
516
517 if (len < 0) {
518 Com_Printf("write on socket %d failed: %s\n", s->socket, netStringError(netError));
519 NET_StreamClose(s);
520 continue;
521 }
522
523 Com_DPrintf(DEBUG_SERVER, "wrote %d bytes to stream %d (%s)\n", len, i, NET_StreamPeerToName(s, buf, sizeof(buf), true));
524 }
525
526 if (FD_ISSET(s->socket, &read_fds_out)) {
527 char buf[4096];
528 const int len = recv(s->socket, buf, sizeof(buf), 0);
529 if (len <= 0) {
530 if (len == -1)
531 Com_Printf("read on socket %d failed: %s\n", s->socket, netStringError(netError));
532 NET_StreamClose(s);
533 continue;
534 } else {
535 if (s->inbound) {
536 SDL_LockMutex(netMutex);
537 s->inbound->add(buf, len);
538 SDL_UnlockMutex(netMutex);
539
540 Com_DPrintf(DEBUG_SERVER, "read %d bytes from stream %d (%s)\n", len, i, NET_StreamPeerToName(s, buf, sizeof(buf), true));
541
542 /* Note that s is potentially invalid after the callback returns */
543 if (s->func)
544 s->func(s);
545
546 continue;
547 }
548 }
549 }
550 }
551
552 for (i = 0; i < MAX_DATAGRAM_SOCKETS; i++) {
553 struct datagram_socket* s = datagram_sockets[i];
554
555 if (!s)
556 continue;
557
558 if (FD_ISSET(s->socket, &write_fds_out)) {
559 if (s->queue) {
560 struct datagram *dgram = s->queue;
561 const int len = sendto(s->socket, dgram->msg, dgram->len, 0, (struct sockaddr* )dgram->addr, s->addrlen);
562 if (len == -1)
563 Com_Printf("sendto on socket %d failed: %s\n", s->socket, netStringError(netError));
564 /* Regardless of whether it worked, we don't retry datagrams */
565 s->queue = dgram->next;
566 Mem_Free(dgram->msg);
567 Mem_Free(dgram->addr);
568 Mem_Free(dgram);
569 if (!s->queue)
570 s->queue_tail = &s->queue;
571 } else {
572 FD_CLR(s->socket, &write_fds);
573 }
574 }
575
576 if (FD_ISSET(s->socket, &read_fds_out)) {
577 char buf[256];
578 char addrbuf[256];
579 socklen_t addrlen = sizeof(addrbuf);
580 const int len = recvfrom(s->socket, buf, sizeof(buf), 0, (struct sockaddr* )addrbuf, &addrlen);
581 if (len == -1)
582 Com_Printf("recvfrom on socket %d failed: %s\n", s->socket, netStringError(netError));
583 else
584 s->func(s, buf, len, (struct sockaddr* )addrbuf);
585 }
586 }
587
588 loopback_ready = false;
589 }
590
NET_SocketSetNonBlocking(SOCKET socketNum)591 static bool NET_SocketSetNonBlocking (SOCKET socketNum)
592 {
593 unsigned long t = 1;
594 if (ioctlsocket(socketNum, FIONBIO, &t) == -1) {
595 Com_Printf("ioctl FIONBIO failed: %s\n", strerror(errno));
596 return false;
597 }
598 return true;
599 }
600
NET_DoConnect(const char * node,const char * service,const struct addrinfo * addr,int i,stream_onclose_func * onclose)601 static struct net_stream *NET_DoConnect (const char* node, const char* service, const struct addrinfo *addr, int i, stream_onclose_func* onclose)
602 {
603 struct net_stream *s;
604 SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
605 if (sock == INVALID_SOCKET) {
606 Com_Printf("Failed to create socket: %s\n", netStringError(netError));
607 return nullptr;
608 }
609
610 if (!NET_SocketSetNonBlocking(sock)) {
611 netCloseSocket(sock);
612 return nullptr;
613 }
614
615 if (connect(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
616 const int err = netError;
617 #ifdef _WIN32
618 if (err != WSAEWOULDBLOCK) {
619 #else
620 if (err != EINPROGRESS) {
621 #endif
622 Com_Printf("Failed to start connection to %s:%s: %s\n", node, service, netStringError(err));
623 netCloseSocket(sock);
624 return nullptr;
625 }
626 }
627
628 s = NET_StreamNew(i);
629 s->socket = sock;
630 s->inbound = dbufferptr(new dbuffer(4096));
631 s->outbound = dbufferptr(new dbuffer(4096));
632 s->family = addr->ai_family;
633 s->addrlen = addr->ai_addrlen;
634 s->onclose = onclose;
635
636 maxfd = std::max(sock + 1, maxfd);
637 FD_SET(sock, &read_fds);
638
639 return s;
640 }
641
642 /**
643 * @brief Try to connect to a given host on a given port
644 * @param[in] node The host to connect to
645 * @param[in] service The port to connect to
646 * @param[in] onclose The callback that is called on closing the returned stream. This is useful if
647 * you hold the pointer for the returned stream anywhere else and would like to get notified once
648 * this pointer is invalid.
649 * @sa NET_DoConnect
650 * @sa NET_ConnectToLoopBack
651 * @todo What about a timeout
652 */
653 struct net_stream *NET_Connect (const char* node, const char* service, stream_onclose_func* onclose)
654 {
655 struct addrinfo *res;
656 struct addrinfo hints;
657 int rc;
658 struct net_stream *s = nullptr;
659 int index;
660
661 OBJZERO(hints);
662 hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
663 hints.ai_socktype = SOCK_STREAM;
664 /* force ipv4 */
665 if (net_ipv4->integer)
666 hints.ai_family = AF_INET;
667
668 rc = getaddrinfo(node, service, &hints, &res);
669 if (rc != 0) {
670 Com_Printf("Failed to resolve host %s:%s: %s\n", node, service, gai_strerror(rc));
671 return nullptr;
672 }
673
674 index = NET_StreamGetFree();
675 if (index == -1) {
676 Com_Printf("Failed to connect to host %s:%s, too many streams open\n", node, service);
677 freeaddrinfo(res);
678 return nullptr;
679 }
680
681 s = NET_DoConnect(node, service, res, index, onclose);
682
683 freeaddrinfo(res);
684 return s;
685 }
686
687 /**
688 * @param[in] onclose The callback that is called on closing the returned stream. This is useful if
689 * you hold the pointer for the returned stream anywhere else and would like to get notified once
690 * this pointer is invalid.
691 * @sa NET_Connect
692 */
693 struct net_stream *NET_ConnectToLoopBack (stream_onclose_func* onclose)
694 {
695 struct net_stream *client, *server;
696 int server_index, client_index;
697
698 if (!server_running)
699 return nullptr;
700
701 server_index = NET_StreamGetFree();
702 client_index = NET_StreamGetFree();
703
704 if (server_index == -1 || client_index == -1 || server_index == client_index) {
705 Com_Printf("Failed to connect to loopback server, too many streams open\n");
706 return nullptr;
707 }
708
709 client = NET_StreamNew(client_index);
710 client->loopback = true;
711 client->inbound = dbufferptr(new dbuffer(4096));
712 client->outbound = dbufferptr(new dbuffer(4096));
713 client->onclose = onclose;
714
715 server = NET_StreamNew(server_index);
716 server->loopback = true;
717 server->inbound = client->outbound;
718 server->outbound = client->inbound;
719 server->func = server_func;
720 server->onclose = nullptr;
721
722 client->loopback_peer = server;
723 server->loopback_peer = client;
724
725 server_func(server);
726
727 return client;
728 }
729
730 /**
731 * @brief Enqueue a network message into a stream
732 * @sa NET_StreamDequeue
733 */
734 void NET_StreamEnqueue (struct net_stream *s, const char* data, int len)
735 {
736 if (len <= 0 || !s || s->closed || s->finished)
737 return;
738
739 if (s->outbound) {
740 const ScopedMutex scopedMutex(netMutex);
741 s->outbound->add(data, len);
742 }
743
744 /* on linux, socket is int, and INVALID_SOCKET -1
745 * on windows it is unsigned and INVALID_SOCKET (~0)
746 * Let's hope that checking for INVALID_SOCKET is good enough for linux. */
747 //if (s->socket >= 0)
748 if (s->socket != INVALID_SOCKET)
749 FD_SET(s->socket, &write_fds);
750
751 if (s->loopback_peer) {
752 loopback_ready = true;
753 s->loopback_peer->ready = true;
754 }
755 }
756
757 /**
758 * @brief Returns the length of the waiting inbound buffer
759 */
760 static int NET_StreamPeek (struct net_stream *s, char* data, int len)
761 {
762 if (len <= 0 || !s)
763 return 0;
764
765 dbufferptr &dbuf = s->inbound;
766 if ((s->closed || s->finished) && dbuffer_len(dbuf) == 0)
767 return 0;
768
769 return dbuf->get(data, len);
770 }
771
772 /**
773 * @sa NET_StreamEnqueue
774 */
775 int NET_StreamDequeue (struct net_stream *s, char* data, int len)
776 {
777 if (len <= 0 || !s || s->finished)
778 return 0;
779
780 return s->inbound->extract(data, len);
781 }
782
783 /**
784 * @brief Reads messages from the network channel and adds them to the dbuffer
785 * where you can use the NET_Read* functions to get the values in the correct
786 * order
787 * @sa NET_StreamDequeue
788 */
789 dbuffer* NET_ReadMsg (struct net_stream *s)
790 {
791 unsigned int v;
792 const ScopedMutex scopedMutex(netMutex);
793
794 if (NET_StreamPeek(s, (char*)&v, 4) < 4)
795 return nullptr;
796
797 int len = LittleLong(v);
798 if (NET_StreamGetLength(s) < (4 + len))
799 return nullptr;
800
801 char tmp[256];
802 const int size = sizeof(tmp);
803 NET_StreamDequeue(s, tmp, 4);
804
805 dbuffer* buf = new dbuffer();
806 while (len > 0) {
807 const int x = NET_StreamDequeue(s, tmp, std::min(len, size));
808 buf->add(tmp, x);
809 len -= x;
810 }
811
812 return buf;
813 }
814
815 void* NET_StreamGetData (struct net_stream *s)
816 {
817 return s ? s->data : nullptr;
818 }
819
820 void NET_StreamSetData (struct net_stream *s, void* data)
821 {
822 if (!s)
823 return;
824 s->data = data;
825 }
826
827 /**
828 * @brief Call NET_StreamFree to dump the whole thing right now
829 * @sa NET_StreamClose
830 * @sa NET_StreamFinished
831 */
832 void NET_StreamFree (struct net_stream *s)
833 {
834 if (!s)
835 return;
836 s->finished = true;
837 NET_StreamClose(s);
838 }
839
840 /**
841 * @brief Call NET_StreamFinished to mark the stream as uninteresting, but to
842 * finish sending any data in the buffer. The stream will appear
843 * closed after this call, and at some unspecified point in the future
844 * s will become an invalid pointer, so it should not be further
845 * referenced.
846 */
847 void NET_StreamFinished (struct net_stream *s)
848 {
849 if (!s)
850 return;
851
852 s->finished = true;
853
854 if (s->socket != INVALID_SOCKET)
855 FD_CLR(s->socket, &read_fds);
856
857 /* Stop the loopback peer from queueing stuff up in here */
858 if (s->loopback_peer)
859 s->loopback_peer->outbound = dbufferptr();
860
861 const ScopedMutex scopedMutex(netMutex);
862 s->inbound = dbufferptr();
863
864 /* If there's nothing in the outbound buffer, any finished stream is
865 * ready to be closed */
866 if (dbuffer_len(s->outbound) == 0)
867 NET_StreamClose(s);
868 }
869
870 /**
871 * @brief Returns the numerical representation of a @c net_stream
872 * @note Not thread safe!
873 */
874 const char* NET_StreamToString (struct net_stream *s)
875 {
876 static char node[64];
877 NET_StreamPeerToName(s, node, sizeof(node), false);
878 return node;
879 }
880
881 /**
882 * @param[in] s The network stream to get the name for
883 * @param[out] dst The target buffer to store the ip and port in
884 * @param[in] len The length of the target buffer
885 * @param[in] appendPort Also append the port number to the target buffer
886 */
887 const char* NET_StreamPeerToName (struct net_stream *s, char* dst, int len, bool appendPort)
888 {
889 if (!s)
890 return "(null)";
891
892 if (NET_StreamIsLoopback(s))
893 return "loopback connection";
894
895 char buf[128];
896 socklen_t addrlen = s->addrlen;
897 if (getpeername(s->socket, (struct sockaddr* )buf, &addrlen) != 0)
898 return "(error)";
899
900 char node[64];
901 char service[64];
902 const int rc = getnameinfo((struct sockaddr* )buf, addrlen, node, sizeof(node), service, sizeof(service),
903 NI_NUMERICHOST | NI_NUMERICSERV);
904 if (rc != 0) {
905 Com_Printf("Failed to convert sockaddr to string: %s\n", gai_strerror(rc));
906 return "(error)";
907 }
908 if (!appendPort) {
909 Q_strncpyz(dst, node, len);
910 } else {
911 node[sizeof(node) - 1] = '\0';
912 service[sizeof(service) - 1] = '\0';
913 Com_sprintf(dst, len, "%s %s", node, service);
914 }
915 return dst;
916 }
917
918 void NET_StreamSetCallback (struct net_stream *s, stream_callback_func* func)
919 {
920 if (!s)
921 return;
922 s->func = func;
923 }
924
925 bool NET_StreamIsLoopback (struct net_stream *s)
926 {
927 return s && s->loopback;
928 }
929
930 static int NET_DoStartServer (const struct addrinfo *addr)
931 {
932 SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
933 int t = 1;
934
935 if (sock == INVALID_SOCKET) {
936 Com_Printf("Failed to create socket: %s\n", netStringError(netError));
937 return INVALID_SOCKET;
938 }
939
940 if (!NET_SocketSetNonBlocking(sock)) {
941 netCloseSocket(sock);
942 return INVALID_SOCKET;
943 }
944
945 #ifdef _WIN32
946 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &t, sizeof(t)) != 0) {
947 #else
948 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(t)) != 0) {
949 #endif
950 Com_Printf("Failed to set SO_REUSEADDR on socket: %s\n", netStringError(netError));
951 netCloseSocket(sock);
952 return INVALID_SOCKET;
953 }
954
955 if (bind(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
956 Com_Printf("Failed to bind socket: %s\n", netStringError(netError));
957 netCloseSocket(sock);
958 return INVALID_SOCKET;
959 }
960
961 if (listen(sock, SOMAXCONN) != 0) {
962 Com_Printf("Failed to listen on socket: %s\n", netStringError(netError));
963 netCloseSocket(sock);
964 return INVALID_SOCKET;
965 }
966
967 maxfd = std::max(sock + 1, maxfd);
968 FD_SET(sock, &read_fds);
969 server_family = addr->ai_family;
970 server_addrlen = addr->ai_addrlen;
971
972 return sock;
973 }
974
975 static struct addrinfo* NET_GetAddrinfoForNode (const char* node, const char* service)
976 {
977 struct addrinfo *res;
978 struct addrinfo hints;
979 int rc;
980
981 OBJZERO(hints);
982 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
983 hints.ai_socktype = SOCK_STREAM;
984 /* force ipv4 */
985 if (net_ipv4->integer)
986 hints.ai_family = AF_INET;
987
988 rc = getaddrinfo(node, service, &hints, &res);
989 if (rc != 0) {
990 Com_Printf("Failed to resolve host %s:%s: %s\n", node ? node : "*", service, gai_strerror(rc));
991 return nullptr;
992 }
993
994 return res;
995 }
996
997 /**
998 * @sa NET_DoStartServer
999 * @param[in] node The node to start the server with
1000 * @param[in] service If this is nullptr we are in single player mode
1001 * @param[in] func The server callback function to read the packets
1002 * @sa SV_ReadPacket
1003 * @sa server_func
1004 * @sa SV_Stop
1005 */
1006 bool SV_Start (const char* node, const char* service, stream_callback_func* func)
1007 {
1008 if (!func)
1009 return false;
1010
1011 if (server_running) {
1012 Com_Printf("SV_Start: Server is still running - call SV_Stop before\n");
1013 return false;
1014 }
1015
1016 if (service) {
1017 struct addrinfo *res = NET_GetAddrinfoForNode(node, service);
1018
1019 server_socket = NET_DoStartServer(res);
1020 if (server_socket == INVALID_SOCKET) {
1021 Com_Printf("Failed to start server on %s:%s\n", node ? node : "*", service);
1022 } else {
1023 server_running = true;
1024 server_func = func;
1025 }
1026 freeaddrinfo(res);
1027 } else {
1028 /* Loopback server only */
1029 server_running = true;
1030 server_func = func;
1031 }
1032
1033 return server_running;
1034 }
1035
1036 /**
1037 * @sa SV_Start
1038 */
1039 void SV_Stop (void)
1040 {
1041 server_running = false;
1042 server_func = nullptr;
1043 if (server_socket != INVALID_SOCKET) {
1044 FD_CLR(server_socket, &read_fds);
1045 netCloseSocket(server_socket);
1046 }
1047 server_socket = INVALID_SOCKET;
1048 }
1049
1050 /**
1051 * @sa NET_DatagramSocketNew
1052 */
1053 static struct datagram_socket* NET_DatagramSocketDoNew (const struct addrinfo *addr)
1054 {
1055 SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
1056 int t = 1;
1057 const int index = NET_DatagramFindFreeSocket();
1058
1059 if (index == -1) {
1060 Com_Printf("Too many datagram sockets open\n");
1061 return nullptr;
1062 }
1063
1064 if (sock == INVALID_SOCKET) {
1065 Com_Printf("Failed to create socket: %s\n", netStringError(netError));
1066 return nullptr;
1067 }
1068
1069 if (!NET_SocketSetNonBlocking(sock)) {
1070 netCloseSocket(sock);
1071 return nullptr;
1072 }
1073
1074 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &t, sizeof(t)) != 0) {
1075 Com_Printf("Failed to set SO_REUSEADDR on socket: %s\n", netStringError(netError));
1076 netCloseSocket(sock);
1077 return nullptr;
1078 }
1079
1080 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(t)) != 0) {
1081 Com_Printf("Failed to set SO_BROADCAST on socket: %s\n", netStringError(netError));
1082 netCloseSocket(sock);
1083 return nullptr;
1084 }
1085
1086 if (bind(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
1087 Com_Printf("Failed to bind socket: %s\n", netStringError(netError));
1088 netCloseSocket(sock);
1089 return nullptr;
1090 }
1091
1092 maxfd = std::max(sock + 1, maxfd);
1093 FD_SET(sock, &read_fds);
1094
1095 datagram_socket* const s = Mem_PoolAllocType(datagram_socket, com_networkPool);
1096 s->family = addr->ai_family;
1097 s->addrlen = addr->ai_addrlen;
1098 s->socket = sock;
1099 s->index = index;
1100 s->queue = nullptr;
1101 s->queue_tail = &s->queue;
1102 s->func = nullptr;
1103 datagram_sockets[index] = s;
1104
1105 return s;
1106 }
1107
1108 /**
1109 * @brief Opens a datagram socket (UDP)
1110 * @sa NET_DatagramSocketDoNew
1111 * @param[in] node The numeric address to resolv (might be nullptr)
1112 * @param[in] service The port number
1113 * @param[in] func Callback function for data handling
1114 */
1115 struct datagram_socket* NET_DatagramSocketNew (const char* node, const char* service, datagram_callback_func *func)
1116 {
1117 struct datagram_socket* s;
1118 struct addrinfo *res;
1119 struct addrinfo hints;
1120 int rc;
1121
1122 if (!service || !func)
1123 return nullptr;
1124
1125 OBJZERO(hints);
1126 hints.ai_flags = AI_NUMERICHOST | AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE;
1127 hints.ai_socktype = SOCK_DGRAM;
1128 /* force ipv4 */
1129 if (net_ipv4->integer)
1130 hints.ai_family = AF_INET;
1131
1132 rc = getaddrinfo(node, service, &hints, &res);
1133
1134 if (rc != 0) {
1135 Com_Printf("Failed to resolve host %s:%s: %s\n", node ? node : "*", service, gai_strerror(rc));
1136 return nullptr;
1137 }
1138
1139 s = NET_DatagramSocketDoNew(res);
1140 if (s)
1141 s->func = func;
1142
1143 freeaddrinfo(res);
1144 return s;
1145 }
1146
1147 /**
1148 * @sa NET_DatagramSocketNew
1149 */
1150 void NET_DatagramSend (struct datagram_socket* s, const char* buf, int len, struct sockaddr* to)
1151 {
1152 if (!s || len <= 0 || !buf || !to)
1153 return;
1154
1155 datagram* const dgram = Mem_PoolAllocType(datagram, com_networkPool);
1156 dgram->msg = Mem_PoolAllocTypeN(char, len, com_networkPool);
1157 dgram->addr = Mem_PoolAllocTypeN(char, s->addrlen, com_networkPool);
1158 memcpy(dgram->msg, buf, len);
1159 memcpy(dgram->addr, to, len);
1160 dgram->len = len;
1161 dgram->next = nullptr;
1162
1163 *s->queue_tail = dgram;
1164 s->queue_tail = &dgram->next;
1165
1166 FD_SET(s->socket, &write_fds);
1167 }
1168
1169 /**
1170 * @sa NET_DatagramSend
1171 * @sa NET_DatagramSocketNew
1172 * @todo This is only sending on the first available device, what if we have several devices?
1173 */
1174 void NET_DatagramBroadcast (struct datagram_socket* s, const char* buf, int len, int port)
1175 {
1176 if (s->family == AF_INET) {
1177 struct sockaddr_in addr;
1178 addr.sin_family = AF_INET;
1179 addr.sin_port = htons(port);
1180 addr.sin_addr.s_addr = INADDR_BROADCAST;
1181 NET_DatagramSend(s, buf, len, (struct sockaddr* )&addr);
1182 } else if (s->family == AF_INET6) {
1183 struct sockaddr_in addr;
1184 addr.sin_family = AF_INET6;
1185 addr.sin_port = htons(port);
1186 addr.sin_addr.s_addr = INADDR_BROADCAST;
1187 NET_DatagramSend(s, buf, len, (struct sockaddr* )&addr);
1188 } else {
1189 Com_Error(ERR_DROP, "Broadcast unsupported on address family %d\n", s->family);
1190 }
1191 }
1192
1193 /**
1194 * @sa NET_DatagramSocketNew
1195 * @sa NET_DatagramSocketDoNew
1196 */
1197 void NET_DatagramSocketClose (struct datagram_socket* s)
1198 {
1199 if (!s)
1200 return;
1201
1202 FD_CLR(s->socket, &read_fds);
1203 FD_CLR(s->socket, &write_fds);
1204 netCloseSocket(s->socket);
1205
1206 while (s->queue) {
1207 struct datagram *dgram = s->queue;
1208 s->queue = dgram->next;
1209 Mem_Free(dgram->msg);
1210 Mem_Free(dgram->addr);
1211 Mem_Free(dgram);
1212 }
1213
1214 datagram_sockets[s->index] = nullptr;
1215 Mem_Free(s);
1216 }
1217
1218 /**
1219 * @brief Convert sockaddr to string
1220 * @param[in] s The datagram socket type to get the addrlen from
1221 * @param[in] addr The socket address to convert into a string
1222 * @param[out] node The target node name buffer
1223 * @param[in] nodelen The length of the node name buffer
1224 * @param[out] service The target service name buffer
1225 * @param[in] servicelen The length of the service name buffer
1226 */
1227 void NET_SockaddrToStrings (struct datagram_socket* s, struct sockaddr* addr, char* node, size_t nodelen, char* service, size_t servicelen)
1228 {
1229 const int rc = getnameinfo(addr, s->addrlen, node, nodelen, service, servicelen,
1230 NI_NUMERICHOST | NI_NUMERICSERV | NI_DGRAM);
1231 if (rc != 0) {
1232 Com_Printf("Failed to convert sockaddr to string: %s\n", gai_strerror(rc));
1233 Q_strncpyz(node, "(error)", nodelen);
1234 Q_strncpyz(service, "(error)", servicelen);
1235 }
1236 }
1237
1238 static void NET_AddrinfoToString (const struct addrinfo *addr, char* buf, size_t bufLength)
1239 {
1240 char* service = inet_ntoa(((struct sockaddr_in *)addr->ai_addr)->sin_addr);
1241 Q_strncpyz(buf, service, bufLength);
1242 }
1243
1244 void NET_ResolvNode (const char* node, char* buf, size_t bufLength)
1245 {
1246 struct addrinfo* addrinfo = NET_GetAddrinfoForNode(node, nullptr);
1247 if (addrinfo == nullptr) {
1248 buf[0] = '\0';
1249 return;
1250 }
1251 NET_AddrinfoToString(addrinfo, buf, bufLength);
1252 freeaddrinfo(addrinfo);
1253 }
1254