net_wins.c (18761B)
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 */ 20 // net_wins.c 21 22 #include "winsock.h" 23 #include "wsipx.h" 24 #include "../qcommon/qcommon.h" 25 26 #define MAX_LOOPBACK 4 27 28 typedef struct 29 { 30 byte data[MAX_MSGLEN]; 31 int datalen; 32 } loopmsg_t; 33 34 typedef struct 35 { 36 loopmsg_t msgs[MAX_LOOPBACK]; 37 int get, send; 38 } loopback_t; 39 40 41 cvar_t *net_shownet; 42 static cvar_t *noudp; 43 static cvar_t *noipx; 44 45 loopback_t loopbacks[2]; 46 int ip_sockets[2]; 47 int ipx_sockets[2]; 48 49 char *NET_ErrorString (void); 50 51 //============================================================================= 52 53 void NetadrToSockadr (netadr_t *a, struct sockaddr *s) 54 { 55 memset (s, 0, sizeof(*s)); 56 57 if (a->type == NA_BROADCAST) 58 { 59 ((struct sockaddr_in *)s)->sin_family = AF_INET; 60 ((struct sockaddr_in *)s)->sin_port = a->port; 61 ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; 62 } 63 else if (a->type == NA_IP) 64 { 65 ((struct sockaddr_in *)s)->sin_family = AF_INET; 66 ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; 67 ((struct sockaddr_in *)s)->sin_port = a->port; 68 } 69 else if (a->type == NA_IPX) 70 { 71 ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; 72 memcpy(((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4); 73 memcpy(((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6); 74 ((struct sockaddr_ipx *)s)->sa_socket = a->port; 75 } 76 else if (a->type == NA_BROADCAST_IPX) 77 { 78 ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; 79 memset(((struct sockaddr_ipx *)s)->sa_netnum, 0, 4); 80 memset(((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6); 81 ((struct sockaddr_ipx *)s)->sa_socket = a->port; 82 } 83 } 84 85 void SockadrToNetadr (struct sockaddr *s, netadr_t *a) 86 { 87 if (s->sa_family == AF_INET) 88 { 89 a->type = NA_IP; 90 *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; 91 a->port = ((struct sockaddr_in *)s)->sin_port; 92 } 93 else if (s->sa_family == AF_IPX) 94 { 95 a->type = NA_IPX; 96 memcpy(&a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4); 97 memcpy(&a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6); 98 a->port = ((struct sockaddr_ipx *)s)->sa_socket; 99 } 100 } 101 102 103 qboolean NET_CompareAdr (netadr_t a, netadr_t b) 104 { 105 if (a.type != b.type) 106 return false; 107 108 if (a.type == NA_LOOPBACK) 109 return TRUE; 110 111 if (a.type == NA_IP) 112 { 113 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) 114 return true; 115 return false; 116 } 117 118 if (a.type == NA_IPX) 119 { 120 if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port) 121 return true; 122 return false; 123 } 124 } 125 126 /* 127 =================== 128 NET_CompareBaseAdr 129 130 Compares without the port 131 =================== 132 */ 133 qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) 134 { 135 if (a.type != b.type) 136 return false; 137 138 if (a.type == NA_LOOPBACK) 139 return TRUE; 140 141 if (a.type == NA_IP) 142 { 143 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]) 144 return true; 145 return false; 146 } 147 148 if (a.type == NA_IPX) 149 { 150 if ((memcmp(a.ipx, b.ipx, 10) == 0)) 151 return true; 152 return false; 153 } 154 } 155 156 char *NET_AdrToString (netadr_t a) 157 { 158 static char s[64]; 159 160 if (a.type == NA_LOOPBACK) 161 Com_sprintf (s, sizeof(s), "loopback"); 162 else if (a.type == NA_IP) 163 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)); 164 else 165 Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], ntohs(a.port)); 166 167 return s; 168 } 169 170 171 /* 172 ============= 173 NET_StringToAdr 174 175 localhost 176 idnewt 177 idnewt:28000 178 192.246.40.70 179 192.246.40.70:28000 180 ============= 181 */ 182 #define DO(src,dest) \ 183 copy[0] = s[src]; \ 184 copy[1] = s[src + 1]; \ 185 sscanf (copy, "%x", &val); \ 186 ((struct sockaddr_ipx *)sadr)->dest = val 187 188 qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr) 189 { 190 struct hostent *h; 191 char *colon; 192 int val; 193 char copy[128]; 194 195 memset (sadr, 0, sizeof(*sadr)); 196 197 if ((strlen(s) >= 23) && (s[8] == ':') && (s[21] == ':')) // check for an IPX address 198 { 199 ((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX; 200 copy[2] = 0; 201 DO(0, sa_netnum[0]); 202 DO(2, sa_netnum[1]); 203 DO(4, sa_netnum[2]); 204 DO(6, sa_netnum[3]); 205 DO(9, sa_nodenum[0]); 206 DO(11, sa_nodenum[1]); 207 DO(13, sa_nodenum[2]); 208 DO(15, sa_nodenum[3]); 209 DO(17, sa_nodenum[4]); 210 DO(19, sa_nodenum[5]); 211 sscanf (&s[22], "%u", &val); 212 ((struct sockaddr_ipx *)sadr)->sa_socket = htons((unsigned short)val); 213 } 214 else 215 { 216 ((struct sockaddr_in *)sadr)->sin_family = AF_INET; 217 218 ((struct sockaddr_in *)sadr)->sin_port = 0; 219 220 strcpy (copy, s); 221 // strip off a trailing :port if present 222 for (colon = copy ; *colon ; colon++) 223 if (*colon == ':') 224 { 225 *colon = 0; 226 ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1)); 227 } 228 229 if (copy[0] >= '0' && copy[0] <= '9') 230 { 231 *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy); 232 } 233 else 234 { 235 if (! (h = gethostbyname(copy)) ) 236 return 0; 237 *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; 238 } 239 } 240 241 return true; 242 } 243 244 #undef DO 245 246 /* 247 ============= 248 NET_StringToAdr 249 250 localhost 251 idnewt 252 idnewt:28000 253 192.246.40.70 254 192.246.40.70:28000 255 ============= 256 */ 257 qboolean NET_StringToAdr (char *s, netadr_t *a) 258 { 259 struct sockaddr sadr; 260 261 if (!strcmp (s, "localhost")) 262 { 263 memset (a, 0, sizeof(*a)); 264 a->type = NA_LOOPBACK; 265 return true; 266 } 267 268 if (!NET_StringToSockaddr (s, &sadr)) 269 return false; 270 271 SockadrToNetadr (&sadr, a); 272 273 return true; 274 } 275 276 277 qboolean NET_IsLocalAddress (netadr_t adr) 278 { 279 return adr.type == NA_LOOPBACK; 280 } 281 282 /* 283 ============================================================================= 284 285 LOOPBACK BUFFERS FOR LOCAL PLAYER 286 287 ============================================================================= 288 */ 289 290 qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) 291 { 292 int i; 293 loopback_t *loop; 294 295 loop = &loopbacks[sock]; 296 297 if (loop->send - loop->get > MAX_LOOPBACK) 298 loop->get = loop->send - MAX_LOOPBACK; 299 300 if (loop->get >= loop->send) 301 return false; 302 303 i = loop->get & (MAX_LOOPBACK-1); 304 loop->get++; 305 306 memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen); 307 net_message->cursize = loop->msgs[i].datalen; 308 memset (net_from, 0, sizeof(*net_from)); 309 net_from->type = NA_LOOPBACK; 310 return true; 311 312 } 313 314 315 void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) 316 { 317 int i; 318 loopback_t *loop; 319 320 loop = &loopbacks[sock^1]; 321 322 i = loop->send & (MAX_LOOPBACK-1); 323 loop->send++; 324 325 memcpy (loop->msgs[i].data, data, length); 326 loop->msgs[i].datalen = length; 327 } 328 329 //============================================================================= 330 331 qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) 332 { 333 int ret; 334 struct sockaddr from; 335 int fromlen; 336 int net_socket; 337 int protocol; 338 int err; 339 340 if (NET_GetLoopPacket (sock, net_from, net_message)) 341 return true; 342 343 for (protocol = 0 ; protocol < 2 ; protocol++) 344 { 345 if (protocol == 0) 346 net_socket = ip_sockets[sock]; 347 else 348 net_socket = ipx_sockets[sock]; 349 350 if (!net_socket) 351 continue; 352 353 fromlen = sizeof(from); 354 ret = recvfrom (net_socket, net_message->data, net_message->maxsize 355 , 0, (struct sockaddr *)&from, &fromlen); 356 if (ret == -1) 357 { 358 err = WSAGetLastError(); 359 360 if (err == WSAEWOULDBLOCK) 361 continue; 362 if (dedicated->value) // let dedicated servers continue after errors 363 Com_Printf ("NET_GetPacket: %s", NET_ErrorString()); 364 else 365 Com_Error (ERR_DROP, "NET_GetPacket: %s", NET_ErrorString()); 366 continue; 367 } 368 369 SockadrToNetadr (&from, net_from); 370 371 if (ret == net_message->maxsize) 372 { 373 Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); 374 continue; 375 } 376 377 net_message->cursize = ret; 378 return true; 379 } 380 381 return false; 382 } 383 384 //============================================================================= 385 386 void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) 387 { 388 int ret; 389 struct sockaddr addr; 390 int net_socket; 391 392 if ( to.type == NA_LOOPBACK ) 393 { 394 NET_SendLoopPacket (sock, length, data, to); 395 return; 396 } 397 398 if (to.type == NA_BROADCAST) 399 { 400 net_socket = ip_sockets[sock]; 401 if (!net_socket) 402 return; 403 } 404 else if (to.type == NA_IP) 405 { 406 net_socket = ip_sockets[sock]; 407 if (!net_socket) 408 return; 409 } 410 else if (to.type == NA_IPX) 411 { 412 net_socket = ipx_sockets[sock]; 413 if (!net_socket) 414 return; 415 } 416 else if (to.type == NA_BROADCAST_IPX) 417 { 418 net_socket = ipx_sockets[sock]; 419 if (!net_socket) 420 return; 421 } 422 else 423 Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); 424 425 NetadrToSockadr (&to, &addr); 426 427 ret = sendto (net_socket, data, length, 0, &addr, sizeof(addr) ); 428 if (ret == -1) 429 { 430 int err = WSAGetLastError(); 431 432 // wouldblock is silent 433 if (err == WSAEWOULDBLOCK) 434 return; 435 436 // some PPP links dont allow broadcasts 437 if ((err == WSAEADDRNOTAVAIL) && ((to.type == NA_BROADCAST) || (to.type == NA_BROADCAST_IPX))) 438 return; 439 440 if (dedicated->value) // let dedicated servers continue after errors 441 { 442 Com_Printf ("NET_SendPacket ERROR: %s\n", NET_ErrorString()); 443 } 444 else 445 { 446 if (err == WSAEADDRNOTAVAIL) 447 { 448 Com_DPrintf ("NET_SendPacket Warning: %s : %s\n", NET_ErrorString(), NET_AdrToString (to)); 449 } 450 else 451 { 452 Com_Error (ERR_DROP, "NET_SendPacket ERROR: %s\n", NET_ErrorString()); 453 } 454 } 455 } 456 } 457 458 459 //============================================================================= 460 461 462 /* 463 ==================== 464 NET_Socket 465 ==================== 466 */ 467 int NET_IPSocket (char *net_interface, int port) 468 { 469 int newsocket; 470 struct sockaddr_in address; 471 qboolean _true = true; 472 int i = 1; 473 int err; 474 475 if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 476 { 477 err = WSAGetLastError(); 478 if (err != WSAEAFNOSUPPORT) 479 Com_Printf ("WARNING: UDP_OpenSocket: socket: %s", NET_ErrorString()); 480 return 0; 481 } 482 483 // make it non-blocking 484 if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) 485 { 486 Com_Printf ("WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString()); 487 return 0; 488 } 489 490 // make it broadcast capable 491 if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) 492 { 493 Com_Printf ("WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString()); 494 return 0; 495 } 496 497 if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) 498 address.sin_addr.s_addr = INADDR_ANY; 499 else 500 NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); 501 502 if (port == PORT_ANY) 503 address.sin_port = 0; 504 else 505 address.sin_port = htons((short)port); 506 507 address.sin_family = AF_INET; 508 509 if( bind (newsocket, (void *)&address, sizeof(address)) == -1) 510 { 511 Com_Printf ("WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); 512 closesocket (newsocket); 513 return 0; 514 } 515 516 return newsocket; 517 } 518 519 520 /* 521 ==================== 522 NET_OpenIP 523 ==================== 524 */ 525 void NET_OpenIP (void) 526 { 527 cvar_t *ip; 528 int port; 529 int dedicated; 530 531 ip = Cvar_Get ("ip", "localhost", CVAR_NOSET); 532 533 dedicated = Cvar_VariableValue ("dedicated"); 534 535 if (!ip_sockets[NS_SERVER]) 536 { 537 port = Cvar_Get("ip_hostport", "0", CVAR_NOSET)->value; 538 if (!port) 539 { 540 port = Cvar_Get("hostport", "0", CVAR_NOSET)->value; 541 if (!port) 542 { 543 port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value; 544 } 545 } 546 ip_sockets[NS_SERVER] = NET_IPSocket (ip->string, port); 547 if (!ip_sockets[NS_SERVER] && dedicated) 548 Com_Error (ERR_FATAL, "Couldn't allocate dedicated server IP port"); 549 } 550 551 552 // dedicated servers don't need client ports 553 if (dedicated) 554 return; 555 556 if (!ip_sockets[NS_CLIENT]) 557 { 558 port = Cvar_Get("ip_clientport", "0", CVAR_NOSET)->value; 559 if (!port) 560 { 561 port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value; 562 if (!port) 563 port = PORT_ANY; 564 } 565 ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, port); 566 if (!ip_sockets[NS_CLIENT]) 567 ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, PORT_ANY); 568 } 569 } 570 571 572 /* 573 ==================== 574 IPX_Socket 575 ==================== 576 */ 577 int NET_IPXSocket (int port) 578 { 579 int newsocket; 580 struct sockaddr_ipx address; 581 int _true = 1; 582 int err; 583 584 if ((newsocket = socket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1) 585 { 586 err = WSAGetLastError(); 587 if (err != WSAEAFNOSUPPORT) 588 Com_Printf ("WARNING: IPX_Socket: socket: %s\n", NET_ErrorString()); 589 return 0; 590 } 591 592 // make it non-blocking 593 if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) 594 { 595 Com_Printf ("WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString()); 596 return 0; 597 } 598 599 // make it broadcast capable 600 if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) == -1) 601 { 602 Com_Printf ("WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString()); 603 return 0; 604 } 605 606 address.sa_family = AF_IPX; 607 memset (address.sa_netnum, 0, 4); 608 memset (address.sa_nodenum, 0, 6); 609 if (port == PORT_ANY) 610 address.sa_socket = 0; 611 else 612 address.sa_socket = htons((short)port); 613 614 if( bind (newsocket, (void *)&address, sizeof(address)) == -1) 615 { 616 Com_Printf ("WARNING: IPX_Socket: bind: %s\n", NET_ErrorString()); 617 closesocket (newsocket); 618 return 0; 619 } 620 621 return newsocket; 622 } 623 624 625 /* 626 ==================== 627 NET_OpenIPX 628 ==================== 629 */ 630 void NET_OpenIPX (void) 631 { 632 int port; 633 int dedicated; 634 635 dedicated = Cvar_VariableValue ("dedicated"); 636 637 if (!ipx_sockets[NS_SERVER]) 638 { 639 port = Cvar_Get("ipx_hostport", "0", CVAR_NOSET)->value; 640 if (!port) 641 { 642 port = Cvar_Get("hostport", "0", CVAR_NOSET)->value; 643 if (!port) 644 { 645 port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value; 646 } 647 } 648 ipx_sockets[NS_SERVER] = NET_IPXSocket (port); 649 } 650 651 // dedicated servers don't need client ports 652 if (dedicated) 653 return; 654 655 if (!ipx_sockets[NS_CLIENT]) 656 { 657 port = Cvar_Get("ipx_clientport", "0", CVAR_NOSET)->value; 658 if (!port) 659 { 660 port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value; 661 if (!port) 662 port = PORT_ANY; 663 } 664 ipx_sockets[NS_CLIENT] = NET_IPXSocket (port); 665 if (!ipx_sockets[NS_CLIENT]) 666 ipx_sockets[NS_CLIENT] = NET_IPXSocket (PORT_ANY); 667 } 668 } 669 670 671 /* 672 ==================== 673 NET_Config 674 675 A single player game will only use the loopback code 676 ==================== 677 */ 678 void NET_Config (qboolean multiplayer) 679 { 680 int i; 681 static qboolean old_config; 682 683 if (old_config == multiplayer) 684 return; 685 686 old_config = multiplayer; 687 688 if (!multiplayer) 689 { // shut down any existing sockets 690 for (i=0 ; i<2 ; i++) 691 { 692 if (ip_sockets[i]) 693 { 694 closesocket (ip_sockets[i]); 695 ip_sockets[i] = 0; 696 } 697 if (ipx_sockets[i]) 698 { 699 closesocket (ipx_sockets[i]); 700 ipx_sockets[i] = 0; 701 } 702 } 703 } 704 else 705 { // open sockets 706 if (! noudp->value) 707 NET_OpenIP (); 708 if (! noipx->value) 709 NET_OpenIPX (); 710 } 711 } 712 713 // sleeps msec or until net socket is ready 714 void NET_Sleep(int msec) 715 { 716 struct timeval timeout; 717 fd_set fdset; 718 extern cvar_t *dedicated; 719 int i; 720 721 if (!dedicated || !dedicated->value) 722 return; // we're not a server, just run full speed 723 724 FD_ZERO(&fdset); 725 i = 0; 726 if (ip_sockets[NS_SERVER]) { 727 FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket 728 i = ip_sockets[NS_SERVER]; 729 } 730 if (ipx_sockets[NS_SERVER]) { 731 FD_SET(ipx_sockets[NS_SERVER], &fdset); // network socket 732 if (ipx_sockets[NS_SERVER] > i) 733 i = ipx_sockets[NS_SERVER]; 734 } 735 timeout.tv_sec = msec/1000; 736 timeout.tv_usec = (msec%1000)*1000; 737 select(i+1, &fdset, NULL, NULL, &timeout); 738 } 739 740 //=================================================================== 741 742 743 static WSADATA winsockdata; 744 745 /* 746 ==================== 747 NET_Init 748 ==================== 749 */ 750 void NET_Init (void) 751 { 752 WORD wVersionRequested; 753 int r; 754 755 wVersionRequested = MAKEWORD(1, 1); 756 757 r = WSAStartup (MAKEWORD(1, 1), &winsockdata); 758 759 if (r) 760 Com_Error (ERR_FATAL,"Winsock initialization failed."); 761 762 Com_Printf("Winsock Initialized\n"); 763 764 noudp = Cvar_Get ("noudp", "0", CVAR_NOSET); 765 noipx = Cvar_Get ("noipx", "0", CVAR_NOSET); 766 767 net_shownet = Cvar_Get ("net_shownet", "0", 0); 768 } 769 770 771 /* 772 ==================== 773 NET_Shutdown 774 ==================== 775 */ 776 void NET_Shutdown (void) 777 { 778 NET_Config (false); // close sockets 779 780 WSACleanup (); 781 } 782 783 784 /* 785 ==================== 786 NET_ErrorString 787 ==================== 788 */ 789 char *NET_ErrorString (void) 790 { 791 int code; 792 793 code = WSAGetLastError (); 794 switch (code) 795 { 796 case WSAEINTR: return "WSAEINTR"; 797 case WSAEBADF: return "WSAEBADF"; 798 case WSAEACCES: return "WSAEACCES"; 799 case WSAEDISCON: return "WSAEDISCON"; 800 case WSAEFAULT: return "WSAEFAULT"; 801 case WSAEINVAL: return "WSAEINVAL"; 802 case WSAEMFILE: return "WSAEMFILE"; 803 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK"; 804 case WSAEINPROGRESS: return "WSAEINPROGRESS"; 805 case WSAEALREADY: return "WSAEALREADY"; 806 case WSAENOTSOCK: return "WSAENOTSOCK"; 807 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ"; 808 case WSAEMSGSIZE: return "WSAEMSGSIZE"; 809 case WSAEPROTOTYPE: return "WSAEPROTOTYPE"; 810 case WSAENOPROTOOPT: return "WSAENOPROTOOPT"; 811 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT"; 812 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT"; 813 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP"; 814 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT"; 815 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT"; 816 case WSAEADDRINUSE: return "WSAEADDRINUSE"; 817 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL"; 818 case WSAENETDOWN: return "WSAENETDOWN"; 819 case WSAENETUNREACH: return "WSAENETUNREACH"; 820 case WSAENETRESET: return "WSAENETRESET"; 821 case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR"; 822 case WSAECONNRESET: return "WSAECONNRESET"; 823 case WSAENOBUFS: return "WSAENOBUFS"; 824 case WSAEISCONN: return "WSAEISCONN"; 825 case WSAENOTCONN: return "WSAENOTCONN"; 826 case WSAESHUTDOWN: return "WSAESHUTDOWN"; 827 case WSAETOOMANYREFS: return "WSAETOOMANYREFS"; 828 case WSAETIMEDOUT: return "WSAETIMEDOUT"; 829 case WSAECONNREFUSED: return "WSAECONNREFUSED"; 830 case WSAELOOP: return "WSAELOOP"; 831 case WSAENAMETOOLONG: return "WSAENAMETOOLONG"; 832 case WSAEHOSTDOWN: return "WSAEHOSTDOWN"; 833 case WSASYSNOTREADY: return "WSASYSNOTREADY"; 834 case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED"; 835 case WSANOTINITIALISED: return "WSANOTINITIALISED"; 836 case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND"; 837 case WSATRY_AGAIN: return "WSATRY_AGAIN"; 838 case WSANO_RECOVERY: return "WSANO_RECOVERY"; 839 case WSANO_DATA: return "WSANO_DATA"; 840 default: return "NO ERROR"; 841 } 842 }