net_udp.c (9960B)
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