|
|
1.1.1.2 ! root 1: /* ! 2: Copyright (C) 1997-2001 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ 1.1 root 20: // net_wins.c 21: 22: #include "../qcommon/qcommon.h" 23: 24: #include <unistd.h> 25: #include <sys/socket.h> 26: #include <netinet/in.h> 27: #include <netdb.h> 28: #include <sys/param.h> 29: #include <sys/ioctl.h> 30: #include <sys/uio.h> 31: #include <errno.h> 32: #include <sys/filio.h> 33: 34: #ifdef NeXT 35: #include <libc.h> 36: #endif 37: 38: netadr_t net_local_adr; 39: 40: #define LOOPBACK 0x7f000001 41: 42: #define MAX_LOOPBACK 4 43: 44: typedef struct 45: { 46: byte data[MAX_MSGLEN]; 47: int datalen; 48: } loopmsg_t; 49: 50: typedef struct 51: { 52: loopmsg_t msgs[MAX_LOOPBACK]; 53: int get, send; 54: } loopback_t; 55: 56: loopback_t loopbacks[2]; 57: int ip_sockets[2]; 58: int ipx_sockets[2]; 59: 60: int NET_Socket (char *net_interface, int port); 61: char *NET_ErrorString (void); 62: 63: //============================================================================= 64: 65: void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s) 66: { 67: memset (s, 0, sizeof(*s)); 68: 69: if (a->type == NA_BROADCAST) 70: { 71: s->sin_family = AF_INET; 72: 73: s->sin_port = a->port; 74: *(int *)&s->sin_addr = -1; 75: } 76: else if (a->type == NA_IP) 77: { 78: s->sin_family = AF_INET; 79: 80: *(int *)&s->sin_addr = *(int *)&a->ip; 81: s->sin_port = a->port; 82: } 83: } 84: 85: void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a) 86: { 87: *(int *)&a->ip = *(int *)&s->sin_addr; 88: a->port = s->sin_port; 89: a->type = NA_IP; 90: } 91: 92: 93: qboolean NET_CompareAdr (netadr_t a, netadr_t b) 94: { 95: if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port) 96: return true; 97: return false; 98: } 99: 100: /* 101: =================== 102: NET_CompareBaseAdr 103: 104: Compares without the port 105: =================== 106: */ 107: qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) 108: { 109: if (a.type != b.type) 110: return false; 111: 112: if (a.type == NA_LOOPBACK) 113: return true; 114: 115: if (a.type == NA_IP) 116: { 117: if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3]) 118: return true; 119: return false; 120: } 121: 122: if (a.type == NA_IPX) 123: { 124: if ((memcmp(a.ipx, b.ipx, 10) == 0)) 125: return true; 126: return false; 127: } 128: } 129: 130: char *NET_AdrToString (netadr_t a) 131: { 132: static char s[64]; 133: 134: Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port)); 135: 136: return s; 137: } 138: 139: char *NET_BaseAdrToString (netadr_t a) 140: { 141: static char s[64]; 142: 143: Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); 144: 145: return s; 146: } 147: 148: /* 149: ============= 150: NET_StringToAdr 151: 152: localhost 153: idnewt 154: idnewt:28000 155: 192.246.40.70 156: 192.246.40.70:28000 157: ============= 158: */ 159: qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr) 160: { 161: struct hostent *h; 162: char *colon; 163: char copy[128]; 164: 165: memset (sadr, 0, sizeof(*sadr)); 166: ((struct sockaddr_in *)sadr)->sin_family = AF_INET; 167: 168: ((struct sockaddr_in *)sadr)->sin_port = 0; 169: 170: strcpy (copy, s); 171: // strip off a trailing :port if present 172: for (colon = copy ; *colon ; colon++) 173: if (*colon == ':') 174: { 175: *colon = 0; 176: ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1)); 177: } 178: 179: if (copy[0] >= '0' && copy[0] <= '9') 180: { 181: *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy); 182: } 183: else 184: { 185: if (! (h = gethostbyname(copy)) ) 186: return 0; 187: *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; 188: } 189: 190: return true; 191: } 192: 193: /* 194: ============= 195: NET_StringToAdr 196: 197: localhost 198: idnewt 199: idnewt:28000 200: 192.246.40.70 201: 192.246.40.70:28000 202: ============= 203: */ 204: qboolean NET_StringToAdr (char *s, netadr_t *a) 205: { 206: struct sockaddr_in sadr; 207: 208: if (!strcmp (s, "localhost")) 209: { 210: memset (a, 0, sizeof(*a)); 211: a->type = NA_LOOPBACK; 212: return true; 213: } 214: 215: if (!NET_StringToSockaddr (s, (struct sockaddr *)&sadr)) 216: return false; 217: 218: SockadrToNetadr (&sadr, a); 219: 220: return true; 221: } 222: 223: 224: qboolean NET_IsLocalAddress (netadr_t adr) 225: { 226: return NET_CompareAdr (adr, net_local_adr); 227: } 228: 229: /* 230: ============================================================================= 231: 232: LOOPBACK BUFFERS FOR LOCAL PLAYER 233: 234: ============================================================================= 235: */ 236: 237: qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) 238: { 239: int i; 240: loopback_t *loop; 241: 242: loop = &loopbacks[sock]; 243: 244: if (loop->send - loop->get > MAX_LOOPBACK) 245: loop->get = loop->send - MAX_LOOPBACK; 246: 247: if (loop->get >= loop->send) 248: return false; 249: 250: i = loop->get & (MAX_LOOPBACK-1); 251: loop->get++; 252: 253: memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen); 254: net_message->cursize = loop->msgs[i].datalen; 255: *net_from = net_local_adr; 256: return true; 257: 258: } 259: 260: 261: void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) 262: { 263: int i; 264: loopback_t *loop; 265: 266: loop = &loopbacks[sock^1]; 267: 268: i = loop->send & (MAX_LOOPBACK-1); 269: loop->send++; 270: 271: memcpy (loop->msgs[i].data, data, length); 272: loop->msgs[i].datalen = length; 273: } 274: 275: //============================================================================= 276: 277: qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) 278: { 279: int ret; 280: struct sockaddr_in from; 281: int fromlen; 282: int net_socket; 283: int protocol; 284: int err; 285: 286: if (NET_GetLoopPacket (sock, net_from, net_message)) 287: return true; 288: 289: for (protocol = 0 ; protocol < 2 ; protocol++) 290: { 291: if (protocol == 0) 292: net_socket = ip_sockets[sock]; 293: else 294: net_socket = ipx_sockets[sock]; 295: 296: if (!net_socket) 297: continue; 298: 299: fromlen = sizeof(from); 300: ret = recvfrom (net_socket, net_message->data, net_message->maxsize 301: , 0, (struct sockaddr *)&from, &fromlen); 302: if (ret == -1) 303: { 304: err = errno; 305: 306: if (err == EWOULDBLOCK || err == ECONNREFUSED) 307: continue; 308: Com_Printf ("NET_GetPacket: %s", NET_ErrorString()); 309: continue; 310: } 311: 312: if (ret == net_message->maxsize) 313: { 314: Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); 315: continue; 316: } 317: 318: net_message->cursize = ret; 319: SockadrToNetadr (&from, net_from); 320: return true; 321: } 322: 323: return false; 324: } 325: 326: //============================================================================= 327: 328: void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) 329: { 330: int ret; 331: struct sockaddr_in addr; 332: int net_socket; 333: 334: if ( to.type == NA_LOOPBACK ) 335: { 336: NET_SendLoopPacket (sock, length, data, to); 337: return; 338: } 339: 340: if (to.type == NA_BROADCAST) 341: { 342: net_socket = ip_sockets[sock]; 343: if (!net_socket) 344: return; 345: } 346: else if (to.type == NA_IP) 347: { 348: net_socket = ip_sockets[sock]; 349: if (!net_socket) 350: return; 351: } 352: else if (to.type == NA_IPX) 353: { 354: net_socket = ipx_sockets[sock]; 355: if (!net_socket) 356: return; 357: } 358: else if (to.type == NA_BROADCAST_IPX) 359: { 360: net_socket = ipx_sockets[sock]; 361: if (!net_socket) 362: return; 363: } 364: else 365: Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); 366: 367: NetadrToSockadr (&to, &addr); 368: 369: ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); 370: if (ret == -1) 371: { 372: Com_Printf ("NET_SendPacket ERROR: %i\n", NET_ErrorString()); 373: } 374: } 375: 376: 377: //============================================================================= 378: 379: 380: 381: 382: /* 383: ==================== 384: NET_OpenIP 385: ==================== 386: */ 387: void NET_OpenIP (void) 388: { 389: cvar_t *port, *ip; 390: 391: port = Cvar_Get ("port", va("%i", PORT_SERVER), CVAR_NOSET); 392: ip = Cvar_Get ("ip", "localhost", CVAR_NOSET); 393: 394: if (!ip_sockets[NS_SERVER]) 395: ip_sockets[NS_SERVER] = NET_Socket (ip->string, port->value); 396: if (!ip_sockets[NS_CLIENT]) 397: ip_sockets[NS_CLIENT] = NET_Socket (ip->string, PORT_ANY); 398: } 399: 400: /* 401: ==================== 402: NET_OpenIPX 403: ==================== 404: */ 405: void NET_OpenIPX (void) 406: { 407: } 408: 409: 410: /* 411: ==================== 412: NET_Config 413: 414: A single player game will only use the loopback code 415: ==================== 416: */ 417: void NET_Config (qboolean multiplayer) 418: { 419: int i; 420: 421: if (!multiplayer) 422: { // shut down any existing sockets 423: for (i=0 ; i<2 ; i++) 424: { 425: if (ip_sockets[i]) 426: { 427: close (ip_sockets[i]); 428: ip_sockets[i] = 0; 429: } 430: if (ipx_sockets[i]) 431: { 432: close (ipx_sockets[i]); 433: ipx_sockets[i] = 0; 434: } 435: } 436: } 437: else 438: { // open sockets 439: NET_OpenIP (); 440: NET_OpenIPX (); 441: } 442: } 443: 444: 445: //=================================================================== 446: 447: 448: /* 449: ==================== 450: NET_Init 451: ==================== 452: */ 453: void NET_Init (void) 454: { 455: } 456: 457: 458: /* 459: ==================== 460: NET_Socket 461: ==================== 462: */ 463: int NET_Socket (char *net_interface, int port) 464: { 465: int newsocket; 466: struct sockaddr_in address; 467: qboolean _true = true; 468: int i = 1; 469: 470: if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 471: { 472: Com_Printf ("ERROR: UDP_OpenSocket: socket:", NET_ErrorString()); 473: return 0; 474: } 475: 476: // make it non-blocking 477: if (ioctl (newsocket, FIONBIO, &_true) == -1) 478: { 479: Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString()); 480: return 0; 481: } 482: 483: // make it broadcast capable 484: if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) 485: { 486: Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString()); 487: return 0; 488: } 489: 490: if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) 491: address.sin_addr.s_addr = INADDR_ANY; 492: else 493: NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); 494: 495: if (port == PORT_ANY) 496: address.sin_port = 0; 497: else 498: address.sin_port = htons((short)port); 499: 500: address.sin_family = AF_INET; 501: 502: if( bind (newsocket, (void *)&address, sizeof(address)) == -1) 503: { 504: Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); 505: close (newsocket); 506: return 0; 507: } 508: 509: return newsocket; 510: } 511: 512: 513: /* 514: ==================== 515: NET_Shutdown 516: ==================== 517: */ 518: void NET_Shutdown (void) 519: { 520: NET_Config (false); // close sockets 521: } 522: 523: 524: /* 525: ==================== 526: NET_ErrorString 527: ==================== 528: */ 529: char *NET_ErrorString (void) 530: { 531: int code; 532: 533: code = errno; 534: return strerror (code); 535: } 536: 537: // sleeps msec or until net socket is ready 538: void NET_Sleep(int msec) 539: { 540: struct timeval timeout; 541: fd_set fdset; 542: extern cvar_t *dedicated; 543: extern qboolean stdin_active; 544: 545: if (!ip_sockets[NS_SERVER] || (dedicated && !dedicated->value)) 546: return; // we're not a server, just run full speed 547: 548: FD_ZERO(&fdset); 549: if (stdin_active) 550: FD_SET(0, &fdset); // stdin is processed too 551: FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket 552: timeout.tv_sec = msec/1000; 553: timeout.tv_usec = (msec%1000)*1000; 554: select(ip_sockets[NS_SERVER]+1, &fdset, NULL, NULL, &timeout); 555: } 556:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.