Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

win_net.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // net_wins.c
00023 
00024 #include "../game/q_shared.h"
00025 #include "../qcommon/qcommon.h"
00026 #include "win_local.h"
00027 
00028 static WSADATA  winsockdata;
00029 static qboolean winsockInitialized = qfalse;
00030 static qboolean usingSocks = qfalse;
00031 static qboolean networkingEnabled = qfalse;
00032 
00033 static cvar_t   *net_noudp;
00034 static cvar_t   *net_noipx;
00035 
00036 static cvar_t   *net_socksEnabled;
00037 static cvar_t   *net_socksServer;
00038 static cvar_t   *net_socksPort;
00039 static cvar_t   *net_socksUsername;
00040 static cvar_t   *net_socksPassword;
00041 static struct sockaddr  socksRelayAddr;
00042 
00043 static SOCKET   ip_socket;
00044 static SOCKET   socks_socket;
00045 static SOCKET   ipx_socket;
00046 
00047 #define MAX_IPS     16
00048 static  int     numIP;
00049 static  byte    localIP[MAX_IPS][4];
00050 
00051 //=============================================================================
00052 
00053 
00054 /*
00055 ====================
00056 NET_ErrorString
00057 ====================
00058 */
00059 char *NET_ErrorString( void ) {
00060     int     code;
00061 
00062     code = WSAGetLastError();
00063     switch( code ) {
00064     case WSAEINTR: return "WSAEINTR";
00065     case WSAEBADF: return "WSAEBADF";
00066     case WSAEACCES: return "WSAEACCES";
00067     case WSAEDISCON: return "WSAEDISCON";
00068     case WSAEFAULT: return "WSAEFAULT";
00069     case WSAEINVAL: return "WSAEINVAL";
00070     case WSAEMFILE: return "WSAEMFILE";
00071     case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
00072     case WSAEINPROGRESS: return "WSAEINPROGRESS";
00073     case WSAEALREADY: return "WSAEALREADY";
00074     case WSAENOTSOCK: return "WSAENOTSOCK";
00075     case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
00076     case WSAEMSGSIZE: return "WSAEMSGSIZE";
00077     case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
00078     case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
00079     case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
00080     case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
00081     case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
00082     case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
00083     case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
00084     case WSAEADDRINUSE: return "WSAEADDRINUSE";
00085     case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
00086     case WSAENETDOWN: return "WSAENETDOWN";
00087     case WSAENETUNREACH: return "WSAENETUNREACH";
00088     case WSAENETRESET: return "WSAENETRESET";
00089     case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
00090     case WSAECONNRESET: return "WSAECONNRESET";
00091     case WSAENOBUFS: return "WSAENOBUFS";
00092     case WSAEISCONN: return "WSAEISCONN";
00093     case WSAENOTCONN: return "WSAENOTCONN";
00094     case WSAESHUTDOWN: return "WSAESHUTDOWN";
00095     case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
00096     case WSAETIMEDOUT: return "WSAETIMEDOUT";
00097     case WSAECONNREFUSED: return "WSAECONNREFUSED";
00098     case WSAELOOP: return "WSAELOOP";
00099     case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
00100     case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
00101     case WSASYSNOTREADY: return "WSASYSNOTREADY";
00102     case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
00103     case WSANOTINITIALISED: return "WSANOTINITIALISED";
00104     case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
00105     case WSATRY_AGAIN: return "WSATRY_AGAIN";
00106     case WSANO_RECOVERY: return "WSANO_RECOVERY";
00107     case WSANO_DATA: return "WSANO_DATA";
00108     default: return "NO ERROR";
00109     }
00110 }
00111 
00112 void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) {
00113     memset( s, 0, sizeof(*s) );
00114 
00115     if( a->type == NA_BROADCAST ) {
00116         ((struct sockaddr_in *)s)->sin_family = AF_INET;
00117         ((struct sockaddr_in *)s)->sin_port = a->port;
00118         ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
00119     }
00120     else if( a->type == NA_IP ) {
00121         ((struct sockaddr_in *)s)->sin_family = AF_INET;
00122         ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
00123         ((struct sockaddr_in *)s)->sin_port = a->port;
00124     }
00125     else if( a->type == NA_IPX ) {
00126         ((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
00127         memcpy( ((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4 );
00128         memcpy( ((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6 );
00129         ((struct sockaddr_ipx *)s)->sa_socket = a->port;
00130     }
00131     else if( a->type == NA_BROADCAST_IPX ) {
00132         ((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
00133         memset( ((struct sockaddr_ipx *)s)->sa_netnum, 0, 4 );
00134         memset( ((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6 );
00135         ((struct sockaddr_ipx *)s)->sa_socket = a->port;
00136     }
00137 }
00138 
00139 
00140 void SockadrToNetadr( struct sockaddr *s, netadr_t *a ) {
00141     if (s->sa_family == AF_INET) {
00142         a->type = NA_IP;
00143         *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
00144         a->port = ((struct sockaddr_in *)s)->sin_port;
00145     }
00146     else if( s->sa_family == AF_IPX ) {
00147         a->type = NA_IPX;
00148         memcpy( &a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4 );
00149         memcpy( &a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6 );
00150         a->port = ((struct sockaddr_ipx *)s)->sa_socket;
00151     }
00152 }
00153 
00154 
00155 /*
00156 =============
00157 Sys_StringToAdr
00158 
00159 idnewt
00160 192.246.40.70
00161 12121212.121212121212
00162 =============
00163 */
00164 #define DO(src,dest)    \
00165     copy[0] = s[src];   \
00166     copy[1] = s[src + 1];   \
00167     sscanf (copy, "%x", &val);  \
00168     ((struct sockaddr_ipx *)sadr)->dest = val
00169 
00170 qboolean Sys_StringToSockaddr( const char *s, struct sockaddr *sadr ) {
00171     struct hostent  *h;
00172     int     val;
00173     char    copy[MAX_STRING_CHARS];
00174     
00175     memset( sadr, 0, sizeof( *sadr ) );
00176 
00177     // check for an IPX address
00178     if( ( strlen( s ) == 21 ) && ( s[8] == '.' ) ) {
00179         ((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX;
00180         ((struct sockaddr_ipx *)sadr)->sa_socket = 0;
00181         copy[2] = 0;
00182         DO(0, sa_netnum[0]);
00183         DO(2, sa_netnum[1]);
00184         DO(4, sa_netnum[2]);
00185         DO(6, sa_netnum[3]);
00186         DO(9, sa_nodenum[0]);
00187         DO(11, sa_nodenum[1]);
00188         DO(13, sa_nodenum[2]);
00189         DO(15, sa_nodenum[3]);
00190         DO(17, sa_nodenum[4]);
00191         DO(19, sa_nodenum[5]);
00192     }
00193     else {
00194         ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
00195         ((struct sockaddr_in *)sadr)->sin_port = 0;
00196 
00197         if( s[0] >= '0' && s[0] <= '9' ) {
00198             *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s);
00199         } else {
00200             if( ( h = gethostbyname( s ) ) == 0 ) {
00201                 return 0;
00202             }
00203             *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
00204         }
00205     }
00206     
00207     return qtrue;
00208 }
00209 
00210 #undef DO
00211 
00212 /*
00213 =============
00214 Sys_StringToAdr
00215 
00216 idnewt
00217 192.246.40.70
00218 =============
00219 */
00220 qboolean Sys_StringToAdr( const char *s, netadr_t *a ) {
00221     struct sockaddr sadr;
00222     
00223     if ( !Sys_StringToSockaddr( s, &sadr ) ) {
00224         return qfalse;
00225     }
00226     
00227     SockadrToNetadr( &sadr, a );
00228     return qtrue;
00229 }
00230 
00231 //=============================================================================
00232 
00233 /*
00234 ==================
00235 Sys_GetPacket
00236 
00237 Never called by the game logic, just the system event queing
00238 ==================
00239 */
00240 int recvfromCount;
00241 
00242 qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
00243     int     ret;
00244     struct sockaddr from;
00245     int     fromlen;
00246     int     net_socket;
00247     int     protocol;
00248     int     err;
00249 
00250     for( protocol = 0 ; protocol < 2 ; protocol++ ) {
00251         if( protocol == 0 ) {
00252             net_socket = ip_socket;
00253         }
00254         else {
00255             net_socket = ipx_socket;
00256         }
00257 
00258         if( !net_socket ) {
00259             continue;
00260         }
00261 
00262         fromlen = sizeof(from);
00263         recvfromCount++;        // performance check
00264         ret = recvfrom( net_socket, net_message->data, net_message->maxsize, 0, (struct sockaddr *)&from, &fromlen );
00265         if (ret == SOCKET_ERROR)
00266         {
00267             err = WSAGetLastError();
00268 
00269             if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
00270                 continue;
00271             }
00272             Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() );
00273             continue;
00274         }
00275 
00276         if ( net_socket == ip_socket ) {
00277             memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 );
00278         }
00279 
00280         if ( usingSocks && net_socket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
00281             if ( ret < 10 || net_message->data[0] != 0 || net_message->data[1] != 0 || net_message->data[2] != 0 || net_message->data[3] != 1 ) {
00282                 continue;
00283             }
00284             net_from->type = NA_IP;
00285             net_from->ip[0] = net_message->data[4];
00286             net_from->ip[1] = net_message->data[5];
00287             net_from->ip[2] = net_message->data[6];
00288             net_from->ip[3] = net_message->data[7];
00289             net_from->port = *(short *)&net_message->data[8];
00290             net_message->readcount = 10;
00291         }
00292         else {
00293             SockadrToNetadr( &from, net_from );
00294             net_message->readcount = 0;
00295         }
00296 
00297         if( ret == net_message->maxsize ) {
00298             Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
00299             continue;
00300         }
00301 
00302         net_message->cursize = ret;
00303         return qtrue;
00304     }
00305 
00306     return qfalse;
00307 }
00308 
00309 //=============================================================================
00310 
00311 static char socksBuf[4096];
00312 
00313 /*
00314 ==================
00315 Sys_SendPacket
00316 ==================
00317 */
00318 void Sys_SendPacket( int length, const void *data, netadr_t to ) {
00319     int             ret;
00320     struct sockaddr addr;
00321     SOCKET          net_socket;
00322 
00323     if( to.type == NA_BROADCAST ) {
00324         net_socket = ip_socket;
00325     }
00326     else if( to.type == NA_IP ) {
00327         net_socket = ip_socket;
00328     }
00329     else if( to.type == NA_IPX ) {
00330         net_socket = ipx_socket;
00331     }
00332     else if( to.type == NA_BROADCAST_IPX ) {
00333         net_socket = ipx_socket;
00334     }
00335     else {
00336         Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" );
00337         return;
00338     }
00339 
00340     if( !net_socket ) {
00341         return;
00342     }
00343 
00344     NetadrToSockadr( &to, &addr );
00345 
00346     if( usingSocks && to.type == NA_IP ) {
00347         socksBuf[0] = 0;    // reserved
00348         socksBuf[1] = 0;
00349         socksBuf[2] = 0;    // fragment (not fragmented)
00350         socksBuf[3] = 1;    // address type: IPV4
00351         *(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
00352         *(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port;
00353         memcpy( &socksBuf[10], data, length );
00354         ret = sendto( net_socket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr) );
00355     }
00356     else {
00357         ret = sendto( net_socket, data, length, 0, &addr, sizeof(addr) );
00358     }
00359     if( ret == SOCKET_ERROR ) {
00360         int err = WSAGetLastError();
00361 
00362         // wouldblock is silent
00363         if( err == WSAEWOULDBLOCK ) {
00364             return;
00365         }
00366 
00367         // some PPP links do not allow broadcasts and return an error
00368         if( ( err == WSAEADDRNOTAVAIL ) && ( ( to.type == NA_BROADCAST ) || ( to.type == NA_BROADCAST_IPX ) ) ) {
00369             return;
00370         }
00371 
00372         Com_Printf( "NET_SendPacket: %s\n", NET_ErrorString() );
00373     }
00374 }
00375 
00376 
00377 //=============================================================================
00378 
00379 /*
00380 ==================
00381 Sys_IsLANAddress
00382 
00383 LAN clients will have their rate var ignored
00384 ==================
00385 */
00386 qboolean Sys_IsLANAddress( netadr_t adr ) {
00387     int     i;
00388 
00389     if( adr.type == NA_LOOPBACK ) {
00390         return qtrue;
00391     }
00392 
00393     if( adr.type == NA_IPX ) {
00394         return qtrue;
00395     }
00396 
00397     if( adr.type != NA_IP ) {
00398         return qfalse;
00399     }
00400 
00401     // choose which comparison to use based on the class of the address being tested
00402     // any local adresses of a different class than the address being tested will fail based on the first byte
00403 
00404     if( adr.ip[0] == 127 && adr.ip[1] == 0 && adr.ip[2] == 0 && adr.ip[3] == 1 ) {
00405         return qtrue;
00406     }
00407 
00408     // Class A
00409     if( (adr.ip[0] & 0x80) == 0x00 ) {
00410         for ( i = 0 ; i < numIP ; i++ ) {
00411             if( adr.ip[0] == localIP[i][0] ) {
00412                 return qtrue;
00413             }
00414         }
00415         // the RFC1918 class a block will pass the above test
00416         return qfalse;
00417     }
00418 
00419     // Class B
00420     if( (adr.ip[0] & 0xc0) == 0x80 ) {
00421         for ( i = 0 ; i < numIP ; i++ ) {
00422             if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) {
00423                 return qtrue;
00424             }
00425             // also check against the RFC1918 class b blocks
00426             if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) {
00427                 return qtrue;
00428             }
00429         }
00430         return qfalse;
00431     }
00432 
00433     // Class C
00434     for ( i = 0 ; i < numIP ; i++ ) {
00435         if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) {
00436             return qtrue;
00437         }
00438         // also check against the RFC1918 class c blocks
00439         if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) {
00440             return qtrue;
00441         }
00442     }
00443     return qfalse;
00444 }
00445 
00446 /*
00447 ==================
00448 Sys_ShowIP
00449 ==================
00450 */
00451 void Sys_ShowIP(void) {
00452     int i;
00453 
00454     for (i = 0; i < numIP; i++) {
00455         Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] );
00456     }
00457 }
00458 
00459 
00460 //=============================================================================
00461 
00462 
00463 /*
00464 ====================
00465 NET_IPSocket
00466 ====================
00467 */
00468 int NET_IPSocket( char *net_interface, int port ) {
00469     SOCKET              newsocket;
00470     struct sockaddr_in  address;
00471     qboolean            _true = qtrue;
00472     int                 i = 1;
00473     int                 err;
00474 
00475     if( net_interface ) {
00476         Com_Printf( "Opening IP socket: %s:%i\n", net_interface, port );
00477     }
00478     else {
00479         Com_Printf( "Opening IP socket: localhost:%i\n", port );
00480     }
00481 
00482     if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
00483         err = WSAGetLastError();
00484         if( err != WSAEAFNOSUPPORT ) {
00485             Com_Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() );
00486         }
00487         return 0;
00488     }
00489 
00490     // make it non-blocking
00491     if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
00492         Com_Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
00493         return 0;
00494     }
00495 
00496     // make it broadcast capable
00497     if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) {
00498         Com_Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
00499         return 0;
00500     }
00501 
00502     if( !net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost") ) {
00503         address.sin_addr.s_addr = INADDR_ANY;
00504     }
00505     else {
00506         Sys_StringToSockaddr( net_interface, (struct sockaddr *)&address );
00507     }
00508 
00509     if( port == PORT_ANY ) {
00510         address.sin_port = 0;
00511     }
00512     else {
00513         address.sin_port = htons( (short)port );
00514     }
00515 
00516     address.sin_family = AF_INET;
00517 
00518     if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) {
00519         Com_Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
00520         closesocket( newsocket );
00521         return 0;
00522     }
00523 
00524     return newsocket;
00525 }
00526 
00527 
00528 /*
00529 ====================
00530 NET_OpenSocks
00531 ====================
00532 */
00533 void NET_OpenSocks( int port ) {
00534     struct sockaddr_in  address;
00535     int                 err;
00536     struct hostent      *h;
00537     int                 len;
00538     qboolean            rfc1929;
00539     unsigned char       buf[64];
00540 
00541     usingSocks = qfalse;
00542 
00543     Com_Printf( "Opening connection to SOCKS server.\n" );
00544 
00545     if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
00546         err = WSAGetLastError();
00547         Com_Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
00548         return;
00549     }
00550 
00551     h = gethostbyname( net_socksServer->string );
00552     if ( h == NULL ) {
00553         err = WSAGetLastError();
00554         Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
00555         return;
00556     }
00557     if ( h->h_addrtype != AF_INET ) {
00558         Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
00559         return;
00560     }
00561     address.sin_family = AF_INET;
00562     address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
00563     address.sin_port = htons( (short)net_socksPort->integer );
00564 
00565     if ( connect( socks_socket, (struct sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) {
00566         err = WSAGetLastError();
00567         Com_Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
00568         return;
00569     }
00570 
00571     // send socks authentication handshake
00572     if ( *net_socksUsername->string || *net_socksPassword->string ) {
00573         rfc1929 = qtrue;
00574     }
00575     else {
00576         rfc1929 = qfalse;
00577     }
00578 
00579     buf[0] = 5;     // SOCKS version
00580     // method count
00581     if ( rfc1929 ) {
00582         buf[1] = 2;
00583         len = 4;
00584     }
00585     else {
00586         buf[1] = 1;
00587         len = 3;
00588     }
00589     buf[2] = 0;     // method #1 - method id #00: no authentication
00590     if ( rfc1929 ) {
00591         buf[2] = 2;     // method #2 - method id #02: username/password
00592     }
00593     if ( send( socks_socket, buf, len, 0 ) == SOCKET_ERROR ) {
00594         err = WSAGetLastError();
00595         Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
00596         return;
00597     }
00598 
00599     // get the response
00600     len = recv( socks_socket, buf, 64, 0 );
00601     if ( len == SOCKET_ERROR ) {
00602         err = WSAGetLastError();
00603         Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
00604         return;
00605     }
00606     if ( len != 2 || buf[0] != 5 ) {
00607         Com_Printf( "NET_OpenSocks: bad response\n" );
00608         return;
00609     }
00610     switch( buf[1] ) {
00611     case 0: // no authentication
00612         break;
00613     case 2: // username/password authentication
00614         break;
00615     default:
00616         Com_Printf( "NET_OpenSocks: request denied\n" );
00617         return;
00618     }
00619 
00620     // do username/password authentication if needed
00621     if ( buf[1] == 2 ) {
00622         int     ulen;
00623         int     plen;
00624 
00625         // build the request
00626         ulen = strlen( net_socksUsername->string );
00627         plen = strlen( net_socksPassword->string );
00628 
00629         buf[0] = 1;     // username/password authentication version
00630         buf[1] = ulen;
00631         if ( ulen ) {
00632             memcpy( &buf[2], net_socksUsername->string, ulen );
00633         }
00634         buf[2 + ulen] = plen;
00635         if ( plen ) {
00636             memcpy( &buf[3 + ulen], net_socksPassword->string, plen );
00637         }
00638 
00639         // send it
00640         if ( send( socks_socket, buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
00641             err = WSAGetLastError();
00642             Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
00643             return;
00644         }
00645 
00646         // get the response
00647         len = recv( socks_socket, buf, 64, 0 );
00648         if ( len == SOCKET_ERROR ) {
00649             err = WSAGetLastError();
00650             Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
00651             return;
00652         }
00653         if ( len != 2 || buf[0] != 1 ) {
00654             Com_Printf( "NET_OpenSocks: bad response\n" );
00655             return;
00656         }
00657         if ( buf[1] != 0 ) {
00658             Com_Printf( "NET_OpenSocks: authentication failed\n" );
00659             return;
00660         }
00661     }
00662 
00663     // send the UDP associate request
00664     buf[0] = 5;     // SOCKS version
00665     buf[1] = 3;     // command: UDP associate
00666     buf[2] = 0;     // reserved
00667     buf[3] = 1;     // address type: IPV4
00668     *(int *)&buf[4] = INADDR_ANY;
00669     *(short *)&buf[8] = htons( (short)port );       // port
00670     if ( send( socks_socket, buf, 10, 0 ) == SOCKET_ERROR ) {
00671         err = WSAGetLastError();
00672         Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
00673         return;
00674     }
00675 
00676     // get the response
00677     len = recv( socks_socket, buf, 64, 0 );
00678     if( len == SOCKET_ERROR ) {
00679         err = WSAGetLastError();
00680         Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
00681         return;
00682     }
00683     if( len < 2 || buf[0] != 5 ) {
00684         Com_Printf( "NET_OpenSocks: bad response\n" );
00685         return;
00686     }
00687     // check completion code
00688     if( buf[1] != 0 ) {
00689         Com_Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
00690         return;
00691     }
00692     if( buf[3] != 1 ) {
00693         Com_Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
00694         return;
00695     }
00696     ((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET;
00697     ((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4];
00698     ((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8];
00699     memset( ((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 );
00700 
00701     usingSocks = qtrue;
00702 }
00703 
00704 
00705 /*
00706 =====================
00707 NET_GetLocalAddress
00708 =====================
00709 */
00710 void NET_GetLocalAddress( void ) {
00711     char                hostname[256];
00712     struct hostent      *hostInfo;
00713     int                 error;
00714     char                *p;
00715     int                 ip;
00716     int                 n;
00717 
00718     if( gethostname( hostname, 256 ) == SOCKET_ERROR ) {
00719         error = WSAGetLastError();
00720         return;
00721     }
00722 
00723     hostInfo = gethostbyname( hostname );
00724     if( !hostInfo ) {
00725         error = WSAGetLastError();
00726         return;
00727     }
00728 
00729     Com_Printf( "Hostname: %s\n", hostInfo->h_name );
00730     n = 0;
00731     while( ( p = hostInfo->h_aliases[n++] ) != NULL ) {
00732         Com_Printf( "Alias: %s\n", p );
00733     }
00734 
00735     if ( hostInfo->h_addrtype != AF_INET ) {
00736         return;
00737     }
00738 
00739     numIP = 0;
00740     while( ( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS ) {
00741         ip = ntohl( *(int *)p );
00742         localIP[ numIP ][0] = p[0];
00743         localIP[ numIP ][1] = p[1];
00744         localIP[ numIP ][2] = p[2];
00745         localIP[ numIP ][3] = p[3];
00746         Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff );
00747         numIP++;
00748     }
00749 }
00750 
00751 /*
00752 ====================
00753 NET_OpenIP
00754 ====================
00755 */
00756 void NET_OpenIP( void ) {
00757     cvar_t  *ip;
00758     int     port;
00759     int     i;
00760 
00761     ip = Cvar_Get( "net_ip", "localhost", CVAR_LATCH );
00762     port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer;
00763 
00764     // automatically scan for a valid port, so multiple
00765     // dedicated servers can be started without requiring
00766     // a different net_port for each one
00767     for( i = 0 ; i < 10 ; i++ ) {
00768         ip_socket = NET_IPSocket( ip->string, port + i );
00769         if ( ip_socket ) {
00770             Cvar_SetValue( "net_port", port + i );
00771             if ( net_socksEnabled->integer ) {
00772                 NET_OpenSocks( port + i );
00773             }
00774             NET_GetLocalAddress();
00775             return;
00776         }
00777     }
00778     Com_Printf( "WARNING: Couldn't allocate IP port\n");
00779 }
00780 
00781 
00782 /*
00783 ====================
00784 NET_IPXSocket
00785 ====================
00786 */
00787 int NET_IPXSocket( int port ) {
00788     SOCKET              newsocket;
00789     struct sockaddr_ipx address;
00790     int                 _true = 1;
00791     int                 err;
00792 
00793     if( ( newsocket = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX ) ) == INVALID_SOCKET ) {
00794         err = WSAGetLastError();
00795         if (err != WSAEAFNOSUPPORT) {
00796             Com_Printf( "WARNING: IPX_Socket: socket: %s\n", NET_ErrorString() );
00797         }
00798         return 0;
00799     }
00800 
00801     // make it non-blocking
00802     if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
00803         Com_Printf( "WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString() );
00804         return 0;
00805     }
00806 
00807     // make it broadcast capable
00808     if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof( _true ) ) == SOCKET_ERROR ) {
00809         Com_Printf( "WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
00810         return 0;
00811     }
00812 
00813     address.sa_family = AF_IPX;
00814     memset( address.sa_netnum, 0, 4 );
00815     memset( address.sa_nodenum, 0, 6 );
00816     if( port == PORT_ANY ) {
00817         address.sa_socket = 0;
00818     }
00819     else {
00820         address.sa_socket = htons( (short)port );
00821     }
00822 
00823     if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) {
00824         Com_Printf( "WARNING: IPX_Socket: bind: %s\n", NET_ErrorString() );
00825         closesocket( newsocket );
00826         return 0;
00827     }
00828 
00829     return newsocket;
00830 }
00831 
00832 
00833 /*
00834 ====================
00835 NET_OpenIPX
00836 ====================
00837 */
00838 void NET_OpenIPX( void ) {
00839     int     port;
00840 
00841     port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer;
00842     ipx_socket = NET_IPXSocket( port );
00843 }
00844 
00845 
00846 
00847 //===================================================================
00848 
00849 
00850 /*
00851 ====================
00852 NET_GetCvars
00853 ====================
00854 */
00855 static qboolean NET_GetCvars( void ) {
00856     qboolean    modified;
00857 
00858     modified = qfalse;
00859 
00860     if( net_noudp && net_noudp->modified ) {
00861         modified = qtrue;
00862     }
00863     net_noudp = Cvar_Get( "net_noudp", "0", CVAR_LATCH | CVAR_ARCHIVE );
00864 
00865     if( net_noipx && net_noipx->modified ) {
00866         modified = qtrue;
00867     }
00868     net_noipx = Cvar_Get( "net_noipx", "0", CVAR_LATCH | CVAR_ARCHIVE );
00869 
00870 
00871     if( net_socksEnabled && net_socksEnabled->modified ) {
00872         modified = qtrue;
00873     }
00874     net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE );
00875 
00876     if( net_socksServer && net_socksServer->modified ) {
00877         modified = qtrue;
00878     }
00879     net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE );
00880 
00881     if( net_socksPort && net_socksPort->modified ) {
00882         modified = qtrue;
00883     }
00884     net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE );
00885 
00886     if( net_socksUsername && net_socksUsername->modified ) {
00887         modified = qtrue;
00888     }
00889     net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE );
00890 
00891     if( net_socksPassword && net_socksPassword->modified ) {
00892         modified = qtrue;
00893     }
00894     net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE );
00895 
00896 
00897     return modified;
00898 }
00899 
00900 
00901 /*
00902 ====================
00903 NET_Config
00904 ====================
00905 */
00906 void NET_Config( qboolean enableNetworking ) {
00907     qboolean    modified;
00908     qboolean    stop;
00909     qboolean    start;
00910 
00911     // get any latched changes to cvars
00912     modified = NET_GetCvars();
00913 
00914     if( net_noudp->integer && net_noipx->integer ) {
00915         enableNetworking = qfalse;
00916     }
00917 
00918     // if enable state is the same and no cvars were modified, we have nothing to do
00919     if( enableNetworking == networkingEnabled && !modified ) {
00920         return;
00921     }
00922 
00923     if( enableNetworking == networkingEnabled ) {
00924         if( enableNetworking ) {
00925             stop = qtrue;
00926             start = qtrue;
00927         }
00928         else {
00929             stop = qfalse;
00930             start = qfalse;
00931         }
00932     }
00933     else {
00934         if( enableNetworking ) {
00935             stop = qfalse;
00936             start = qtrue;
00937         }
00938         else {
00939             stop = qtrue;
00940             start = qfalse;
00941         }
00942         networkingEnabled = enableNetworking;
00943     }
00944 
00945     if( stop ) {
00946         if ( ip_socket && ip_socket != INVALID_SOCKET ) {
00947             closesocket( ip_socket );
00948             ip_socket = 0;
00949         }
00950 
00951         if ( socks_socket && socks_socket != INVALID_SOCKET ) {
00952             closesocket( socks_socket );
00953             socks_socket = 0;
00954         }
00955 
00956         if ( ipx_socket && ipx_socket != INVALID_SOCKET ) {
00957             closesocket( ipx_socket );
00958             ipx_socket = 0;
00959         }
00960     }
00961 
00962     if( start ) {
00963         if (! net_noudp->integer ) {
00964             NET_OpenIP();
00965         }
00966         if (! net_noipx->integer ) {
00967             NET_OpenIPX();
00968         }
00969     }
00970 }
00971 
00972 
00973 /*
00974 ====================
00975 NET_Init
00976 ====================
00977 */
00978 void NET_Init( void ) {
00979     int     r;
00980 
00981     r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
00982     if( r ) {
00983         Com_Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
00984         return;
00985     }
00986 
00987     winsockInitialized = qtrue;
00988     Com_Printf( "Winsock Initialized\n" );
00989 
00990     // this is really just to get the cvars registered
00991     NET_GetCvars();
00992 
00993     //FIXME testing!
00994     NET_Config( qtrue );
00995 }
00996 
00997 
00998 /*
00999 ====================
01000 NET_Shutdown
01001 ====================
01002 */
01003 void NET_Shutdown( void ) {
01004     if ( !winsockInitialized ) {
01005         return;
01006     }
01007     NET_Config( qfalse );
01008     WSACleanup();
01009     winsockInitialized = qfalse;
01010 }
01011 
01012 
01013 /*
01014 ====================
01015 NET_Sleep
01016 
01017 sleeps msec or until net socket is ready
01018 ====================
01019 */
01020 void NET_Sleep( int msec ) {
01021 }
01022 
01023 
01024 /*
01025 ====================
01026 NET_Restart_f
01027 ====================
01028 */
01029 void NET_Restart( void ) {
01030     NET_Config( networkingEnabled );
01031 }

Generated on Thu Aug 25 12:38:05 2005 for Quake III Arena by  doxygen 1.3.9.1