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