00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "common.h"
00030 #include <errno.h>
00031 #include <string.h>
00032 #include <fcntl.h>
00033 #include <unistd.h>
00034
00035 #ifdef _WIN32
00036 #include "../ports/system.h"
00037 #endif
00038
00039 #define MAX_STREAMS 56
00040 #define MAX_DATAGRAM_SOCKETS 7
00041
00042 struct memPool_s *com_networkPool;
00043
00044 #ifdef _WIN32
00045 # include <winsock2.h>
00046 # include <ws2tcpip.h>
00047 # if WINVER < 0x501
00048 # include <wspiapi.h>
00049 # else
00050 # include <ws2spi.h>
00051 # endif
00052 # define netError WSAGetLastError()
00053 # define netStringError netStringErrorWin
00054 # define netCloseSocket closesocket
00055 # define gai_strerrorA netStringErrorWin
00056
00057 #else
00058
00059 # include <sys/ioctl.h>
00060 # include <sys/select.h>
00061 # include <sys/types.h>
00062 # include <sys/socket.h>
00063 # include <sys/time.h>
00064 # include <netdb.h>
00065 # include <arpa/inet.h>
00066 # include <netinet/in.h>
00067 # include <signal.h>
00068 typedef int SOCKET;
00069 # define INVALID_SOCKET (-1)
00070 # define netError errno
00071 # define netStringError strerror
00072 # define netCloseSocket close
00073 # define ioctlsocket ioctl
00074 #endif
00075
00081 #ifndef AI_NUMERICSERV
00082 #define AI_NUMERICSERV 0
00083 #endif
00084 #ifndef AI_ADDRCONFIG
00085 #define AI_ADDRCONFIG 0
00086 #endif
00087
00092 #define NET_MULTICAST_IP6 "ff04::696f:7175:616b:6533"
00093
00094 static cvar_t* net_ipv4;
00095
00096 struct net_stream {
00097 void *data;
00098
00099 qboolean loopback;
00100 qboolean ready;
00101 qboolean closed;
00102 qboolean finished;
00103 int socket;
00104 int index;
00105 int family;
00106 int addrlen;
00107
00108 struct dbuffer *inbound;
00109 struct dbuffer *outbound;
00110
00111 stream_callback_func *func;
00112 struct net_stream *loopback_peer;
00113 };
00114
00115 struct datagram {
00116 int len;
00117 char *msg;
00118 char *addr;
00119 struct datagram *next;
00120 };
00121
00122 struct datagram_socket {
00123 int socket;
00124 int index;
00125 int family;
00126 int addrlen;
00127 struct datagram *queue;
00128 struct datagram **queue_tail;
00129 datagram_callback_func *func;
00130 };
00131
00132 static fd_set read_fds;
00133 static fd_set write_fds;
00134 static int maxfd;
00135 static struct net_stream *streams[MAX_STREAMS];
00136 static struct datagram_socket *datagram_sockets[MAX_DATAGRAM_SOCKETS];
00137
00138 static qboolean loopback_ready = qfalse;
00139 static qboolean server_running = qfalse;
00140 static stream_callback_func *server_func = NULL;
00141 static int server_socket = INVALID_SOCKET;
00142 static int server_family, server_addrlen;
00143
00144 #ifdef _WIN32
00145 static const char *netStringErrorWin (int code)
00146 {
00147 switch (code) {
00148 case WSAEINTR: return "WSAEINTR";
00149 case WSAEBADF: return "WSAEBADF";
00150 case WSAEACCES: return "WSAEACCES";
00151 case WSAEDISCON: return "WSAEDISCON";
00152 case WSAEFAULT: return "WSAEFAULT";
00153 case WSAEINVAL: return "WSAEINVAL";
00154 case WSAEMFILE: return "WSAEMFILE";
00155 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
00156 case WSAEINPROGRESS: return "WSAEINPROGRESS";
00157 case WSAEALREADY: return "WSAEALREADY";
00158 case WSAENOTSOCK: return "WSAENOTSOCK";
00159 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
00160 case WSAEMSGSIZE: return "WSAEMSGSIZE";
00161 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
00162 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
00163 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
00164 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
00165 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
00166 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
00167 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
00168 case WSAEADDRINUSE: return "WSAEADDRINUSE";
00169 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
00170 case WSAENETDOWN: return "WSAENETDOWN";
00171 case WSAENETUNREACH: return "WSAENETUNREACH";
00172 case WSAENETRESET: return "WSAENETRESET";
00173 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
00174 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
00175 case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
00176 case WSAECONNRESET: return "WSAECONNRESET";
00177 case WSAENOBUFS: return "WSAENOBUFS";
00178 case WSAEISCONN: return "WSAEISCONN";
00179 case WSAENOTCONN: return "WSAENOTCONN";
00180 case WSAESHUTDOWN: return "WSAESHUTDOWN";
00181 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
00182 case WSAETIMEDOUT: return "WSAETIMEDOUT";
00183 case WSAECONNREFUSED: return "WSAECONNREFUSED";
00184 case WSAELOOP: return "WSAELOOP";
00185 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
00186 case WSASYSNOTREADY: return "WSASYSNOTREADY";
00187 case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
00188 case WSANOTINITIALISED: return "WSANOTINITIALISED";
00189 case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
00190 case WSATRY_AGAIN: return "WSATRY_AGAIN";
00191 case WSANO_RECOVERY: return "WSANO_RECOVERY";
00192 case WSANO_DATA: return "WSANO_DATA";
00193 default: return "NO ERROR";
00194 }
00195 }
00196 #endif
00197
00204 static int NET_StreamGetFree (void)
00205 {
00206 static int start = 0;
00207 int i;
00208
00209 for (i = 0; i < MAX_STREAMS; i++) {
00210 const int pos = (i + start) % MAX_STREAMS;
00211 if (streams[pos] == NULL) {
00212 start = (pos + 1) % MAX_STREAMS;
00213 Com_DPrintf(DEBUG_SERVER, "New stream at index: %i\n", pos);
00214 return pos;
00215 }
00216 }
00217 return -1;
00218 }
00219
00223 static int NET_DatagramFindFreeSocket (void)
00224 {
00225 static int start = 0;
00226 int i;
00227
00228 for (i = 0; i < MAX_DATAGRAM_SOCKETS; i++) {
00229 const int pos = (i + start) % MAX_DATAGRAM_SOCKETS;
00230 if (datagram_sockets[pos] == NULL) {
00231 start = (pos + 1) % MAX_DATAGRAM_SOCKETS;
00232 Com_DPrintf(DEBUG_SERVER, "New datagram at index: %i\n", pos);
00233 return pos;
00234 }
00235 }
00236 return -1;
00237 }
00238
00243 static struct net_stream *NET_StreamNew (int index)
00244 {
00245 struct net_stream *s = Mem_PoolAlloc(sizeof(*s), com_networkPool, 0);
00246 s->data = NULL;
00247 s->loopback_peer = NULL;
00248 s->loopback = qfalse;
00249 s->closed = qfalse;
00250 s->finished = qfalse;
00251 s->ready = qfalse;
00252 s->socket = INVALID_SOCKET;
00253 s->inbound = NULL;
00254 s->outbound = NULL;
00255 s->index = index;
00256 s->family = 0;
00257 s->addrlen = 0;
00258 s->func = NULL;
00259 if (streams[index])
00260 NET_StreamFree(streams[index]);
00261 streams[index] = s;
00262 return s;
00263 }
00264
00265 static void NET_ShowStreams_f (void)
00266 {
00267 int i;
00268 char buf[256];
00269 int cnt = 0;
00270
00271 for (i = 0; i < MAX_STREAMS; i++) {
00272 if (streams[i] != NULL) {
00273 Com_Printf("Steam %i is opened: %s on socket %i (closed: %i, finished: %i, outbound: "UFO_SIZE_T", inbound: "UFO_SIZE_T")\n", i,
00274 NET_StreamPeerToName(streams[i], buf, sizeof(buf), qtrue),
00275 streams[i]->socket, streams[i]->closed, streams[i]->finished,
00276 dbuffer_len(streams[i]->outbound), dbuffer_len(streams[i]->inbound));
00277 cnt++;
00278 }
00279 }
00280 Com_Printf("%i/%i streams opened\n", cnt, MAX_STREAMS);
00281 }
00282
00287 void NET_Init (void)
00288 {
00289 int i;
00290 #ifdef _WIN32
00291 WSADATA winsockdata;
00292 #endif
00293
00294 Com_Printf("\n----- network initialization -------\n");
00295
00296 #ifdef _WIN32
00297 if (WSAStartup(MAKEWORD(2, 0), &winsockdata) != 0)
00298 Com_Error(ERR_FATAL, "Winsock initialization failed.");
00299 #endif
00300
00301 maxfd = 0;
00302 FD_ZERO(&read_fds);
00303 FD_ZERO(&write_fds);
00304
00305 for (i = 0; i < MAX_STREAMS; i++)
00306 streams[i] = NULL;
00307 for (i = 0; i < MAX_DATAGRAM_SOCKETS; i++)
00308 datagram_sockets[i] = NULL;
00309
00310 #ifndef _WIN32
00311 signal(SIGPIPE, SIG_IGN);
00312 #endif
00313
00314 dbuffer_init();
00315
00316 net_ipv4 = Cvar_Get("net_ipv4", "1", CVAR_ARCHIVE, "Only use ipv4");
00317 Cmd_AddCommand("net_showstreams", NET_ShowStreams_f, "Show opened streams");
00318 }
00319
00323 void NET_Shutdown (void)
00324 {
00325 #ifdef _WIN32
00326 WSACleanup();
00327 #endif
00328 dbuffer_shutdown();
00329 }
00330
00335 static void NET_StreamClose (struct net_stream *s)
00336 {
00337 if (!s || s->closed)
00338 return;
00339
00340 if (s->socket != INVALID_SOCKET) {
00341 if (dbuffer_len(s->outbound))
00342 Com_Printf("The outbound buffer for this socket (%d) is not empty\n", s->socket);
00343 else if (dbuffer_len(s->inbound))
00344 Com_Printf("The inbound buffer for this socket (%d) is not empty\n", s->socket);
00345
00346 FD_CLR(s->socket, &read_fds);
00347 FD_CLR(s->socket, &write_fds);
00348 netCloseSocket(s->socket);
00349 s->socket = INVALID_SOCKET;
00350 }
00351 if (s->index >= 0)
00352 streams[s->index] = NULL;
00353
00354 if (s->loopback_peer) {
00355
00356 s->loopback_peer->outbound = NULL;
00357 s->loopback_peer->loopback_peer = NULL;
00358 }
00359
00360 s->closed = qtrue;
00361 Com_DPrintf(DEBUG_SERVER, "Close stream at index: %i\n", s->index);
00362
00363
00364
00365 if (!s->loopback_peer)
00366 free_dbuffer(s->outbound);
00367
00368 s->outbound = NULL;
00369 s->socket = INVALID_SOCKET;
00370
00371
00372 if (s->finished) {
00373 free_dbuffer(s->inbound);
00374 Mem_Free(s);
00375 } else if (s->func)
00376 s->func(s);
00377 }
00378
00379 static void do_accept (int sock)
00380 {
00381 const int index = NET_StreamGetFree();
00382 struct net_stream *s;
00383 if (index == -1) {
00384 Com_Printf("Too many streams open, rejecting inbound connection\n");
00385 netCloseSocket(sock);
00386 return;
00387 }
00388
00389 s = NET_StreamNew(index);
00390 s->socket = sock;
00391 s->inbound = new_dbuffer();
00392 s->outbound = new_dbuffer();
00393 s->family = server_family;
00394 s->addrlen = server_addrlen;
00395 s->func = server_func;
00396
00397 maxfd = max(sock + 1, maxfd);
00398 FD_SET(sock, &read_fds);
00399
00400 server_func(s);
00402 }
00403
00407 void NET_Wait (int timeout)
00408 {
00409 struct timeval tv;
00410 int ready;
00411 int i;
00412
00413 fd_set read_fds_out;
00414 fd_set write_fds_out;
00415
00416 memcpy(&read_fds_out, &read_fds, sizeof(read_fds_out));
00417 memcpy(&write_fds_out, &write_fds, sizeof(write_fds_out));
00418
00419
00420
00421 if (loopback_ready)
00422 timeout = 0;
00423
00424 tv.tv_sec = timeout / 1000;
00425 tv.tv_usec = 1000 * (timeout % 1000);
00426 #ifdef _WIN32
00427 if (read_fds_out.fd_count == 0) {
00428 Sys_Sleep(timeout);
00429 ready = 0;
00430 } else
00431 #endif
00432 ready = select(maxfd, &read_fds_out, &write_fds_out, NULL, &tv);
00433
00434 if (ready == -1) {
00435 Com_Printf("select failed: %s\n", netStringError(netError));
00436 return;
00437 }
00438
00439 if (ready == 0 && !loopback_ready)
00440 return;
00441
00442 if (server_socket != INVALID_SOCKET && FD_ISSET(server_socket, &read_fds_out)) {
00443 const int client_socket = accept(server_socket, NULL, 0);
00444 if (client_socket == INVALID_SOCKET) {
00445 if (errno != EAGAIN)
00446 Com_Printf("accept on socket %d failed: %s\n", server_socket, netStringError(netError));
00447 } else
00448 do_accept(client_socket);
00449 }
00450
00451 for (i = 0; i < MAX_STREAMS; i++) {
00452 struct net_stream *s = streams[i];
00453
00454 if (!s)
00455 continue;
00456
00457 if (s->loopback) {
00458
00459 if (!s->loopback_peer && NET_StreamGetLength(s) == 0) {
00460 NET_StreamClose(s);
00461 }
00462
00463 else if (s->ready && s->func) {
00464 s->func(s);
00465 }
00466
00467 continue;
00468 }
00469
00470 if (s->socket == INVALID_SOCKET)
00471 continue;
00472
00473 if (FD_ISSET(s->socket, &write_fds_out)) {
00474 char buf[4096];
00475 int len;
00476
00477 if (dbuffer_len(s->outbound) == 0) {
00478 FD_CLR(s->socket, &write_fds);
00479
00480
00481 if (s->finished)
00482 NET_StreamClose(s);
00483
00484 continue;
00485 }
00486
00487 len = dbuffer_get(s->outbound, buf, sizeof(buf));
00488 len = send(s->socket, buf, len, 0);
00489
00490 if (len < 0) {
00491 Com_Printf("write on socket %d failed: %s\n", s->socket, netStringError(netError));
00492 NET_StreamClose(s);
00493 continue;
00494 }
00495
00496 Com_DPrintf(DEBUG_SERVER, "wrote %d bytes to stream %d (%s)\n", len, i, NET_StreamPeerToName(s, buf, sizeof(buf), qtrue));
00497
00498 dbuffer_remove(s->outbound, len);
00499 }
00500
00501 if (FD_ISSET(s->socket, &read_fds_out)) {
00502 char buf[4096];
00503 const int len = recv(s->socket, buf, sizeof(buf), 0);
00504 if (len <= 0) {
00505 if (len == -1)
00506 Com_Printf("read on socket %d failed: %s\n", s->socket, netStringError(netError));
00507 NET_StreamClose(s);
00508 continue;
00509 } else {
00510 if (s->inbound) {
00511 dbuffer_add(s->inbound, buf, len);
00512
00513 Com_DPrintf(DEBUG_SERVER, "read %d bytes from stream %d (%s)\n", len, i, NET_StreamPeerToName(s, buf, sizeof(buf), qtrue));
00514
00515
00516 if (s->func)
00517 s->func(s);
00518
00519 continue;
00520 }
00521 }
00522 }
00523 }
00524
00525 for (i = 0; i < MAX_DATAGRAM_SOCKETS; i++) {
00526 struct datagram_socket *s = datagram_sockets[i];
00527
00528 if (!s)
00529 continue;
00530
00531 if (FD_ISSET(s->socket, &write_fds_out)) {
00532 if (s->queue) {
00533 struct datagram *dgram = s->queue;
00534 const int len = sendto(s->socket, dgram->msg, dgram->len, 0, (struct sockaddr *)dgram->addr, s->addrlen);
00535 if (len == -1)
00536 Com_Printf("sendto on socket %d failed: %s\n", s->socket, netStringError(netError));
00537
00538 s->queue = dgram->next;
00539 Mem_Free(dgram->msg);
00540 Mem_Free(dgram->addr);
00541 Mem_Free(dgram);
00542 if (!s->queue)
00543 s->queue_tail = &s->queue;
00544 } else {
00545 FD_CLR(s->socket, &write_fds);
00546 }
00547 }
00548
00549 if (FD_ISSET(s->socket, &read_fds_out)) {
00550 char buf[256];
00551 char addrbuf[256];
00552 socklen_t addrlen = sizeof(addrbuf);
00553 const int len = recvfrom(s->socket, buf, sizeof(buf), 0, (struct sockaddr *)addrbuf, &addrlen);
00554 if (len == -1)
00555 Com_Printf("recvfrom on socket %d failed: %s\n", s->socket, netStringError(netError));
00556 else
00557 s->func(s, buf, len, (struct sockaddr *)addrbuf);
00558 }
00559 }
00560
00561 loopback_ready = qfalse;
00562 }
00563
00564 static qboolean NET_SocketSetNonBlocking (int socket)
00565 {
00566 unsigned long t = 1;
00567 if (ioctlsocket(socket, FIONBIO, &t) == -1) {
00568 Com_Printf("ioctl FIONBIO failed: %s\n", strerror(errno));
00569 return qfalse;
00570 }
00571 return qtrue;
00572 }
00573
00574 static struct net_stream *NET_DoConnect (const char *node, const char *service, const struct addrinfo *addr, int i)
00575 {
00576 struct net_stream *s;
00577 SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
00578 if (sock == INVALID_SOCKET) {
00579 Com_Printf("Failed to create socket: %s\n", netStringError(netError));
00580 return NULL;
00581 }
00582
00583 if (!NET_SocketSetNonBlocking(sock)) {
00584 netCloseSocket(sock);
00585 return NULL;
00586 }
00587
00588 if (connect(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
00589 const int err = netError;
00590 #ifdef _WIN32
00591 if (err != WSAEWOULDBLOCK) {
00592 #else
00593 if (err != EINPROGRESS) {
00594 #endif
00595 Com_Printf("Failed to start connection to %s:%s: %s\n", node, service, netStringError(err));
00596 netCloseSocket(sock);
00597 return NULL;
00598 }
00599 }
00600
00601 s = NET_StreamNew(i);
00602 s->socket = sock;
00603 s->inbound = new_dbuffer();
00604 s->outbound = new_dbuffer();
00605 s->family = addr->ai_family;
00606 s->addrlen = addr->ai_addrlen;
00607
00608 maxfd = max(sock + 1, maxfd);
00609 FD_SET(sock, &read_fds);
00610
00611 return s;
00612 }
00613
00622 struct net_stream *NET_Connect (const char *node, const char *service)
00623 {
00624 struct addrinfo *res;
00625 struct addrinfo hints;
00626 int rc;
00627 struct net_stream *s = NULL;
00628 int index;
00629
00630 memset(&hints, 0, sizeof(hints));
00631 hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
00632 hints.ai_socktype = SOCK_STREAM;
00633
00634 if (net_ipv4->integer)
00635 hints.ai_family = AF_INET;
00636
00637 rc = getaddrinfo(node, service, &hints, &res);
00638 if (rc != 0) {
00639 Com_Printf("Failed to resolve host %s:%s: %s\n", node, service, gai_strerror(rc));
00640 return NULL;
00641 }
00642
00643 index = NET_StreamGetFree();
00644 if (index == -1) {
00645 Com_Printf("Failed to connect to host %s:%s, too many streams open\n", node, service);
00646 freeaddrinfo(res);
00647 return NULL;
00648 }
00649
00650 s = NET_DoConnect(node, service, res, index);
00651
00652 freeaddrinfo(res);
00653 return s;
00654 }
00655
00659 struct net_stream *NET_ConnectToLoopBack (void)
00660 {
00661 struct net_stream *client, *server;
00662 int server_index, client_index;
00663
00664 if (!server_running)
00665 return NULL;
00666
00667 server_index = NET_StreamGetFree();
00668 client_index = NET_StreamGetFree();
00669
00670 if (server_index == -1 || client_index == -1 || server_index == client_index) {
00671 Com_Printf("Failed to connect to loopback server, too many streams open\n");
00672 return NULL;
00673 }
00674
00675 client = NET_StreamNew(client_index);
00676 client->loopback = qtrue;
00677 client->inbound = new_dbuffer();
00678 client->outbound = new_dbuffer();
00679
00680 server = NET_StreamNew(server_index);
00681 server->loopback = qtrue;
00682 server->inbound = client->outbound;
00683 server->outbound = client->inbound;
00684 server->func = server_func;
00685
00686 client->loopback_peer = server;
00687 server->loopback_peer = client;
00688
00689 server_func(server);
00690
00691 return client;
00692 }
00693
00699 void NET_StreamEnqueue (struct net_stream *s, const char *data, int len)
00700 {
00701 if (len <= 0 || !s || s->closed || s->finished)
00702 return;
00703
00704 if (s->outbound)
00705 dbuffer_add(s->outbound, data, len);
00706
00707 if (s->socket >= 0)
00708 FD_SET(s->socket, &write_fds);
00709
00710 if (s->loopback_peer) {
00711 loopback_ready = qtrue;
00712 s->loopback_peer->ready = qtrue;
00713 }
00714 }
00715
00716 qboolean NET_StreamIsClosed (struct net_stream *s)
00717 {
00718 return s ? (s->closed || s->finished) : qtrue;
00719 }
00720
00721 int NET_StreamGetLength (struct net_stream *s)
00722 {
00723 return s ? dbuffer_len(s->inbound) : 0;
00724 }
00725
00730 int NET_StreamPeek (struct net_stream *s, char *data, int len)
00731 {
00732 if (len <= 0 || !s)
00733 return 0;
00734
00735 if ((s->closed || s->finished) && dbuffer_len(s->inbound) == 0)
00736 return 0;
00737
00738 return dbuffer_get(s->inbound, data, len);
00739 }
00740
00745 int NET_StreamDequeue (struct net_stream *s, char *data, int len)
00746 {
00747 if (len <= 0 || !s || s->finished)
00748 return 0;
00749
00750 return dbuffer_extract(s->inbound, data, len);
00751 }
00752
00753 void *NET_StreamGetData (struct net_stream *s)
00754 {
00755 return s ? s->data : NULL;
00756 }
00757
00758 void NET_StreamSetData (struct net_stream *s, void *data)
00759 {
00760 if (!s)
00761 return;
00762 s->data = data;
00763 }
00764
00770 void NET_StreamFree (struct net_stream *s)
00771 {
00772 if (!s)
00773 return;
00774 s->finished = qtrue;
00775 NET_StreamClose(s);
00776 }
00777
00785 void NET_StreamFinished (struct net_stream *s)
00786 {
00787 if (!s)
00788 return;
00789
00790 s->finished = qtrue;
00791
00792 if (s->socket >= 0)
00793 FD_CLR(s->socket, &read_fds);
00794
00795
00796 if (s->loopback_peer)
00797 s->loopback_peer->outbound = NULL;
00798
00799 free_dbuffer(s->inbound);
00800 s->inbound = NULL;
00801
00802
00803
00804 if (dbuffer_len(s->outbound) == 0)
00805 NET_StreamClose(s);
00806 }
00807
00814 const char *NET_StreamPeerToName (struct net_stream *s, char *dst, int len, qboolean appendPort)
00815 {
00816 if (!s)
00817 return "(null)";
00818 else if (NET_StreamIsLoopback(s))
00819 return "loopback connection";
00820 else {
00821 char buf[128];
00822 char node[64];
00823 char service[64];
00824 int rc;
00825 socklen_t addrlen = s->addrlen;
00826 if (getpeername(s->socket, (struct sockaddr *)buf, &addrlen) != 0)
00827 return "(error)";
00828
00829 rc = getnameinfo((struct sockaddr *)buf, addrlen, node, sizeof(node), service, sizeof(service),
00830 NI_NUMERICHOST | NI_NUMERICSERV);
00831 if (rc != 0) {
00832 Com_Printf("Failed to convert sockaddr to string: %s\n", gai_strerror(rc));
00833 return "(error)";
00834 }
00835 if (!appendPort)
00836 Q_strncpyz(dst, node, len);
00837 else {
00838 node[sizeof(node) - 1] = '\0';
00839 service[sizeof(service) - 1] = '\0';
00840 Com_sprintf(dst, len, "%s %s", node, service);
00841 }
00842 return dst;
00843 }
00844 }
00845
00846 void NET_StreamSetCallback (struct net_stream *s, stream_callback_func *func)
00847 {
00848 if (!s)
00849 return;
00850 s->func = func;
00851 }
00852
00853 qboolean NET_StreamIsLoopback (struct net_stream *s)
00854 {
00855 return s && s->loopback;
00856 }
00857
00858 static int NET_DoStartServer (const struct addrinfo *addr)
00859 {
00860 SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
00861 int t = 1;
00862
00863 if (sock == INVALID_SOCKET) {
00864 Com_Printf("Failed to create socket: %s\n", netStringError(netError));
00865 return INVALID_SOCKET;
00866 }
00867
00868 if (!NET_SocketSetNonBlocking(sock)) {
00869 netCloseSocket(sock);
00870 return INVALID_SOCKET;
00871 }
00872
00873 #ifdef _WIN32
00874 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) != 0) {
00875 #else
00876 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(t)) != 0) {
00877 #endif
00878 Com_Printf("Failed to set SO_REUSEADDR on socket: %s\n", netStringError(netError));
00879 netCloseSocket(sock);
00880 return INVALID_SOCKET;
00881 }
00882
00883 if (bind(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
00884 Com_Printf("Failed to bind socket: %s\n", netStringError(netError));
00885 netCloseSocket(sock);
00886 return INVALID_SOCKET;
00887 }
00888
00889 if (listen(sock, SOMAXCONN) != 0) {
00890 Com_Printf("Failed to listen on socket: %s\n", netStringError(netError));
00891 netCloseSocket(sock);
00892 return INVALID_SOCKET;
00893 }
00894
00895 maxfd = max(sock + 1, maxfd);
00896 FD_SET(sock, &read_fds);
00897 server_family = addr->ai_family;
00898 server_addrlen = addr->ai_addrlen;
00899
00900 return sock;
00901 }
00902
00912 qboolean SV_Start (const char *node, const char *service, stream_callback_func *func)
00913 {
00914 if (!func)
00915 return qfalse;
00916
00917 if (server_running) {
00918 Com_Printf("SV_Start: Server is still running - call SV_Stop before\n");
00919 return qfalse;
00920 }
00921
00922 if (service) {
00923 struct addrinfo *res;
00924 struct addrinfo hints;
00925 int rc;
00926
00927 memset(&hints, 0, sizeof(hints));
00928 hints.ai_flags = AI_NUMERICHOST | AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE;
00929 hints.ai_socktype = SOCK_STREAM;
00930
00931 if (net_ipv4->integer)
00932 hints.ai_family = AF_INET;
00933
00934 rc = getaddrinfo(node, service, &hints, &res);
00935
00936 if (rc != 0) {
00937 Com_Printf("Failed to resolve host %s:%s: %s\n", node ? node : "*", service, gai_strerror(rc));
00938 return qfalse;
00939 }
00940
00941 server_socket = NET_DoStartServer(res);
00942 if (server_socket == INVALID_SOCKET) {
00943 Com_Printf("Failed to start server on %s:%s\n", node ? node : "*", service);
00944 } else {
00945 server_running = qtrue;
00946 server_func = func;
00947 }
00948 freeaddrinfo(res);
00949 } else {
00950
00951 server_running = qtrue;
00952 server_func = func;
00953 }
00954
00955 return server_running;
00956 }
00957
00961 void SV_Stop (void)
00962 {
00963 server_running = qfalse;
00964 server_func = NULL;
00965 if (server_socket != INVALID_SOCKET) {
00966 FD_CLR(server_socket, &read_fds);
00967 netCloseSocket(server_socket);
00968 }
00969 server_socket = INVALID_SOCKET;
00970 }
00971
00975 static struct datagram_socket *NET_DatagramSocketDoNew (const struct addrinfo *addr)
00976 {
00977 struct datagram_socket *s;
00978 SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
00979 int t = 1;
00980 const int index = NET_DatagramFindFreeSocket();
00981
00982 if (index == -1) {
00983 Com_Printf("Too many datagram sockets open\n");
00984 return NULL;
00985 }
00986
00987 if (sock == INVALID_SOCKET) {
00988 Com_Printf("Failed to create socket: %s\n", netStringError(netError));
00989 return NULL;
00990 }
00991
00992 if (!NET_SocketSetNonBlocking(sock)) {
00993 netCloseSocket(sock);
00994 return NULL;
00995 }
00996
00997 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) != 0) {
00998 Com_Printf("Failed to set SO_REUSEADDR on socket: %s\n", netStringError(netError));
00999 netCloseSocket(sock);
01000 return NULL;
01001 }
01002
01003 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &t, sizeof(t)) != 0) {
01004 Com_Printf("Failed to set SO_BROADCAST on socket: %s\n", netStringError(netError));
01005 netCloseSocket(sock);
01006 return NULL;
01007 }
01008
01009 if (bind(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
01010 Com_Printf("Failed to bind socket: %s\n", netStringError(netError));
01011 netCloseSocket(sock);
01012 return NULL;
01013 }
01014
01015 maxfd = max(sock + 1, maxfd);
01016 FD_SET(sock, &read_fds);
01017
01018 s = Mem_PoolAlloc(sizeof(*s), com_networkPool, 0);
01019 s->family = addr->ai_family;
01020 s->addrlen = addr->ai_addrlen;
01021 s->socket = sock;
01022 s->index = index;
01023 s->queue = NULL;
01024 s->queue_tail = &s->queue;
01025 s->func = NULL;
01026 datagram_sockets[index] = s;
01027
01028 return s;
01029 }
01030
01038 struct datagram_socket *NET_DatagramSocketNew (const char *node, const char *service, datagram_callback_func *func)
01039 {
01040 struct datagram_socket *s;
01041 struct addrinfo *res;
01042 struct addrinfo hints;
01043 int rc;
01044
01045 if (!service || !func)
01046 return NULL;
01047
01048 memset(&hints, 0, sizeof(hints));
01049 hints.ai_flags = AI_NUMERICHOST | AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE;
01050 hints.ai_socktype = SOCK_DGRAM;
01051
01052 if (net_ipv4->integer)
01053 hints.ai_family = AF_INET;
01054
01055 rc = getaddrinfo(node, service, &hints, &res);
01056
01057 if (rc != 0) {
01058 Com_Printf("Failed to resolve host %s:%s: %s\n", node ? node : "*", service, gai_strerror(rc));
01059 return qfalse;
01060 }
01061
01062 s = NET_DatagramSocketDoNew(res);
01063 if (s)
01064 s->func = func;
01065
01066 freeaddrinfo(res);
01067 return s;
01068 }
01069
01073 void NET_DatagramSend (struct datagram_socket *s, const char *buf, int len, struct sockaddr *to)
01074 {
01075 struct datagram *dgram;
01076 if (!s || len <= 0 || !buf || !to)
01077 return;
01078
01079 dgram = Mem_PoolAlloc(sizeof(*dgram), com_networkPool, 0);
01080 dgram->msg = Mem_PoolAlloc(len, com_networkPool, 0);
01081 dgram->addr = Mem_PoolAlloc(s->addrlen, com_networkPool, 0);
01082 memcpy(dgram->msg, buf, len);
01083 memcpy(dgram->addr, to, len);
01084 dgram->len = len;
01085 dgram->next = NULL;
01086
01087 *s->queue_tail = dgram;
01088 s->queue_tail = &dgram->next;
01089
01090 FD_SET(s->socket, &write_fds);
01091 }
01092
01098 void NET_DatagramBroadcast (struct datagram_socket *s, const char *buf, int len, int port)
01099 {
01100 if (s->family == AF_INET) {
01101 struct sockaddr_in addr;
01102 addr.sin_family = AF_INET;
01103 addr.sin_port = htons(port);
01104 addr.sin_addr.s_addr = INADDR_BROADCAST;
01105 NET_DatagramSend(s, buf, len, (struct sockaddr *)&addr);
01106 } else if (s->family == AF_INET6) {
01107 struct sockaddr_in addr;
01108 addr.sin_family = AF_INET6;
01109 addr.sin_port = htons(port);
01110 addr.sin_addr.s_addr = INADDR_BROADCAST;
01111 NET_DatagramSend(s, buf, len, (struct sockaddr *)&addr);
01112 } else {
01113 Com_Error(ERR_DROP, "Broadcast unsupported on address family %d\n", s->family);
01114 }
01115 }
01116
01121 void NET_DatagramSocketClose (struct datagram_socket *s)
01122 {
01123 if (!s)
01124 return;
01125
01126 FD_CLR(s->socket, &read_fds);
01127 FD_CLR(s->socket, &write_fds);
01128 netCloseSocket(s->socket);
01129
01130 while (s->queue) {
01131 struct datagram *dgram = s->queue;
01132 s->queue = dgram->next;
01133 Mem_Free(dgram->msg);
01134 Mem_Free(dgram->addr);
01135 Mem_Free(dgram);
01136 }
01137
01138 datagram_sockets[s->index] = NULL;
01139 Mem_Free(s);
01140 }
01141
01151 void NET_SockaddrToStrings (struct datagram_socket *s, struct sockaddr *addr, char *node, size_t nodelen, char *service, size_t servicelen)
01152 {
01153 const int rc = getnameinfo(addr, s->addrlen, node, nodelen, service, servicelen,
01154 NI_NUMERICHOST | NI_NUMERICSERV | NI_DGRAM);
01155 if (rc != 0) {
01156 Com_Printf("Failed to convert sockaddr to string: %s\n", gai_strerror(rc));
01157 Q_strncpyz(node, "(error)", nodelen);
01158 Q_strncpyz(service, "(error)", servicelen);
01159 }
01160 }