|
|
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 <sys/time.h> 27: #include <netinet/in.h> 28: #include <netdb.h> 29: #include <sys/param.h> 30: #include <sys/ioctl.h> 31: #include <sys/uio.h> 32: #include <errno.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); 1.1.1.2 ! root 302: ! 303: SockadrToNetadr (&from, net_from); ! 304: 1.1 root 305: if (ret == -1) 306: { 307: err = errno; 308: 309: if (err == EWOULDBLOCK || err == ECONNREFUSED) 310: continue; 1.1.1.2 ! root 311: Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(), ! 312: NET_AdrToString(*net_from)); 1.1 root 313: continue; 314: } 315: 316: if (ret == net_message->maxsize) 317: { 318: Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); 319: continue; 320: } 321: 322: net_message->cursize = ret; 323: return true; 324: } 325: 326: return false; 327: } 328: 329: //============================================================================= 330: 331: void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) 332: { 333: int ret; 334: struct sockaddr_in addr; 335: int net_socket; 336: 337: if ( to.type == NA_LOOPBACK ) 338: { 339: NET_SendLoopPacket (sock, length, data, to); 340: return; 341: } 342: 343: if (to.type == NA_BROADCAST) 344: { 345: net_socket = ip_sockets[sock]; 346: if (!net_socket) 347: return; 348: } 349: else if (to.type == NA_IP) 350: { 351: net_socket = ip_sockets[sock]; 352: if (!net_socket) 353: return; 354: } 355: else if (to.type == NA_IPX) 356: { 357: net_socket = ipx_sockets[sock]; 358: if (!net_socket) 359: return; 360: } 361: else if (to.type == NA_BROADCAST_IPX) 362: { 363: net_socket = ipx_sockets[sock]; 364: if (!net_socket) 365: return; 366: } 367: else 368: Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); 369: 370: NetadrToSockadr (&to, &addr); 371: 372: ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); 373: if (ret == -1) 374: { 1.1.1.2 ! root 375: Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(), ! 376: NET_AdrToString (to)); 1.1 root 377: } 378: } 379: 380: 381: //============================================================================= 382: 383: 384: 385: 386: /* 387: ==================== 388: NET_OpenIP 389: ==================== 390: */ 391: void NET_OpenIP (void) 392: { 393: cvar_t *port, *ip; 394: 395: port = Cvar_Get ("port", va("%i", PORT_SERVER), CVAR_NOSET); 396: ip = Cvar_Get ("ip", "localhost", CVAR_NOSET); 397: 398: if (!ip_sockets[NS_SERVER]) 399: ip_sockets[NS_SERVER] = NET_Socket (ip->string, port->value); 400: if (!ip_sockets[NS_CLIENT]) 401: ip_sockets[NS_CLIENT] = NET_Socket (ip->string, PORT_ANY); 402: } 403: 404: /* 405: ==================== 406: NET_OpenIPX 407: ==================== 408: */ 409: void NET_OpenIPX (void) 410: { 411: } 412: 413: 414: /* 415: ==================== 416: NET_Config 417: 418: A single player game will only use the loopback code 419: ==================== 420: */ 421: void NET_Config (qboolean multiplayer) 422: { 423: int i; 424: 425: if (!multiplayer) 426: { // shut down any existing sockets 427: for (i=0 ; i<2 ; i++) 428: { 429: if (ip_sockets[i]) 430: { 431: close (ip_sockets[i]); 432: ip_sockets[i] = 0; 433: } 434: if (ipx_sockets[i]) 435: { 436: close (ipx_sockets[i]); 437: ipx_sockets[i] = 0; 438: } 439: } 440: } 441: else 442: { // open sockets 443: NET_OpenIP (); 444: NET_OpenIPX (); 445: } 446: } 447: 448: 449: //=================================================================== 450: 451: 452: /* 453: ==================== 454: NET_Init 455: ==================== 456: */ 457: void NET_Init (void) 458: { 459: } 460: 461: 462: /* 463: ==================== 464: NET_Socket 465: ==================== 466: */ 467: int NET_Socket (char *net_interface, int port) 468: { 469: int newsocket; 470: struct sockaddr_in address; 471: qboolean _true = true; 472: int i = 1; 473: 474: if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 475: { 1.1.1.2 ! root 476: Com_Printf ("ERROR: UDP_OpenSocket: socket: %s", NET_ErrorString()); 1.1 root 477: return 0; 478: } 479: 480: // make it non-blocking 481: if (ioctl (newsocket, FIONBIO, &_true) == -1) 482: { 483: Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString()); 484: return 0; 485: } 486: 487: // make it broadcast capable 488: if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) 489: { 490: Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString()); 491: return 0; 492: } 493: 494: if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) 495: address.sin_addr.s_addr = INADDR_ANY; 496: else 497: NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); 498: 499: if (port == PORT_ANY) 500: address.sin_port = 0; 501: else 502: address.sin_port = htons((short)port); 503: 504: address.sin_family = AF_INET; 505: 506: if( bind (newsocket, (void *)&address, sizeof(address)) == -1) 507: { 508: Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); 509: close (newsocket); 510: return 0; 511: } 512: 513: return newsocket; 514: } 515: 516: 517: /* 518: ==================== 519: NET_Shutdown 520: ==================== 521: */ 522: void NET_Shutdown (void) 523: { 524: NET_Config (false); // close sockets 525: } 526: 527: 528: /* 529: ==================== 530: NET_ErrorString 531: ==================== 532: */ 533: char *NET_ErrorString (void) 534: { 535: int code; 536: 537: code = errno; 538: return strerror (code); 539: } 540: 541: // sleeps msec or until net socket is ready 542: void NET_Sleep(int msec) 543: { 544: struct timeval timeout; 545: fd_set fdset; 546: extern cvar_t *dedicated; 547: extern qboolean stdin_active; 548: 549: if (!ip_sockets[NS_SERVER] || (dedicated && !dedicated->value)) 550: return; // we're not a server, just run full speed 551: 552: FD_ZERO(&fdset); 553: if (stdin_active) 554: FD_SET(0, &fdset); // stdin is processed too 555: FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket 556: timeout.tv_sec = msec/1000; 557: timeout.tv_usec = (msec%1000)*1000; 558: select(ip_sockets[NS_SERVER]+1, &fdset, NULL, NULL, &timeout); 559: } 560:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.