]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/psnet.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / network / psnet.cpp
1 /*
2  * $Logfile: /Freespace2/code/Network/PsNet.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C file containing application level network-interface.
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:48  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:10  root
14  * Initial import.
15  *
16  * 
17  * 7     7/15/99 9:20a Andsager
18  * FS2_DEMO initial checkin
19  * 
20  * 6     11/19/98 4:19p Dave
21  * Put IPX sockets back in psnet. Consolidated all multiplayer config
22  * files into one.
23  * 
24  * 5     11/19/98 8:04a Dave
25  * Full support for D3-style reliable sockets. Revamped packet lag/loss
26  * system, made it receiver side and at the lowest possible level.
27  * 
28  * 4     11/17/98 11:12a Dave
29  * Removed player identification by address. Now assign explicit id #'s.
30  * 
31  * 3     10/09/98 2:57p Dave
32  * Starting splitting up OS stuff.
33  * 
34  * 2     10/07/98 10:53a Dave
35  * Initial checkin.
36  * 
37  * 1     10/07/98 10:50a Dave
38  * 
39  * 107   9/15/98 4:04p Allender
40  * added back in the -ip_addr command line switch because it needs to be
41  * in the standalone server only executable
42  * 
43  * 106   9/14/98 11:28a Allender
44  * support for server bashing of address when received from client.  Added
45  * a cmdline.cfg file to process command line arguments from a file
46  * 
47  * 105   9/08/98 2:20p Allender
48  * temporary code to force IP address to a specific value.
49  * 
50  * 104   8/21/98 1:15p Dave
51  * Put in log system hooks in useful places.
52  * 
53  * 103   8/12/98 4:50p Allender
54  * fix error with new write socket code
55  * 
56  * 102   8/11/98 11:45a Allender
57  * fix major problem in psnet_send where select() would block until ready
58  * to send, which for slow modems could be a long time.  Doesn't block,
59  * and now correctly returns when socket is not set for writing
60  * 
61  * 101   8/07/98 10:40a Allender
62  * new command line flags for starting netgames.  Only starting currently
63  * works, and PXO isn't implemented yet
64  * 
65  * 100   7/28/98 4:43p Allender
66  * fix bug where error on receiving of reliable data would sometimes
67  * infinate loop
68  * 
69  * 99    7/06/98 5:05p Allender
70  * dont use default port to send UDP data to.  Use port stored in address
71  * 
72  * 98    6/13/98 9:32p Mike
73  * Kill last character in file which caused "Find in Files" to report the
74  * file as "not a text file."
75  * 
76  * 97    6/13/98 6:01p Hoffoss
77  * Externalized all new (or forgot to be added) strings to all the code.
78  * 
79  * 96    6/13/98 3:19p Hoffoss
80  * NOX()ed out a bunch of strings that shouldn't be translated.
81  * 
82  * 95    6/10/98 2:56p Dave
83  * Substantial changes to reduce bandwidth and latency problems.
84  * 
85  * 94    6/05/98 9:55a Lawrance
86  * OEM changes
87  * 
88  * 93    5/24/98 2:17p Allender
89  * make reliable socket read all data before returning
90  * 
91  * 92    5/22/98 10:54a Allender
92  * new dialog information for networking to tell user if connection type
93  * doesn't match the setup specified type
94  * 
95  * 91    5/21/98 3:31p Allender
96  * more RAS stuff -- fix possible problem when unable to read data on
97  * reliable socket
98  * 
99  * 90    5/20/98 4:34p John
100  * fixed some bugs with rasenum connections.  HAd to specify ansi versions
101  * in dll.   Also, my pc returned 0 connections, before that still said
102  * there was a connection.
103  *
104  * $NoKeywords: $
105  */
106
107
108 #include <windows.h>
109 #include <windowsx.h>
110 #include <stdio.h>
111 #include <winsock.h>
112 #include <wsipx.h>
113 #include <process.h>
114 #include <ras.h>
115 #include <raserror.h>
116 #include <limits.h>
117
118 #include "pstypes.h"
119 #include "psnet.h"
120 #include "multi.h"
121 #include "multiutil.h"
122 #include "multilag.h"
123 #include "osregistry.h"
124 #include "timer.h"
125 #include "multi_log.h"
126 #include "cmdline.h"
127
128 #ifndef PSNET2
129
130 // old style packet buffering
131 // #define PSNET_BUFFER_OLD_SCHOOL
132
133 // sockets for IPX and TCP
134 SOCKET IPX_socket;
135 SOCKET IPX_reliable_socket;
136 SOCKET IPX_listen_socket;
137
138 SOCKET TCP_socket;
139 SOCKET TCP_reliable_socket;
140 SOCKET TCP_listen_socket;
141
142 // the sockets that the game will use when selecting network type
143 SOCKET Unreliable_socket = INVALID_SOCKET;
144 SOCKET Reliable_socket = INVALID_SOCKET;
145 SOCKET Listen_socket = INVALID_SOCKET;
146
147 BOOL            Psnet_my_addr_valid;
148 net_addr Psnet_my_addr;
149
150 ubyte Null_address[6];
151
152 int Socket_type;
153 int Can_broadcast;                      // can we do broadcasting on our socket?
154 int Ipx_can_broadcast = 0;
155 int Tcp_can_broadcast = 0;
156
157 int Network_status;
158 int Tcp_failure_code = 0;
159 int Ipx_failure_code = 0;
160 int Ras_connected;
161 int Psnet_connection;
162
163 ushort  Psnet_default_port;
164
165 // specified their internet connnection type
166 #define NETWORK_CONNECTION_NONE                 1
167 #define NETWORK_CONNECTION_DIALUP               2
168 #define NETWORK_CONNECTION_LAN                  3
169
170 // defines and variables to indicate network connection status
171 #define NETWORK_STATUS_NOT_INITIALIZED  1
172 #define NETWORK_STATUS_NO_WINSOCK               2                       // winsock failed to initialize
173 #define NETWORK_STATUS_NO_PROTOCOL              3                       // specified protocol doesn't appear to be loaded
174 #define NETWORK_STATUS_NO_RELIABLE              4
175 #define NETWORK_STATUS_RUNNING                  5                       // everything should be running
176
177 // defintion of structures that actually leave this machine.  psnet_send give us only
178 // the data that we want to send.  We will add a header onto this data (packet sequence
179 // number, possibly a checksum).  We must include a 2 byte flags variable into both structure
180 // since the receiving end of this packet must know whether or not to checksum the packet.
181
182 // use the pack pragma to pack these structures to 2 byte aligment.  Really only needed for
183 // the naked packet.
184
185 #pragma pack(push, 2)
186
187 // packet def for a checksum'ed packet
188 #define MAX_CHECKSUM_PACKET_SIZE                1024
189 typedef struct network_checksum_packet
190 {
191         int             sequence_number;
192         ushort  flags;
193         ushort  checksum;
194         ubyte           data[MAX_CHECKSUM_PACKET_SIZE];
195 } network_checksum_packet;
196
197 // definition for a non-checksum packet
198 typedef struct network_packet
199 {
200         int             sequence_number;
201         ushort  flags;
202         ubyte           data[MAX_PACKET_SIZE];
203 } network_naked_packet;
204
205 // structure definition for our packet buffers
206 typedef struct network_packet_buffer
207 {
208         int             sequence_number;
209         int             len;
210         net_addr        from_addr;
211         ubyte           data[MAX_PACKET_SIZE];
212 } network_packet_buffer;
213
214 #pragma pack(pop)
215
216 #define MAX_PACKET_BUFFERS              96
217
218 #ifdef PSNET_BUFFER_OLD_SCHOOL
219         LOCAL network_packet_buffer packet_buffers[MAX_PACKET_BUFFERS];         // buffer to hold packets sent to us
220         LOCAL short packet_free_list[MAX_PACKET_BUFFERS];                                                       // contains id's of free packet buffers
221         LOCAL Num_packet_buffers;
222         LOCAL int Largest_packet_index = 0;
223
224         int     Next_packet_id;
225         int     Last_packet_id;
226 #endif
227
228 // variables to keep track of bytes read/written during the course of network play
229 #ifndef NDEBUG
230
231 #define PSNET_FRAME_FILTER              32
232 #define MAX_NET_STATS                   32
233
234 typedef struct {
235         int                             in_use;
236         net_addr                        addr;                                           // stats for this address
237         int                             total_read;                                     // total bytes read
238         int                             total_written;                          // total bytes read.
239 } net_stats;
240
241 typedef struct {
242         net_addr                        addr;
243         SOCKET                  socket;
244 } socket_xlate;
245
246 net_stats Psnet_stats[MAX_NET_STATS];
247 socket_xlate Psnet_socket_addr[MAX_NET_STATS];
248
249 int     psnet_bytes_read_frame;                 // running count of bytes read this frame
250 int     psnet_bytes_written_frame;              // running count of bytes written this frame
251
252 int     Psnet_bytes_read;                                       // globally available numbers for printing on the hud
253 int     Psnet_bytes_written;
254
255 int     psnet_read_sizes[PSNET_FRAME_FILTER];
256 int     psnet_write_sizes[PSNET_FRAME_FILTER];
257
258 int     psnet_read_total;
259 int     psnet_write_total;
260 int     psnet_frame_int;
261 int     psnet_frame_count;
262
263 #endif
264
265 #define MAXHOSTNAME                     128
266
267 #define MAX_RECEIVE_BUFSIZE     (1<<15)         // 32 K, eh?
268 #define MAX_SEND_RETRIES                20                              // number of retries when sending would block
269 #define MAX_LINGER_TIME                 0                               // in seconds -- when lingering to close a socket
270
271 #ifndef NDEBUG
272
273 int psnet_same_no_port( net_addr * a1, net_addr * a2 );
274
275 // do stats for a particular address.  num_bytes is the number of bytes either read or
276 // written (depending on the read flag.  read flag is true when reading, 0 when writing
277 void psnet_do_net_stats( net_addr *addr, int num_bytes, int read )
278 {
279         int i;  
280
281         for ( i = 0; i < MAX_NET_STATS; i++ ) {
282                 if ( !Psnet_stats[i].in_use )
283                         continue;
284                 if ( addr && psnet_same_no_port(&Psnet_stats[i].addr, addr) )
285                         break;
286         }
287
288         if ( i == MAX_NET_STATS ) {
289                 // find the first NULL entry
290                 for ( i = 0; i < MAX_NET_STATS; i++ ) {
291                         if ( !Psnet_stats[i].in_use )
292                                 break;
293                 }
294                 if ( i == MAX_NET_STATS ) {
295                         Int3();                         // we should always have a slot
296                         return;
297                 }
298                 Psnet_stats[i].addr = *addr;
299                 Psnet_stats[i].in_use = 1;
300         }
301         if ( read )
302                 Psnet_stats[i].total_read += num_bytes;
303         else
304                 Psnet_stats[i].total_written += num_bytes;
305 }
306
307 // returns the stats for the given network address.  returns 1 when (i.e. net_addr was found),
308 // 0 otherwise.  total read and total written are returned in the parameters
309 int psnet_get_stats( net_addr *addr, int *tr, int *tw )
310 {
311         int i;
312
313         for ( i = 0; i < MAX_NET_STATS; i++ ) {
314                 if ( !Psnet_stats[i].in_use )
315                         continue;
316
317                 if ( addr && psnet_same_no_port(&Psnet_stats[i].addr, addr) )
318                         break;
319         }
320
321         if ( i == MAX_NET_STATS )
322                 return 0;
323
324         *tr = Psnet_stats[i].total_read;
325         *tw = Psnet_stats[i].total_written;
326
327         return 1;
328 }
329
330 void psnet_stats_init()
331 {
332         int i;
333
334         for ( i = 0; i < MAX_NET_STATS; i++ ) {
335                 Psnet_stats[i].in_use = 0;
336                 Psnet_stats[i].total_read = 0;
337                 Psnet_stats[i].total_written = 0;
338                 Psnet_socket_addr[i].socket = INVALID_SOCKET;
339         }
340 }
341
342 #endif
343
344 #define NETWORK_STATUS_NOT_INITIALIZED  1
345 #define NETWORK_STATUS_NO_WINSOCK               2                       // winsock failed to initialize
346 #define NETWORK_STATUS_NO_TCPIP                 3                       // TCP/IP doesn't appear to be loaded
347 #define NETWORK_STATUS_RUNNING                  4                       // everything should be running
348
349 // function called from high level FreeSpace code to determine the status of the networking
350 // code returns one of a handful of macros
351 int psnet_get_network_status()
352 {
353         // first case is when "none" is selected
354         if ( Psnet_connection == NETWORK_CONNECTION_NONE ) {
355                 return NETWORK_ERROR_NO_TYPE;
356         }
357
358         // first, check the connection status of the network
359         if ( Network_status == NETWORK_STATUS_NO_WINSOCK )
360                 return NETWORK_ERROR_NO_WINSOCK;
361
362         if ( Network_status == NETWORK_STATUS_NO_TCPIP )
363                 return NETWORK_ERROR_NO_TCPIP;
364         
365         // network is running -- be sure that the RAS people know to connect if they currently cannot.
366         
367         if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
368                 // if on a dialup connection, be sure that RAS is active.
369                 if ( !Ras_connected ) {
370                         return NETWORK_ERROR_CONNECT_TO_ISP;
371                 }
372         } else if ( Psnet_connection == NETWORK_CONNECTION_LAN ) {
373                 // if on a LAN, and they have a dialup connection active, return error to indicate that they need
374                 // to pick the right connection type
375                 if ( Ras_connected ) {
376                         return NETWORK_ERROR_LAN_AND_RAS;
377                 }
378         }
379         return NETWORK_ERROR_NONE;
380 }
381
382 DWORD (__stdcall *pRasEnumConnections)(LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections) = NULL;
383 DWORD (__stdcall *pRasGetConnectStatus)(HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) = NULL;
384 DWORD (__stdcall *pRasGetProjectionInfo)(HRASCONN hrasconn, RASPROJECTION rasprojection, LPVOID lpprojection, LPDWORD lpcb ) = NULL;
385  
386 // functions to get the status of a RAS connection
387 void psnet_ras_status()
388 {
389         int rval;
390         unsigned long size, num_connections, i;
391         RASCONN rasbuffer[25];
392         HINSTANCE ras_handle;
393
394         Ras_connected = 0;
395
396         // first, call a LoadLibrary to load the RAS api
397         ras_handle = LoadLibrary( NOX("rasapi32.dll") );
398         if ( ras_handle == NULL ) {
399                 return;
400         }
401
402         pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, NOX("RasEnumConnectionsA"));
403         if (!pRasEnumConnections)       {
404                 FreeLibrary( ras_handle );
405                 return;
406         }
407         pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, NOX("RasGetConnectStatusA"));
408         if (!pRasGetConnectStatus)      {
409                 FreeLibrary( ras_handle );
410                 return;
411         }
412         pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, NOX("RasGetProjectionInfoA"));
413         if (!pRasGetProjectionInfo)     {
414                 FreeLibrary( ras_handle );
415                 return;
416         }
417
418         size = sizeof(rasbuffer);
419         rasbuffer[0].dwSize = sizeof(RASCONN);
420
421         rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
422         if ( rval ) {
423                 FreeLibrary( ras_handle );
424                 return;
425         }
426
427         // JAS: My computer gets to this point, but I have no RAS connections,
428         // so just exit
429         if ( num_connections < 1 )      {
430                 nprintf(("Network", "Found no connections\n" )); 
431                 FreeLibrary( ras_handle );
432                 return;
433         }
434
435         nprintf(("Network", "Found %d connections\n", num_connections));
436
437         for (i = 0; i < num_connections; i++ ) {
438                 RASCONNSTATUS status;
439                 RASPPPIP projection;
440                 unsigned long size;
441
442                 nprintf(("Network", "Connection %d:\n", i));
443                 nprintf(("Network", "Entry Name: %s\n", rasbuffer[i].szEntryName));
444                 nprintf(("Network", "Device Type: %s\n", rasbuffer[i].szDeviceType));
445                 nprintf(("Network", "Device Name: %s\n", rasbuffer[i].szDeviceName));
446
447                 // get the connection status
448                 status.dwSize = sizeof(RASCONNSTATUS);
449                 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
450                 if ( rval != 0 ) {
451                         FreeLibrary( ras_handle );
452                         return;
453                 }
454
455                 nprintf(("Network", "\tStatus: %s\n", (status.rasconnstate==RASCS_Connected)?"Connected":"Not Connected"));
456
457                 // get the projection informatiom
458                 size = sizeof(projection);
459                 projection.dwSize = size;
460                 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
461                 if ( rval != 0 ) {
462                         FreeLibrary( ras_handle );
463                         return;
464                 }
465
466                 printf(("Network", "\tIP Address: %s\n", projection.szIpAddress));
467         }
468
469         Ras_connected = 1;
470
471         FreeLibrary( ras_handle );
472 }
473
474 // -------------------------------------------------------------------------------------------------
475 // netmisc_calc_checksum() calculates the checksum of a block of memory.
476 //
477 //
478 ushort psnet_calc_checksum( void * vptr, int len )
479 {
480         ubyte * ptr = (ubyte *)vptr;
481         unsigned int sum1,sum2;
482
483         sum1 = sum2 = 0;
484
485         while(len--)    {
486                 sum1 += *ptr++;
487                 if (sum1 >= 255 ) sum1 -= 255;
488                 sum2 += sum1;
489         }
490         sum2 %= 255;
491         
492         return (unsigned short)((sum1<<8)+ sum2);
493 }
494
495 // -------------------------------------------------------------------------------------------------
496 // psnet_set_socket_mode()
497 //
498 //
499
500 uint psnet_set_socket_mode(SOCKET sock_id, int opt, BOOL toggle)
501 {
502         return (setsockopt(sock_id, SOL_SOCKET, opt, (LPSTR)&toggle, sizeof(toggle)));
503 }
504
505
506 // -------------------------------------------------------------------------------------------------
507 // sock_get_ip() returns the IP address of this computer.
508 //
509 //
510
511 uint sock_get_ip()
512 {
513         char LclHost[MAXHOSTNAME];
514         LPHOSTENT Hostent;
515         SOCKADDR_IN LclAddr;
516         SOCKADDR_IN RmtAddr;    
517         SOCKET hSock;
518         int nRet;
519
520         // Init local address to zero
521         LclAddr.sin_addr.s_addr = INADDR_ANY;
522         
523         // Get the local host name
524         nRet = gethostname(LclHost, MAXHOSTNAME );
525         if (nRet != SOCKET_ERROR )      {
526                 // Resolve host name for local address
527                 Hostent = gethostbyname((LPSTR)LclHost);
528                 if ( Hostent )
529                         LclAddr.sin_addr.s_addr = *((u_long FAR *)(Hostent->h_addr));
530         }
531                         
532         return LclAddr.sin_addr.s_addr;
533
534         RmtAddr = RmtAddr;
535         hSock = hSock;
536 }
537
538 // psnet_get_ip() attempts to get the local IP address of this machine
539 // returns 0 on failure, and 1 on success
540 int psnet_get_ip( SOCKET s )
541 {
542         int rval, len;
543         SOCKADDR_IN local_addr;
544
545         if ( Psnet_my_addr_valid ){
546                 return 1;
547         }
548
549         memset(&local_addr, 0, sizeof(SOCKADDR_IN));
550         len = sizeof(SOCKADDR_IN);
551         rval = getsockname(s, (SOCKADDR *)&local_addr, &len );
552         if ( rval == SOCKET_ERROR )
553                 return 0;
554
555         // now we should have an IP address of this machine.
556         memcpy(Psnet_my_addr.addr, &(local_addr.sin_addr), 4);
557         Psnet_my_addr.port = ntohs(local_addr.sin_port);        
558
559         Psnet_my_addr_valid = 1;
560         return 1;
561 }
562
563 // -------------------------------------------------------------------------------------------------
564 // psnet_close()
565 //
566 //
567
568 void psnet_close()
569 {
570 #ifndef PSNET_RELIABLE_OLD_SCHOOL
571         psnet_reliable_close(); 
572 #endif
573
574         if ( Network_status != NETWORK_STATUS_RUNNING )
575                 return;
576
577         WSACancelBlockingCall();
578
579         if ( TCP_listen_socket != INVALID_SOCKET ) {
580                 shutdown( TCP_listen_socket, 1 );
581                 closesocket( TCP_listen_socket );
582         }
583
584         if ( TCP_reliable_socket != INVALID_SOCKET ) {
585                 shutdown( TCP_reliable_socket, 1 );
586                 closesocket( TCP_reliable_socket );
587         }
588
589         if ( TCP_socket != INVALID_SOCKET ) {
590                 shutdown( TCP_socket, 1 );
591                 closesocket( TCP_socket );
592         }
593
594         if (WSACleanup())       {
595                 //Warning( LOCATION, "Error closing wsock!\n" );
596         }
597         
598         Network_status = NETWORK_STATUS_NOT_INITIALIZED;
599 }
600
601 // function to initialize a reliable socket.  All it does is call the socket() command.
602 // returns 1 on success, 0 on failure.
603 int psnet_init_stream( SOCKET *s, int type )
604 {
605         SOCKET sock;
606
607         switch( type ) {
608         case NET_IPX:
609                 sock = socket(AF_IPX,SOCK_STREAM,NSPROTO_SPX);
610                 if ( sock == INVALID_SOCKET )
611                         return 0;
612                 break;
613
614         case NET_TCP:
615                 sock = socket(AF_INET,SOCK_STREAM,0);
616                 if ( sock == INVALID_SOCKET )
617                         return 0;
618                 break;
619
620         default:
621                 Int3();
622                 return 0;
623         }
624
625         *s = sock;
626
627         return 1;
628 }
629
630 // called by psnet_init to initialize the listen socket used by a host/server
631 int psnet_init_reliable(ushort port, int should_listen, int type)
632 {
633         SOCKET sock = 0;                // JAS: Get rid of optimized warning
634         SOCKADDR_IN sockaddr;           // UDP/TCP socket structure
635         SOCKADDR_IPX ipx_addr;          // IPX socket structure
636
637         // set up the reliable TCP transport socket
638         if ( !psnet_init_stream(&sock, type) ) {
639                 nprintf(("Network", "Unable to initialize reliable socket on port %d (%d)!\n"  , port, WSAGetLastError() )); 
640                 return INVALID_SOCKET;
641         }
642
643         // bind the socket to the port
644         switch( type ) {
645         case NET_IPX:
646                 memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
647                 ipx_addr.sa_socket = htons( port );
648                 ipx_addr.sa_family = AF_IPX;
649                 if (bind(sock, (SOCKADDR *)&ipx_addr, sizeof(SOCKADDR_IPX)) == SOCKET_ERROR) {
650                         nprintf(("Network", "Unable to bind reliable socket on port %d (%d)!\n"  , port, WSAGetLastError() )); 
651                         return INVALID_SOCKET;
652                 }
653                 break;
654
655         case NET_TCP:
656                 memset( &sockaddr, 0, sizeof(SOCKADDR_IN) );
657                 sockaddr.sin_family = AF_INET; 
658                 sockaddr.sin_addr.s_addr = INADDR_ANY;  //fill in with our IP
659                 sockaddr.sin_port = htons( port );
660                 if ( bind(sock, (SOCKADDR*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {     
661                         nprintf(("Network", "Unable to bind reliable socket on port %d (%d)!\n"  , port, WSAGetLastError() )); 
662                         return INVALID_SOCKET;
663                 }
664                 break;
665
666         default:
667                 Int3();
668                 return INVALID_SOCKET;
669         }
670
671
672         // set up the listen on the Reliable_socket port
673         if ( should_listen && listen(sock, 5) ) {
674                 nprintf(("Network", "Unable to listen on Listen Socket (%d)!\n"  , WSAGetLastError() )); 
675                 return INVALID_SOCKET;
676         }
677
678         // make any reliable sockets which we create that aren't listening non-blocking sockets
679         if ( !should_listen ) {
680                 int error;
681                 unsigned long arg;
682
683                 arg = TRUE;
684                 error = ioctlsocket( sock, FIONBIO, &arg );
685                 if ( error == SOCKET_ERROR ) {
686                         nprintf(("Network", "Unable to make reliable socket non-blocking -- %d", WSAGetLastError() ));
687                         return INVALID_SOCKET;
688                 }
689
690                 // set the reuse option
691                 if ( psnet_set_socket_mode(sock, SO_REUSEADDR, 1) == SOCKET_ERROR ) {
692                         error = WSAGetLastError();
693                         nprintf(("Network", "Error setting socket to reuse address -- %d\n", error));
694                 }
695
696         }
697
698         return sock;
699 }
700
701 void psnet_socket_options( SOCKET sock )
702 {
703         int broadcast;
704         int ret, cursize, cursizesize, bufsize, trysize;
705
706         // Set the mode of the socket to allow broadcasting.  We need to be able to broadcast
707         // when a game is searched for in IPX mode.
708         broadcast = 1;
709         if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (LPSTR)&broadcast, sizeof(broadcast) )){
710                 Can_broadcast = 0;
711         } else {
712                 Can_broadcast = 1;
713         }
714
715         // try and increase the size of my receive buffer
716         bufsize = MAX_RECEIVE_BUFSIZE;
717         
718         // set the current size of the receive buffer
719         cursizesize = sizeof(int);
720         getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&cursize, &cursizesize);
721         for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
722                 ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&trysize, sizeof(trysize));
723                 if ( ret == SOCKET_ERROR ) {
724                         int wserr;
725
726                         wserr = WSAGetLastError();
727                         if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
728                                 break;
729                 } else
730                         break;
731         }
732         getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&cursize, &cursizesize);
733         nprintf(("Network", "Receive buffer set to %d\n", cursize));
734
735         // set the current size of the send buffer
736         cursizesize = sizeof(int);
737         getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&cursize, &cursizesize);
738         for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
739                 ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&trysize, sizeof(trysize));
740                 if ( ret == SOCKET_ERROR ) {
741                         int wserr;
742
743                         wserr = WSAGetLastError();
744                         if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
745                                 break;
746                 } else
747                         break;
748         }
749         getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&cursize, &cursizesize);
750         nprintf(("Network", "Send buffer set to %d\n", cursize));
751 }
752
753
754 // psnet_init called at game startup time and initializes all sockets that the game might use (i.e. for both
755 // IPX and TCP).
756 void psnet_init( int protocol, int port_num )
757 {       
758         char *internet_connection;
759         WSADATA wsa_data;       
760
761         // UDP/TCP socket structure
762         SOCKADDR_IN sockaddr; 
763
764         // IPX socket structure
765         //SOCKADDR_IPX ipx_addr;
766
767 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
768         return;
769 #endif
770
771         // GAME PORT INITIALIZATION STUFF
772         if ( Network_status == NETWORK_STATUS_RUNNING )
773                 return;
774
775         internet_connection = os_config_read_string(NULL, "NetworkConnection", "none");
776         if ( !stricmp(internet_connection, NOX("dialup")) ) {
777                 Psnet_connection = NETWORK_CONNECTION_DIALUP;
778         } else if ( !stricmp(internet_connection, NOX("lan")) ) {
779                 Psnet_connection = NETWORK_CONNECTION_LAN;
780         } else {
781                 Psnet_connection = NETWORK_CONNECTION_NONE;
782         }
783
784         Network_status = NETWORK_STATUS_NO_WINSOCK;
785         if (WSAStartup(0x101, &wsa_data )){
786                 return;
787         }
788
789         // get the port for running this game on.  Be careful that it cannot be out of bounds
790         Psnet_default_port = DEFAULT_GAME_PORT;
791         if ( (port_num > 1023) && (port_num < USHRT_MAX) ) {
792                 Psnet_default_port = (ushort)port_num;
793         }
794
795 #ifndef PSNET_RELIABLE_OLD_SCHOOL
796         if(!psnet_reliable_init()){
797                 nprintf(("Network","PSNET RELIABLE : init failed - no networking available!\n"));
798                 return;
799         }
800 #endif
801
802         // initialize TCP now
803         TCP_socket = INVALID_SOCKET;
804         TCP_reliable_socket = INVALID_SOCKET;
805         TCP_listen_socket = INVALID_SOCKET;
806
807         Network_status = NETWORK_STATUS_NO_TCPIP;
808         TCP_socket = socket( AF_INET, SOCK_DGRAM, 0 );
809         if ( TCP_socket == INVALID_SOCKET ) {
810                 Tcp_failure_code = WSAGetLastError();
811                 nprintf(("Network", "Error on TCP startup %d\n", Tcp_failure_code));
812                 return;
813         }
814
815         // bind the socket
816         memset(&sockaddr,0,sizeof(SOCKADDR_IN));
817         sockaddr.sin_family = AF_INET; 
818
819         sockaddr.sin_addr.s_addr = INADDR_ANY;  //fill in with our IP
820
821         sockaddr.sin_port = htons( Psnet_default_port );
822         if ( bind(TCP_socket, (SOCKADDR*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {       
823                 Tcp_failure_code = WSAGetLastError();
824                 nprintf(( "Network", "Couldn't bind TCP socket (%d)! Invalidating TCP\n", Tcp_failure_code )); 
825                 return;
826         }
827
828 #ifdef PSNET_RELIABLE_OLD_SCHOOL
829         // set up reliable socket (using SPX).
830         TCP_reliable_socket = psnet_init_reliable( 0, 0, NET_TCP );
831         if ( TCP_reliable_socket == INVALID_SOCKET ) {
832                 Tcp_failure_code = WSAGetLastError();
833                 nprintf(( "Network", "Couldn't initialize TCP reliable socket (OLD SCHOOL) (%d)! Invalidating TCP\n", Tcp_failure_code )); 
834                 return;
835         }
836
837         TCP_listen_socket = psnet_init_reliable( (u_short)(Psnet_default_port-1), 1, NET_TCP );
838         if ( TCP_listen_socket == INVALID_SOCKET ) {
839                 Tcp_failure_code = WSAGetLastError();
840                 nprintf(( "Network", "Couldn't initialize TCP listen socket (OLD SCHOOL) (%d)! Invalidating TCP\n", Tcp_failure_code )); 
841                 return;
842         }
843 #endif
844
845         psnet_socket_options( TCP_socket );             
846         Tcp_can_broadcast = Can_broadcast;
847         Can_broadcast = 0;
848
849 // fire up a second UDP socket for "reliable" transport
850 #ifndef PSNET_RELIABLE_OLD_SCHOOL
851         TCP_reliable_socket = socket( AF_INET, SOCK_DGRAM, 0 );
852         if ( TCP_reliable_socket != INVALID_SOCKET )    {
853                 // bind the socket
854                 memset(&sockaddr,0,sizeof(SOCKADDR_IN));
855                 sockaddr.sin_family = AF_INET; 
856
857                 sockaddr.sin_addr.s_addr = INADDR_ANY;  //fill in with our IP
858                 //unsigned long my_ip = sock_get_ip();
859                 //memcpy(&sockaddr.sin_addr.s_addr,&my_ip,sizeof(uint));
860
861                 sockaddr.sin_port = htons( (ushort)(port+1) );
862                 if ( bind(TCP_reliable_socket, (SOCKADDR*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {      
863                         nprintf(( "Network", "Couldn't bind TCP socket (%d)! Invalidating TCP\n", WSAGetLastError() )); 
864                         goto tcp_done;
865                 }
866
867                 psnet_socket_options( TCP_reliable_socket );            
868                 Can_broadcast = 0;
869         }
870 #endif
871
872         psnet_ras_status();
873
874         Network_status = NETWORK_STATUS_RUNNING;
875
876         nprintf(("Network","TCP Initialized\n"));
877
878         // with TCP initialized, see if the RAS services are installed
879
880
881 #ifndef NDEBUG
882         psnet_frame_int = -1;           // for counting bytes per frame
883 #endif
884
885 #ifdef PSNET_BUFFER_OLD_SCHOOL
886         Next_packet_id = 0;
887         Last_packet_id = -1;
888
889         // initialize the packet buffer stuff.  We use an array (the packet_free_list) to determine
890         // which of the packet buffers we can use next.
891         int i;
892         for (i=0; i<MAX_PACKET_BUFFERS; i++ )   {
893                 packet_buffers[i].sequence_number = -1;
894                 packet_free_list[i] = (short)i;
895         }
896         Num_packet_buffers = 0;
897         Largest_packet_index = 0;
898 #else
899         // initialize the new buffering system
900         psnet_buffer_init();
901 #endif
902 }
903
904 #define MAX_TMPBUF_SIZE 1024
905
906 #ifdef PSNET_RELIABLE_OLD_SCHOOL
907 // function to shutdown and close the given socket.  It takes a couple of things into consideration
908 // when closing, such as possibly reiniting reliable sockets if they are closed here.
909 void psnet_rel_close_socket( PSNET_SOCKET *p_sockp )
910 {
911         int reinit_type;
912         int error, rval;
913         SOCKET *sockp;
914
915         sockp = (SOCKET *)p_sockp;
916
917         if ( *sockp == INVALID_SOCKET )
918                 return;
919
920 #ifndef NDEBUG
921         if ( *sockp == IPX_reliable_socket )
922                 nprintf(("Network", "Closing my reliable IPX socket\n"));
923         else if ( *sockp == TCP_reliable_socket )
924                 nprintf(("network", "Closing my relibale TCP socket\n"));
925         else 
926                 nprintf(("Network", "Closing client's reliable socket\n"));
927 #endif
928
929         // make the socket blocking
930         //unsigned long val = 0;
931         //rval = ioctlsocket(*sockp,FIONBIO,&val);
932         //if ( rval == SOCKET_ERROR ) {
933         //      error = WSAGetLastError();
934         //      nprintf(("Network", "Error %d when trying to make reliable socket blocking.\n", error));
935         //}
936
937         // set the socket to linger with a timeout of 0
938         linger l_val;
939         l_val.l_onoff = 1;
940         l_val.l_linger = 0;
941         rval = setsockopt(*sockp,SOL_SOCKET,SO_LINGER,(char*)&l_val,sizeof(linger));
942         if ( rval == SOCKET_ERROR ) {
943                 error = WSAGetLastError();
944                 nprintf(("Network", "Error %d when trying to set linger value.\n", error));
945         }
946
947         // see if this socket is my Reliable_socket.  If so, I will have to reinitialize it!
948         reinit_type = -1;
949         if ( *sockp == IPX_reliable_socket )
950                 reinit_type = NET_IPX;
951         else if ( *sockp == TCP_reliable_socket )
952                 reinit_type = NET_TCP;
953
954         /*
955         rval = shutdown( *sockp, 2);            // shut the whole damn thing down.
956         if ( rval == SOCKET_ERROR ) {
957                 error = WSAGetLastError();
958                 nprintf(("Network", "Error %d on socket shutdown\n", error));
959         }
960         */
961
962         shutdown( *sockp, 1 );
963         rval = 1;
964         while ( rval && (rval != SOCKET_ERROR) ) {
965                 char tmp_buf[MAX_TMPBUF_SIZE];
966
967                 rval = recv( *sockp, tmp_buf, MAX_TMPBUF_SIZE, 0 );
968                 if ( rval == SOCKET_ERROR ) {
969                         int error;
970
971                         error = WSAGetLastError();
972                         if ( error == WSAEWOULDBLOCK )
973                                 break;
974                 }
975         }
976
977         rval = closesocket( *sockp );
978         if ( rval == SOCKET_ERROR ) {
979                 error = WSAGetLastError();
980                 nprintf(("Network", "Error %d on closing socket\n", error ));
981         }
982
983         *sockp = INVALID_SOCKET;
984
985         // see if we need to reinitialize
986         if ( reinit_type != -1 ) {
987                 ushort port;
988
989                 port = Psnet_default_port;
990                 if ( reinit_type == NET_IPX ){
991                         IPX_reliable_socket = psnet_init_reliable( 0, 0, NET_IPX);
992                         Reliable_socket = IPX_reliable_socket;
993                 }
994                 else if ( reinit_type == NET_TCP){
995                         TCP_reliable_socket = psnet_init_reliable( 0, 0, NET_TCP);
996                         Reliable_socket = TCP_reliable_socket;
997                 }
998         }
999 }
1000 #else
1001 // function to shutdown and close the given socket.  It takes a couple of things into consideration
1002 // when closing, such as possibly reiniting reliable sockets if they are closed here.
1003 void psnet_close_socket( PSNET_SOCKET *p_sockp )
1004 {
1005         net_addr remove;
1006
1007         // copy the address to be removed
1008         memcpy(&remove,&((net_addr*)(*p_sockp)),sizeof(net_addr));
1009
1010         // remove it from the reliable address list
1011         psnet_reliable_notify_drop_addr(&remove);
1012
1013         // invalidate the passed in "socket"
1014         *p_sockp = NULL;
1015 }
1016 #endif
1017
1018 // function to check the status of the reliable socket and try to re-initialize it if necessary.
1019 // win95 seems to have trouble doing a reinit of the socket immediately after close, so this
1020 // function exists to check the status, and reinitialize if we need to
1021 int psnet_rel_check()
1022 {
1023         // if our Reliable_socket is valid, simply return true to indicate all is well.
1024         if ( Reliable_socket != INVALID_SOCKET )
1025                 return 1;
1026
1027         // based on our protocol type, try to reinitialize the socket we need.
1028         switch( Socket_type ) {
1029                 
1030         case NET_IPX:
1031                 IPX_reliable_socket = psnet_init_reliable( 0, 0, NET_IPX);
1032                 Reliable_socket = IPX_reliable_socket;
1033                 break;
1034
1035         case NET_TCP:
1036                 TCP_reliable_socket = psnet_init_reliable( 0, 0, NET_TCP);
1037                 Reliable_socket = TCP_reliable_socket;
1038                 break;
1039
1040         }
1041
1042         // return our status.
1043         if ( Reliable_socket == INVALID_SOCKET )
1044                 return 0;
1045
1046         return 1;
1047 }
1048
1049 // this function is called from a high level at FreeSpace to set the protocol that the user wishes to use
1050 int psnet_use_protocol( int protocol )
1051 {
1052         int len;
1053         SOCKADDR_IPX    ipx_addr;
1054
1055         // zero out my address
1056         Psnet_my_addr_valid = 0;
1057         memset( &Psnet_my_addr, 0, sizeof(Psnet_my_addr) );
1058
1059         // wait until we choose a protocol to determine if we can broadcast
1060         Can_broadcast = 0;
1061
1062         switch ( protocol ) {
1063         case NET_IPX:
1064                 return 0;
1065
1066                 // assign the IPX_* sockets to the socket values used elsewhere
1067                 Unreliable_socket = IPX_socket;
1068                 Reliable_socket = IPX_reliable_socket;
1069                 Listen_socket = IPX_listen_socket;
1070
1071                 Can_broadcast = Ipx_can_broadcast;
1072                 if(Can_broadcast){
1073                         nprintf(("Network","Psnet : IPX broadcast\n"));
1074                 }
1075
1076                 // get the socket name for the IPX_socket, and put it into My_addr
1077                 len = sizeof(SOCKADDR_IPX);
1078                 if ( getsockname(IPX_socket, (SOCKADDR *)&ipx_addr, &len) == SOCKET_ERROR ) {
1079                         nprintf(("Network", "Unable to get sock name for IPX unreliable socket (%d)\n", WSAGetLastError() ));
1080                         return 0;
1081                 }
1082
1083                 memcpy(Psnet_my_addr.net_id, ipx_addr.sa_netnum, 4);
1084                 memcpy(Psnet_my_addr.addr, ipx_addr.sa_nodenum, 6);
1085                 Psnet_my_addr.port = DEFAULT_GAME_PORT;         
1086
1087                 nprintf(("Network","Psnet using - NET_IPX\n"));
1088                 break;
1089
1090         case NET_TCP:
1091                 if ( Network_status != NETWORK_STATUS_RUNNING )
1092                         return 0;
1093
1094                 // assign the TCP_* sockets to the socket values used elsewhere
1095                 Unreliable_socket = TCP_socket;
1096                 Reliable_socket = TCP_reliable_socket;
1097                 Listen_socket = TCP_listen_socket;
1098
1099                 Can_broadcast = Tcp_can_broadcast;
1100                 if(Can_broadcast){
1101                         nprintf(("Network","Psnet : TCP broadcast\n"));
1102                 }
1103
1104                 nprintf(("Network","Psnet using - NET_TCP\n"));
1105                 break;
1106
1107         default:
1108                 Int3();
1109                 return 0;
1110         }
1111
1112         Psnet_my_addr.type = protocol;
1113         Socket_type = protocol;
1114
1115         return 1;
1116 }
1117
1118 #define MAX_CONNECT_TRIES       10
1119
1120 // attacmpt to connect() to the server's tcp socket.  socket parameter is simply assigned to the
1121 // Reliable_socket socket created in psnet_init
1122 void psnet_rel_connect_to_server( PSNET_SOCKET *psocket, net_addr *server_addr)
1123 {
1124         SOCKADDR_IN sockaddr;                           // UDP/TCP socket structure
1125         SOCKADDR_IPX ipx_addr;                          // IPX socket structure
1126         SOCKADDR *addr;                                         // pointer to SOCKADDR to make coding easier
1127         SOCKET *socket;
1128         ubyte iaddr[6];
1129         u_short port;
1130         int name_length, val;
1131
1132         memset(iaddr, 0x00, 6);
1133         memcpy(iaddr, server_addr->addr, 6);
1134         port = (u_short)(server_addr->port - 1);
1135
1136         socket = (SOCKET *)psocket;
1137
1138         switch( Socket_type ) {
1139         case NET_IPX:
1140                 ipx_addr.sa_family = AF_IPX;
1141                 memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1142                 memcpy(ipx_addr.sa_netnum, server_addr->net_id, 4);
1143                 ipx_addr.sa_socket = htons(port);
1144                 addr = (SOCKADDR *)&ipx_addr;
1145                 name_length = sizeof(ipx_addr);
1146                 break;
1147
1148         case NET_TCP:
1149                 sockaddr.sin_family = AF_INET; 
1150                 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1151                 sockaddr.sin_port = htons(port); 
1152                 addr = (SOCKADDR *)&sockaddr;
1153                 name_length = sizeof(sockaddr);
1154                 break;
1155
1156         default:
1157                 Int3();
1158                 return;
1159         }
1160
1161         // NETLOG
1162         ml_string(NOX("Attempting to perform reliable TCP connect to server"));
1163
1164         // connect this guys Reliable_socket to the socket parameter passed in
1165         *socket = INVALID_SOCKET;
1166         val = connect(Reliable_socket, addr, name_length);
1167
1168          // I suppose that we could have a valid socket right away
1169         if ( val != SOCKET_ERROR ) {
1170                 *socket = Reliable_socket;
1171         } else {
1172                 int error;
1173
1174                 error = WSAGetLastError();
1175                 if ( error == WSAEWOULDBLOCK ) {                        // use select to find out when socket is writeable
1176                         int is_set, num_tries;
1177                         fd_set wfds;
1178                         struct timeval timeout;
1179
1180                         // call select -- and return if an error leaving our connection to the client invalid
1181                         num_tries = 0;
1182                         do {
1183                                 FD_ZERO(&wfds);
1184                                 FD_SET( Reliable_socket, &wfds );
1185                                 timeout.tv_sec = 0;
1186                                 timeout.tv_usec = 500000;                       //500000 micro seconds is 1/2 second
1187
1188                                 is_set = select( -1, NULL, &wfds, NULL, &timeout);
1189                                 // check for error on select first
1190                                 if ( is_set == SOCKET_ERROR ) {
1191                                         nprintf(("Network", "Error on select for connect %d\n", WSAGetLastError() ));
1192                                         return;
1193                                 } else if (is_set) {                    // if set, then we have connection, move forward
1194                                         break;
1195                                 } else {
1196                                         Sleep(10);                                      // sleep for 10 ms and try again
1197                                         num_tries++;
1198                                 }
1199                         } while ( num_tries < MAX_CONNECT_TRIES );
1200
1201                         if ( num_tries == MAX_CONNECT_TRIES )
1202                                 return;
1203
1204                         *socket = Reliable_socket;
1205
1206                 } else {
1207                         nprintf(("Network", "Connecting with server failed %d\n", error ));
1208                         *socket = INVALID_SOCKET;
1209                 }
1210         }
1211
1212         // if we have a connection, get my address from getsockname
1213         if ( *socket == Reliable_socket ) {
1214                 if ( !psnet_get_ip(Reliable_socket) ) {
1215                         *socket = INVALID_SOCKET;
1216                         return;
1217                 }
1218         }
1219 }
1220
1221 #ifndef NDEBUG
1222 void psnet_calc_bytes_per_frame()
1223 {
1224 }
1225 #endif
1226
1227 // -------------------------------------------------------------------------------------------------
1228 // psnet_same()
1229 //
1230 //
1231
1232 int psnet_same_no_port( net_addr * a1, net_addr * a2 )
1233 {
1234         if ( !memcmp(a1->addr, a2->addr, 6) )
1235                 return 1;
1236         return 0;
1237 }
1238
1239 int psnet_same( net_addr * a1, net_addr * a2 )
1240 {
1241         return psnet_same_no_port( a1, a2 );
1242 /*
1243         if ( !memcmp(a1->addr, a2->addr, 6)  && a1->port == a2->port)
1244                 return 1;
1245         return 0;
1246 */
1247 }
1248
1249 // -------------------------------------------------------------------------------------------------
1250 // psnet_describe()
1251 //
1252 //
1253
1254 char* psnet_addr_to_string( char * text, net_addr * address )
1255 {
1256
1257         if ( Network_status != NETWORK_STATUS_RUNNING )         {
1258                 strcpy( text, XSTR("[no networking]",910) );
1259                 return text;
1260         }
1261
1262         in_addr temp_addr;
1263
1264         switch ( address->type ) {
1265                 case NET_IPX:
1266                         sprintf(text, "%x %x %x %x: %x %x %x %x %x %x", address->net_id[0],
1267                                                                                                                                                         address->net_id[1],
1268                                                                                                                                                         address->net_id[2],
1269                                                                                                                                                         address->net_id[3],
1270                                                                                                                                                         address->addr[0],
1271                                                                                                                                                         address->addr[1],
1272                                                                                                                                                         address->addr[2],
1273                                                                                                                                                         address->addr[3],
1274                                                                                                                                                         address->addr[4],
1275                                                                                                                                                         address->addr[5]);
1276                         break;
1277
1278                 case NET_TCP:
1279                         memcpy(&temp_addr.s_addr, address->addr, 4);
1280                         strcpy( text, inet_ntoa(temp_addr) );
1281                         break;
1282
1283                 default:
1284                         // Assert(0);
1285                         break;
1286
1287         } // end switch
1288         
1289         return text;
1290 }
1291
1292
1293 // -------------------------------------------------------------------------------------------------
1294 // psnet_undescribe()
1295 //
1296 //
1297
1298 void psnet_string_to_addr( net_addr * address, char * text )
1299 {
1300         struct hostent *he;
1301         char str[255], *c, *port;
1302         in_addr addr;
1303
1304         if ( Network_status != NETWORK_STATUS_RUNNING ) {
1305                 strcpy( text, XSTR("[no networking]",910) );
1306                 return;
1307         }
1308
1309         // copy the text string to local storage to look for ports
1310         Assert( strlen(text) < 255 );
1311         strcpy(str, text);
1312         c = strrchr(str, ':');
1313         port = NULL;
1314         if ( c ) {
1315                 *c = '\0';
1316                 port = c+1;
1317         }
1318
1319         switch ( address->type ) {
1320                 case NET_IPX:         
1321                         Int3();         // no support for this yet
1322                         break;
1323
1324                 case NET_TCP:
1325                         addr.s_addr = inet_addr(str);
1326                         // if we get INADDR_NONE returns, then we need to try and resolve the host
1327                         // name
1328                         if ( addr.s_addr == INADDR_NONE ) {
1329                                 he = gethostbyname( str );
1330                                 // returns a non-null pointer if successful, so get the address
1331                                 if ( he ) {
1332                                         addr.s_addr = ((in_addr *)(he->h_addr))->s_addr;                        // this is the address in network byte order
1333                                 } else {
1334                                         addr.s_addr = INADDR_NONE;
1335                                 }
1336                         }
1337
1338                         memset(address->addr, 0x00, 6);
1339                         memcpy(address->addr, &addr.s_addr, 4);
1340                         if ( port )
1341                                 address->port = (ushort)(atoi(port));
1342                         break;
1343
1344                 default:
1345                         Assert(0);
1346                         break;
1347
1348         } // end switch
1349
1350 }
1351
1352 // psnet_get_socket_data() will get data out of the socket and stuff it into the packet_buffers
1353 // The original psnet_get() now calls this function, then determines which of the packet buffers
1354 // to package up and use
1355 void psnet_get_socket_data(SOCKET socket, int flags = PSNET_FLAG_RAW)
1356 {
1357         SOCKADDR_IN ip_addr;                            // UDP/TCP socket structure
1358         SOCKADDR_IPX ipx_addr;                  // IPX socket structure
1359         fd_set  rfds;
1360         timeval timeout;
1361         int             read_len, from_len;
1362         net_addr        from_addr;      
1363         network_checksum_packet packet_read;    
1364         network_checksum_packet packet_data;
1365
1366         // clear the addresses to remove compiler warnings
1367         memset(&ip_addr, 0, sizeof(SOCKADDR_IN));
1368         memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
1369
1370         if ( Network_status != NETWORK_STATUS_RUNNING ) {
1371                 nprintf(("Network","Network ==> socket not inited in psnet_get\n"));
1372                 return;
1373         }
1374
1375         while ( 1 ) {           
1376 #ifdef PSNET_BUFFER_OLD_SCHOOL
1377                 int packet_id, id;
1378                 // if there are no more packet buffers that we can use, then we must bail here before reading
1379                 // any data!!!!
1380                 if ( Num_packet_buffers >= MAX_PACKET_BUFFERS ) {
1381                         nprintf(("Network", "Packet buffer overrun in psnet_get()\n"));
1382                         break;
1383                 }
1384 #endif
1385
1386                 // check if there is any data on the socket to be read.  The amount of data that can be 
1387                 // atomically read is stored in len.
1388
1389                 FD_ZERO(&rfds);
1390                 FD_SET( socket, &rfds );
1391                 timeout.tv_sec = 0;
1392                 timeout.tv_usec = 0;
1393
1394                 if ( select( -1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1395                         nprintf(("Network", "Error %d doing a socket select on read\n", WSAGetLastError()));
1396                         break;
1397                 }
1398
1399                 // if the read file descriptor is not set, then bail!
1400                 if ( !FD_ISSET(socket, &rfds ) )
1401                         return;
1402
1403                 // get data off the socket and process
1404                 read_len = SOCKET_ERROR;
1405                 switch ( Socket_type ) {
1406                 case NET_IPX:
1407                         from_len = sizeof(SOCKADDR_IPX);
1408                         if(flags & PSNET_FLAG_RAW){
1409                                 read_len = recvfrom( socket, (char*)packet_read.data, MAX_PACKET_SIZE, 0,  (SOCKADDR*)&ipx_addr, &from_len );
1410                         } else {
1411                                 read_len = recvfrom( socket, (char *)&packet_read, sizeof(packet_data), 0,  (SOCKADDR*)&ipx_addr, &from_len );
1412                         }
1413                         break;
1414
1415                 case NET_TCP:
1416                         from_len = sizeof(SOCKADDR_IN);
1417                         if(flags & PSNET_FLAG_RAW){
1418                                 read_len = recvfrom( socket, (char*)packet_read.data, MAX_PACKET_SIZE, 0,  (SOCKADDR*)&ip_addr, &from_len );
1419                         } else {
1420                                 read_len = recvfrom( socket, (char *)&packet_read, sizeof(packet_data), 0,  (SOCKADDR*)&ip_addr, &from_len );
1421                         }
1422                         break;
1423                 
1424                 default:
1425                         Int3();
1426                         break;
1427                 }
1428
1429                 // set the from_addr for storage into the packet buffer structure
1430                 from_addr.type = Socket_type;
1431
1432                 switch ( Socket_type ) {
1433                 case NET_IPX:
1434                         if(socket == Reliable_socket){
1435                                 from_addr.port = Psnet_default_port;
1436                         } else {
1437                                 from_addr.port = ntohs( ipx_addr.sa_socket );
1438                         }
1439                         memcpy(from_addr.addr, ipx_addr.sa_nodenum, 6 );
1440                         memcpy(from_addr.net_id, ipx_addr.sa_netnum, 4 );
1441                         break;
1442
1443                 case NET_TCP:
1444                         if(socket == Reliable_socket){
1445                                 from_addr.port = Psnet_default_port;
1446                         } else {
1447                                 from_addr.port = ntohs( ip_addr.sin_port );
1448                         }
1449                         memset(from_addr.addr, 0x00, 6);
1450                         memcpy(from_addr.addr, &ip_addr.sin_addr.S_un.S_addr, 4);
1451                         break;
1452
1453                 default:
1454                         Assert(0);
1455                         break;
1456                 }
1457
1458                 if ( read_len == SOCKET_ERROR ) {
1459                         int x = WSAGetLastError();
1460                         nprintf(("Network", "Read error on socket.  Winsock error %d \n", x));
1461                         break;
1462                 }               
1463
1464 #ifndef PSNET_RELIABLE_OLD_SCHOOL
1465                 int shave_size;
1466                 // now we check to see if this is a reliable packet, and act accordindly
1467                 if(socket == Reliable_socket){
1468                         // this function processes the incoming packet, and determines if the system should continue to process the data
1469                         shave_size = psnet_reliable_should_process(&from_addr,packet_read.data,read_len);
1470                         if(!shave_size){                                
1471                                 continue;
1472                         } else {
1473                                 // copy in from data+2, so we skip the reliable data header
1474                                 memcpy(packet_data.data,packet_read.data + shave_size,read_len);
1475
1476                                 // subtract out the size of the reliable header
1477                                 read_len -= shave_size;
1478                         }
1479                 } else {
1480                         memcpy(packet_data.data,packet_read.data,read_len);
1481                 }
1482 #else
1483                 memcpy(packet_data.data,packet_read.data,read_len);
1484 #endif
1485
1486 #ifdef PSNET_BUFFER_OLD_SCHOOL
1487                 ubyte           *data;
1488                 int len;
1489
1490                 // if we had no error reading from the socket, then determine if we need to calculate a
1491                 // checksum on the packet               
1492                 if ( !(flags & PSNET_FLAG_RAW) && (packet_data.flags & PSNET_FLAG_CHECKSUM) ) {
1493                         ushort checksum;                        
1494
1495                         // calculate the size of the data that is actual real data
1496                         len = read_len - (sizeof(packet_data) - MAX_CHECKSUM_PACKET_SIZE);
1497                         checksum = psnet_calc_checksum( packet_data.data, len );
1498                         if ( checksum != packet_data.checksum ) {
1499                                 nprintf(("Network", "bad checksum on incoming packet -- discarding\n"));
1500                                 return;
1501                         }
1502                         data = packet_data.data;
1503                         packet_id = packet_data.sequence_number;
1504                 } else {
1505                         network_naked_packet *packet;
1506
1507                         // just read in the raw socket data and length
1508                         if(flags & PSNET_FLAG_RAW){
1509                                 data = packet_data.data;
1510                                 len = read_len;
1511
1512                                 packet_id = 0;
1513                         } else {
1514                                 // we don't have a checksum packet.  cast the data to the naked packet type and
1515                                 // copy it over to passed parameters
1516                                 packet = (network_naked_packet *)&packet_data;                          
1517         
1518                                 len = read_len - (sizeof(network_naked_packet) - MAX_PACKET_SIZE);
1519                                 data = packet->data;                            
1520
1521                                 packet_id = packet->sequence_number;
1522                         }                       
1523                 }
1524
1525                 // look at the sequence number compared to what we last received                
1526                 if ( Last_packet_id > -1 ) {
1527                         if ( packet_id != (Last_packet_id+1) ) {
1528                                 //if ( packet_id < Last_packet_id )
1529                                 //      nprintf(("network", "packet %d came in delayed (last id was %d\n", packet_id, Last_packet_id));
1530                                 //else if ( packet_id > (Last_packet_id+1) )
1531                                 //      nprintf(("Network", "missed %d packet(s).  last id %d.  This id %d\n", (packet_id - Last_packet_id), Last_packet_id, packet_id));
1532                         }
1533                 }
1534                 Last_packet_id = packet_id;                             
1535
1536 #ifndef NDEBUG
1537                 psnet_do_net_stats( &from_addr, read_len, 1 );
1538                 psnet_bytes_read_frame += read_len;
1539 #endif
1540
1541                 // put all of the data (length, who from, etc.) into the next available packet buffer
1542                 // slot.  We should be assured of a slot here because of the check at the beginning
1543                 // of the while loop
1544                 Assert ( Num_packet_buffers < MAX_PACKET_BUFFERS );
1545                 id = packet_free_list[ Num_packet_buffers++ ];
1546                 if (id > Largest_packet_index ) Largest_packet_index = id;
1547                 packet_buffers[id].len = len;           // use the flags field of the packet structure to hold the data length
1548                 packet_buffers[id].sequence_number =  packet_id;
1549                 packet_buffers[id].from_addr = from_addr;
1550                 memcpy( packet_buffers[id].data, data, len );           
1551 #else
1552 #ifndef NDEBUG
1553                 psnet_do_net_stats( &from_addr, read_len, 1 );
1554                 psnet_bytes_read_frame += read_len;
1555 #endif
1556
1557                 // buffer the packet
1558                 psnet_buffer_packet(packet_data.data,read_len,&from_addr);
1559 #endif
1560         }
1561 }
1562
1563 // -------------------------------------------------------------------------------------------------
1564 // psnet_send()
1565 //
1566 //
1567
1568 int psnet_send( net_addr * who_to, void * data, int len, int flags, int reliable_socket )
1569 {
1570         
1571         SOCKET send_sock;
1572         SOCKADDR_IN sockaddr;                           // UDP/TCP socket structure
1573         SOCKADDR_IPX ipx_addr;                          // IPX socket structure
1574         int ret, send_len;
1575         ubyte iaddr[6], *send_data;
1576         short port;
1577         fd_set  wfds;
1578         struct timeval timeout;
1579
1580         if(!reliable_socket){
1581                 send_sock = Unreliable_socket;
1582         } else {
1583                 send_sock = Reliable_socket;
1584         }
1585
1586         if ( Network_status != NETWORK_STATUS_RUNNING ) {
1587                 nprintf(("Network","Network ==> Socket not inited in psnet_send\n"));
1588                 return 0;
1589         }
1590
1591         if ( psnet_same( who_to, &Psnet_my_addr) ){
1592                 return 0;
1593         }
1594
1595         memset(iaddr, 0x00, 6);
1596         memcpy(iaddr, who_to->addr, 6);
1597
1598         if ( memcmp(iaddr, Null_address, 6) == 0) {
1599                 nprintf(("Network","Network ==> send to address is 0 in psnet_send\n"));
1600                 return 0;
1601         }
1602
1603         if(send_sock == Unreliable_socket){
1604                 port = who_to->port;
1605         } else if(send_sock == Reliable_socket){
1606                 port = DEFAULT_GAME_PORT + 1;
1607         } else {
1608                 port = who_to->port;
1609         }
1610                 
1611         if ( port == 0) {
1612                 nprintf(("Network","Network ==> destination port %d invalid in psnet_send\n", port));
1613                 return 0;
1614         }
1615
1616 #ifdef PSNET_BUFFER_OLD_SCHOOL
1617         network_checksum_packet         Send_network_checksum_packet;
1618         network_naked_packet                    Send_network_naked_packet;
1619
1620         // determine from the flags whether or not this packet should have a checksum.
1621         if ( flags & PSNET_FLAG_CHECKSUM ) {      
1622                 // can't send raw data with a checksum, dumbass!
1623                 Assert(!(flags & PSNET_FLAG_RAW));
1624
1625                 Send_network_checksum_packet.sequence_number = Next_packet_id++;
1626                 Send_network_checksum_packet.flags = PSNET_FLAG_CHECKSUM;
1627                                                 
1628                 Send_network_checksum_packet.checksum = psnet_calc_checksum(data, len);
1629                 memcpy( Send_network_checksum_packet.data, data, len );
1630                 send_len = sizeof(Send_network_checksum_packet) - MAX_CHECKSUM_PACKET_SIZE + len;
1631                 send_data = (ubyte *)&Send_network_checksum_packet;
1632         } else {                
1633                 // send standard psnet stuff
1634                 if(!(flags & PSNET_FLAG_RAW)){
1635                         Send_network_naked_packet.sequence_number = Next_packet_id++;           
1636                         Send_network_naked_packet.flags = 0;
1637                                                 
1638                         memcpy(Send_network_naked_packet.data, data, len);
1639                         send_len = sizeof(Send_network_naked_packet) - MAX_PACKET_SIZE + len;           // gets us the real size of the structure
1640                         send_data = (ubyte *)&Send_network_naked_packet;
1641                 }
1642                 // send raw data
1643                 else {
1644                         send_data = (ubyte*)data;
1645                         send_len = len;
1646                 }
1647         }
1648 #else
1649         send_data = (ubyte*)data;
1650         send_len = len;
1651 #endif
1652
1653
1654         FD_ZERO(&wfds);
1655         FD_SET( send_sock, &wfds );
1656         timeout.tv_sec = 0;
1657         timeout.tv_usec = 0;
1658
1659         if ( select( -1, NULL, &wfds, NULL, &timeout) == SOCKET_ERROR ) {
1660                 nprintf(("Network", "Error on blocking select for write %d\n", WSAGetLastError() ));
1661                 return 0;
1662         }
1663
1664         // if the write file descriptor is not set, then bail!
1665         if ( !FD_ISSET(send_sock, &wfds ) )
1666                 return 0;
1667
1668         ret = SOCKET_ERROR;
1669         switch ( who_to->type ) {
1670
1671                 case NET_IPX:
1672                         ipx_addr.sa_socket = htons(port);
1673                         ipx_addr.sa_family = AF_IPX;
1674                         memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1675                         memcpy(ipx_addr.sa_netnum, who_to->net_id, 4);
1676                                 
1677                         ret = sendto(send_sock, (char *)send_data, send_len, 0, (SOCKADDR*)&ipx_addr, sizeof(ipx_addr));
1678                         if ( (ret != SOCKET_ERROR) && (ret != send_len) )
1679                                 nprintf(("Network", "requested to send %d bytes -- sent %d instead!!!\n", send_len, ret));
1680                         break;
1681
1682
1683
1684                 case NET_TCP:
1685                         sockaddr.sin_family = AF_INET; 
1686                         memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1687                         sockaddr.sin_port = htons(port); 
1688
1689                         ret = sendto( send_sock, (char *)send_data, send_len, 0, (SOCKADDR*)&sockaddr, sizeof(sockaddr) );
1690                         break;
1691
1692                 default:
1693                         Assert(0);      // unknown protocol
1694                         break;
1695
1696         } // end switch
1697
1698         if ( ret != SOCKET_ERROR )      {
1699 #ifndef NDEBUG
1700                 psnet_bytes_written_frame += send_len;
1701                 psnet_do_net_stats( who_to, send_len, 0 );
1702 #endif
1703                 return 1;
1704         }
1705         //Warning( LOCATION, "Couldn't send data (0x%x)!\n", WSAGetLastError() ); 
1706         return 0;
1707 }
1708
1709 #ifdef PSNET_BUFFER_OLD_SCHOOL
1710 // routine to "free" a packet buffer
1711 void free_packet( int id )
1712 {
1713         packet_buffers[id].sequence_number = -1;
1714         packet_free_list[ --Num_packet_buffers ] = (short)id;
1715         if ( Largest_packet_index == id)
1716                 while ((--Largest_packet_index>0) && (packet_buffers[Largest_packet_index].sequence_number == -1 ));
1717 }
1718 #endif
1719
1720 #ifdef PSNET_RELIABLE_OLD_SCHOOL
1721 // psnet_send_reliable sends the given data through the given reliable socket.
1722
1723 #define MAX_RSEND_BUFFER                2048
1724 ubyte rsend_buffer[MAX_RSEND_BUFFER];
1725
1726 int psnet_rel_send( PSNET_SOCKET psocket, ubyte *data, int length, int flags )
1727 {
1728         ubyte *send_data;
1729         int num_sent, total_sent, error, retries;
1730         SOCKET socket;
1731         unsigned short s_length;
1732
1733         socket = (SOCKET)psocket;       
1734
1735         // basic checks
1736         if ( Network_status != NETWORK_STATUS_RUNNING ) {
1737                 nprintf(("Network","Network ==> Socket not inited in psnet_send\n"));
1738                 return 0;
1739         }
1740
1741         if ( socket == INVALID_SOCKET )         // might happen in race conditions -- should get cleaned up.
1742                 return 0;
1743
1744         Assert( length < MAX_RSEND_BUFFER );
1745
1746         // copy the length of the data into the beginning of the buffer.  then put the data into the buffer
1747         // after the length value
1748         Assert( length > 0 );
1749         s_length = (ushort)length;
1750         memcpy( &rsend_buffer[0], &s_length, sizeof(s_length) );
1751         memcpy( &rsend_buffer[2], data, length );
1752
1753         retries = 0;
1754         total_sent = 0;
1755         send_data = data;
1756         do {
1757                 num_sent = send( socket, (char *)rsend_buffer, length+sizeof(s_length), 0 );
1758                 if ( num_sent == SOCKET_ERROR ) {
1759                         error = WSAGetLastError();
1760                         if ( (error != WSAEWOULDBLOCK) || (retries > MAX_SEND_RETRIES) )        {               // means that we would block on send -- not really an error
1761
1762                                 // if error is would block, then set error to aborted connection
1763                                 if ( error == WSAEWOULDBLOCK )
1764                                         error = WSAECONNABORTED;
1765
1766                                 multi_eval_socket_error(socket, error);
1767                                 return 0;
1768                         }
1769                         retries++;                                                                                      // keep a try count
1770                 } else {
1771                         length -= num_sent;
1772                         send_data += num_sent;
1773                         total_sent += num_sent;
1774                 }
1775         } while ( length > 0 );
1776
1777 #ifndef NDEBUG
1778         psnet_bytes_written_frame += total_sent;
1779
1780         //int index;
1781         //index = psnet_find_stats_loc( who_to );
1782         //if ( index != -1 )
1783         //      Psnet_stats[index].total_written += send_len;
1784 #endif
1785         return 1;
1786 }
1787
1788 // get data off the reliable socket
1789 int psnet_rel_get( PSNET_SOCKET psocket, ubyte *buffer, int max_len, int flags)
1790 {
1791         int from_len, total_read, error;
1792         SOCKET socket;
1793         fd_set rfds;
1794         struct timeval timeout;
1795         short read_len;
1796         ubyte rread_buffer[2];
1797
1798         socket = (SOCKET)psocket;
1799
1800         // see if there is data to be read
1801         FD_ZERO(&rfds);
1802         FD_SET( socket, &rfds );
1803         timeout.tv_sec = 0;
1804         timeout.tv_usec = 0;
1805
1806         if ( select( -1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1807                 nprintf(("Network", "Error on select for read reliable: %d\n", WSAGetLastError() ));
1808                 return 0;
1809         }
1810
1811         // if no data, then we can leave.
1812         if ( !FD_ISSET(socket, &rfds ) )
1813                 return 0;
1814
1815         // we know we have data to read.  We must read the two byte length of the packet first
1816         total_read = 0;
1817         read_len = 2;
1818         do {
1819                 from_len = recv(socket, (char *)(&rread_buffer[total_read]), read_len - total_read, 0);
1820
1821                 // from_len will be 0 when back end gracefully closes connection.  We will assume that since
1822                 // the close is graceful, we will info from him telling us he's left.  So we'll ignore
1823                 // this condition here.
1824                 if ( from_len == 0 ) {
1825                         nprintf(("Network", "Dumping player because recv returned 0\n"));
1826                         multi_eval_socket_error( socket, WSAECONNRESET );               // this error drops player from game.
1827                         return 0;
1828                 }
1829
1830                 // on a socket error, we need to check for WSAEWOULDBLOCK meaning that there is no more
1831                 // data to be read.
1832                 else if ( from_len == SOCKET_ERROR ) {
1833                         error = WSAGetLastError();
1834                         if ( error != WSAEWOULDBLOCK )
1835                                 multi_eval_socket_error( socket, error );
1836                         return 0;               // get it next frame?
1837                 }
1838
1839                 total_read += from_len;
1840         } while ( total_read < read_len );
1841
1842
1843         total_read = 0;
1844         memcpy(&read_len, &rread_buffer[0], 2);
1845         Assert( (read_len > 0) && (read_len < max_len) );
1846         if ( read_len == 0 )
1847                 return 0;
1848
1849         do {
1850                 from_len = recv(socket, (char *)(buffer + total_read), read_len - total_read, 0);
1851
1852                 // from_len will be 0 when back end gracefully closes connection.  We will assume that since
1853                 // the close is graceful, we will info from him telling us he's left.  So we'll ignore
1854                 // this condition here.
1855                 if ( from_len == 0 ) {
1856                         nprintf(("Network", "Dumping player because recv returned 0\n"));
1857                         multi_eval_socket_error( socket, WSAECONNRESET );               // this error drops player from game.
1858                         return 0;
1859                 }
1860
1861                 // on a socket error, we need to check for WSAEWOULDBLOCK meaning that there is no more
1862                 // data to be read.
1863                 else if ( from_len == SOCKET_ERROR ) {
1864                         error = WSAGetLastError();
1865                         if ( error != WSAEWOULDBLOCK ) {
1866                                 multi_eval_socket_error( socket, error );
1867                                 return 0;
1868                         }
1869                         continue;
1870                 }
1871
1872                 total_read += from_len;
1873         } while ( total_read < read_len );
1874
1875         return total_read;
1876 }
1877 #else
1878 // psnet_send_reliable sends the given data through the given reliable socket.
1879 int psnet_send_reliable( PSNET_SOCKET psocket, ubyte *data, int length, int flags )
1880 {
1881         // don't do anything if the socket is null
1882         if(psocket == NULL){
1883                 return 0;
1884         }
1885         
1886         // send a reliable data packet
1887         return psnet_reliable_send(data,length,(net_addr*)psocket);
1888 }
1889
1890 int psnet_get_reliable( PSNET_SOCKET psocket, ubyte *buffer, int max_len, int flags)
1891
1892 {
1893         int best, best_id, i, n, size;
1894
1895         // call the routine to read data out of the socket (which stuffs it into the packet buffers)
1896         psnet_get_socket_data(Reliable_socket,flags);
1897
1898 #ifdef PSNET_BUFFER_OLD_SCHOOL
1899         // now determine which (if any) of the packet buffers we should look at!
1900         best = -1;
1901         n = 0;
1902         best_id = -1;
1903
1904         for (i=0; i <= Largest_packet_index; i++ )      {
1905                 if ( packet_buffers[i].sequence_number > -1 ) {
1906                         n++;
1907                         if ( best == -1 || (packet_buffers[i].sequence_number < best) ) {
1908                                 best = packet_buffers[i].sequence_number;
1909                                 best_id = i;
1910                         }
1911                 }                       
1912         }
1913
1914         //mprintf( (0, "Best id = %d, pn = %d, last_ecb = %x, len=%x, ne = %d\n", best_id, best, last_ecb, lastlen, neterrors ));
1915         //mprintf( (1, "<%d> ", neterrors ));
1916
1917         if ( best_id < 0 ) return 0;
1918
1919         size = packet_buffers[best_id].len;
1920         memcpy( buffer, packet_buffers[best_id].data, size );
1921         memcpy( psocket, &packet_buffers[best_id].from_addr, sizeof(net_addr) );
1922         free_packet(best_id);
1923
1924         return size;    
1925 #else
1926         return 0;
1927 #endif
1928 }
1929 #endif
1930
1931 // function which checks the Listen_socket for possibly incoming requests to be connected.
1932 // returns 0 on error or nothing waiting.  1 if we should try to accept
1933 int psnet_rel_check_for_listen(net_addr *from_addr)
1934 {
1935         fd_set  rfds;
1936         timeval timeout;
1937         SOCKET  sock;                           // when trying to accept, this is new socket
1938         SOCKADDR_IN ip_addr;                            // UDP/TCP socket structure
1939         SOCKADDR_IPX ipx_addr;                  // IPX socket structure
1940         int from_len, error;
1941         unsigned long arg;
1942
1943         FD_ZERO(&rfds);
1944         FD_SET( Listen_socket, &rfds );
1945         timeout.tv_sec = 0;
1946         timeout.tv_usec = 0;
1947         if ( select(-1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1948                 nprintf(("Network", "Error %d doing select on listen socket\n", WSAGetLastError() ));
1949                 return 0;
1950         }
1951
1952         // check to see if Listen_socket has something -- if not, return
1953         if ( !FD_ISSET(Listen_socket, &rfds) )
1954                 return INVALID_SOCKET;
1955
1956         sock = INVALID_SOCKET;
1957         switch ( Socket_type ) {
1958         case NET_IPX:
1959                 from_len = sizeof(SOCKADDR_IPX);
1960                 sock = accept( Listen_socket, (SOCKADDR*)&ipx_addr, &from_len );
1961                 from_addr->port = ntohs( ipx_addr.sa_socket );
1962                 memcpy(from_addr->addr, ipx_addr.sa_nodenum, 6 );
1963                 memcpy(from_addr->net_id, ipx_addr.sa_netnum, 4 );
1964                 nprintf(("Network","Accepted SPX connection!!\n"));
1965                 break;
1966
1967         case NET_TCP:
1968                 from_len = sizeof(SOCKADDR_IN);
1969                 sock = accept( Listen_socket, (SOCKADDR*)&ip_addr, &from_len );
1970                 from_addr->port = ntohs( ip_addr.sin_port );
1971                 memset(from_addr->addr, 0x00, 6);
1972                 memcpy(from_addr->addr, &ip_addr.sin_addr.S_un.S_addr, 4);
1973                 nprintf(("Network","Accepted TCP connected!!\n"));
1974                 break;
1975         
1976         default:
1977                 Int3();
1978                 break;
1979         }
1980
1981         if ( !psnet_get_ip(sock) ) {
1982                 return INVALID_SOCKET;
1983         }
1984
1985         // make the new socket non-blocking
1986         if(sock != INVALID_SOCKET){
1987                 arg = TRUE;
1988                 error = ioctlsocket( sock, FIONBIO, &arg );
1989                 if ( error == SOCKET_ERROR ) {
1990                         nprintf(("Network", "Unable to make accepted socket non-blocking -- %d", WSAGetLastError() ));
1991                         return INVALID_SOCKET;
1992                 }
1993         }
1994
1995         return sock;
1996
1997 }
1998
1999 // psnet_get() will call the above function to read data out of the socket.  It will then determine
2000 // which of the buffers we should use and pass to the routine which called us
2001 int psnet_get( void * data, net_addr* from_addr, int flags )
2002 {                       
2003         // USE THIS CODE TO TEST NON-BUFFERED SOCKET READS. OUT-OF-ORDER PACKETS DROP TO NEARLY 0
2004         // - Dave
2005         /*
2006         fd_set  rfds;
2007         timeval timeout;
2008         int read_len,from_len;
2009         SOCKADDR_IN ip_addr;
2010         FD_ZERO(&rfds);
2011         FD_SET( Unreliable_socket, &rfds );
2012         timeout.tv_sec = 0;
2013         timeout.tv_usec = 0;
2014
2015         if ( select( -1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
2016                 nprintf(("Network", "Error %d doing a socket select on read\n", WSAGetLastError()));
2017                 return 0;
2018         }
2019
2020         // if the read file descriptor is not set, then bail!
2021         if ( !FD_ISSET(Unreliable_socket, &rfds ) )
2022                 return 0;
2023
2024         // get data off the socket and process
2025         read_len = SOCKET_ERROR;        
2026         from_len = sizeof(SOCKADDR_IN); 
2027         read_len = recvfrom( Unreliable_socket, (char*)data, MAX_PACKET_SIZE, 0,  (SOCKADDR*)&ip_addr, &from_len );     
2028         from_addr->port = ntohs( ip_addr.sin_port );    
2029         memset(from_addr->addr, 0x00, 6);
2030         memcpy(from_addr->addr, &ip_addr.sin_addr.S_un.S_addr, 4);      
2031         return read_len;        
2032         */
2033         
2034         // call the routine to read data out of the socket (which stuffs it into the packet buffers)
2035         psnet_get_socket_data(Unreliable_socket,flags);
2036
2037 #ifdef PSNET_BUFFER_OLD_SCHOOL
2038         int best, best_id, i, n, size;
2039
2040         // now determine which (if any) of the packet buffers we should look at!
2041         best = -1;
2042         n = 0;
2043         best_id = -1;
2044
2045         for (i=0; i <= Largest_packet_index; i++ )      {
2046                 if ( packet_buffers[i].sequence_number > -1 ) {
2047                         n++;
2048                         if ( best == -1 || (packet_buffers[i].sequence_number < best) ) {
2049                                 best = packet_buffers[i].sequence_number;
2050                                 best_id = i;
2051                         }
2052                 }                       
2053         }
2054
2055         //mprintf( (0, "Best id = %d, pn = %d, last_ecb = %x, len=%x, ne = %d\n", best_id, best, last_ecb, lastlen, neterrors ));
2056         //mprintf( (1, "<%d> ", neterrors ));
2057
2058         if ( best_id < 0 ) return 0;
2059
2060         size = packet_buffers[best_id].len;
2061         memcpy( data, packet_buffers[best_id].data, size );
2062         memcpy( from_addr, &packet_buffers[best_id].from_addr, sizeof(net_addr) );
2063         free_packet(best_id);
2064
2065         return size;
2066 #else
2067         int buffer_size;
2068
2069         // try and get a free buffer and return its size
2070         if(psnet_buffer_get_next((ubyte*)data,&buffer_size,from_addr)){
2071                 return buffer_size;
2072         }
2073
2074         // return nothing
2075         return 0;
2076 #endif
2077 }
2078
2079
2080
2081 // -------------------------------------------------------------------------------------------------
2082 // psnet_broadcast()
2083 //
2084 //
2085
2086 int psnet_broadcast( net_addr * who_to, void * data, int len, int flags )
2087 {
2088         if ( Network_status != NETWORK_STATUS_RUNNING ) {
2089                 nprintf(("Network","Network ==> Socket not inited in psnet_broadcast\n"));
2090                 return 0;
2091         }
2092
2093         if ( !Can_broadcast ) {
2094                 nprintf(("Network", "Cannot broadcast -- returning without doing anything\n"));
2095                 return 0;
2096         }
2097
2098         ubyte broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2099
2100         // broadcasting works on a local subnet which is all we really want to do for now anyway.
2101         // we might keep this in as an option for freespace later.
2102         switch ( who_to->type ) {
2103                 case NET_IPX:
2104                 case NET_TCP:
2105
2106                         memcpy(who_to->addr, broadcast, 6);
2107                         psnet_send(who_to, data, len, flags);
2108                         break;
2109         
2110         } // end switch
2111
2112         return 1;
2113 }
2114
2115 // called to clear out the socket of any remaining data
2116
2117 void psnet_flush()
2118 {
2119         ubyte data[MAX_PACKET_SIZE];
2120         net_addr from_addr;
2121
2122         while ( psnet_get( data, &from_addr ) > 0 ) ;
2123 }
2124
2125
2126
2127 #ifndef NDEBUG
2128 // function to keep track of bytes read/written on average during the frame
2129 void psnet_calc_socket_stats()
2130 {
2131         if ( psnet_frame_int == -1 )    {
2132                 int i;
2133                 for ( i = 0; i < PSNET_FRAME_FILTER; i++ ) {
2134                         psnet_read_sizes[i] = 0;
2135                         psnet_write_sizes[i] = 0;
2136                 }
2137                 psnet_read_total = 0;
2138                 psnet_write_total = 0;
2139                 psnet_frame_int = 0;
2140         }
2141         psnet_read_total -= psnet_read_sizes[psnet_frame_int];
2142         psnet_write_total -= psnet_write_sizes[psnet_frame_int];
2143
2144         psnet_read_total += psnet_bytes_read_frame;
2145         psnet_write_total += psnet_bytes_written_frame;
2146
2147         psnet_read_sizes[psnet_frame_int] = psnet_bytes_read_frame;
2148         psnet_write_sizes[psnet_frame_int] = psnet_bytes_written_frame;
2149
2150         psnet_frame_int = (psnet_frame_int + 1 ) % PSNET_FRAME_FILTER;
2151
2152         if ( psnet_frame_count > 0 )    {
2153                 if ( psnet_frame_count >= PSNET_FRAME_FILTER )
2154                         Psnet_bytes_read = psnet_read_total / PSNET_FRAME_FILTER;
2155                 else
2156                         Psnet_bytes_read = psnet_read_total / psnet_frame_count;
2157
2158                 if ( psnet_frame_count >= PSNET_FRAME_FILTER )
2159                         Psnet_bytes_written = psnet_write_total / PSNET_FRAME_FILTER;
2160                 else
2161                         Psnet_bytes_written = psnet_write_total / psnet_frame_count;
2162         }
2163
2164         psnet_frame_count++;
2165         psnet_bytes_read_frame = 0;
2166         psnet_bytes_written_frame = 0;
2167 }
2168 #endif
2169
2170 int psnet_is_valid_numeric_ip(char *ip)
2171 {
2172         char *token;
2173         char copy[100];
2174         int val1,val2,val3,val4;
2175
2176         // get the first ip value
2177         strcpy(copy,ip);
2178         token = strtok(copy,".");
2179         if(token == NULL){
2180                 return 0;
2181         } else {
2182                 // get the value of the token
2183                 val1 = atoi(token);
2184                 if((val1 < 0) || (val1 > 255)){
2185                         return 0;
2186                 }
2187         }
2188
2189         // second ip value
2190         token = strtok(NULL,".");
2191         if(token == NULL){
2192                 return 0;
2193         } else {
2194                 // get the value of the token
2195                 val2 = atoi(token);
2196                 if((val2 < 0) || (val2 > 255)){
2197                         return 0;
2198                 }
2199         }
2200
2201         // third ip value
2202         token = strtok(NULL,".");
2203         if(token == NULL){
2204                 return 0;
2205         } else {
2206                 // get the value of the token
2207                 val3 = atoi(token);
2208                 if((val3 < 0) || (val3 > 255)){
2209                         return 0;
2210                 }
2211         }
2212
2213         // third ip value
2214         token = strtok(NULL,"");
2215         if(token == NULL){
2216                 return 0;
2217         } else {
2218                 // get the value of the token
2219                 val4 = atoi(token);
2220                 if((val4 < 0) || (val4 > 255)){
2221                         return 0;
2222                 }
2223         }
2224
2225         // make sure he hasn't entered all 0's
2226         if((val1 == 0) && (val2 == 0) && (val3 == 0) && (val4 == 0)){
2227                 return 0;
2228         }
2229
2230         // valid
2231         return 1;
2232 }
2233
2234
2235 // returns true or false if the given string is a valid ip string or not.
2236 // allow port allows us to append the port number on the end of the ip string with
2237 // <addr>:<port#>
2238 // so we must be sure to remove the port number
2239 int psnet_is_valid_ip_string( char *ip_string, int allow_port )
2240 {
2241         in_addr addr;
2242         struct hostent *host_ent;
2243         char str[255], *c;
2244
2245         // our addresses may have ports, so make local copy and remove port number
2246         Assert( strlen(ip_string) < 255 );
2247         strcpy(str, ip_string);
2248         c = strrchr(str, ':');
2249         if ( c ){
2250                 *c = '\0';
2251         }       
2252
2253         addr.s_addr = inet_addr(ip_string);
2254         if ( addr.s_addr != INADDR_NONE ){
2255                 // make sure the ip string is a valid format string
2256                 if(psnet_is_valid_numeric_ip(ip_string)){
2257                         return 1;
2258                 }
2259         }
2260
2261         // try name resolution
2262         host_ent = gethostbyname( ip_string );
2263         if ( !host_ent ){
2264                 return 0;
2265         }
2266
2267         // valid host entry so return 1;
2268         return 1;
2269 }
2270
2271
2272 // ------------------------------------------------------------------------------------------------------
2273 // PACKET BUFFERING FUNCTIONS
2274 //
2275
2276 #ifndef PSNET_BUFFER_OLD_SCHOOL
2277
2278 // a sequence number of -1 will indicate that this packet is not valid
2279 LOCAL network_packet_buffer Psnet_buffers[MAX_PACKET_BUFFERS];
2280 LOCAL int Psnet_seq_number = 0;
2281 LOCAL int Psnet_lowest_id = 0;
2282 LOCAL int Psnet_highest_id = 0;
2283
2284 // initialize the buffering system
2285 void psnet_buffer_init()
2286 {
2287         int idx;
2288         
2289         // blast the buffer clean
2290         memset(Psnet_buffers,0,sizeof(network_packet_buffer) * MAX_PACKET_BUFFERS);
2291         
2292         // set all buffer sequence #'s to -1
2293         for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2294                 Psnet_buffers[idx].sequence_number = -1;
2295         }
2296
2297         // initialize the sequence #
2298         Psnet_seq_number = 0;
2299         Psnet_lowest_id = -1;
2300         Psnet_highest_id = -1;
2301 }
2302
2303 // buffer a packet (maintain order!)
2304 void psnet_buffer_packet(ubyte *data, int length, net_addr *from)
2305 {
2306         int idx;
2307         int found_buf = 0;
2308         
2309         // find the first empty packet
2310         for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2311                 if(Psnet_buffers[idx].sequence_number == -1){
2312                         found_buf = 1;
2313                         break;
2314                 }
2315         }
2316
2317         // if we didn't find the buffer, report an overrun
2318         if(!found_buf){
2319                 nprintf(("Network","WARNING - Buffer overrun in psnet\n"));
2320         } else {
2321                 // copy in the data
2322                 memcpy(Psnet_buffers[idx].data,data,length);
2323                 Psnet_buffers[idx].len = length;
2324                 memcpy(&Psnet_buffers[idx].from_addr,from,sizeof(net_addr));
2325                 Psnet_buffers[idx].sequence_number = Psnet_seq_number;
2326                 
2327                 // keep track of the highest id#
2328                 Psnet_highest_id = Psnet_seq_number++;
2329
2330                 // set the lowest id# for the first time
2331                 if(Psnet_lowest_id == -1){
2332                         Psnet_lowest_id = Psnet_highest_id;
2333                 }
2334         }
2335 }
2336
2337 // get the index of the next packet in order!
2338 int psnet_buffer_get_next(ubyte *data, int *length, net_addr *from)
2339 {       
2340         int idx;
2341         int found_buf = 0;
2342
2343         // if there are no buffers, do nothing
2344         if((Psnet_lowest_id == -1) || (Psnet_lowest_id > Psnet_highest_id)){
2345                 return 0;
2346         }
2347
2348         // search until we find the lowest packet index id#
2349         for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2350                 // if we found the buffer
2351                 if(Psnet_buffers[idx].sequence_number == Psnet_lowest_id){
2352                         found_buf = 1;
2353                         break;
2354                 }
2355         }
2356
2357         // at this point, we should _always_ have found the buffer
2358         Assert(found_buf);
2359         
2360         // copy out the buffer data
2361         memcpy(data,Psnet_buffers[idx].data,Psnet_buffers[idx].len);
2362         *length = Psnet_buffers[idx].len;
2363         memcpy(from,&Psnet_buffers[idx].from_addr,sizeof(net_addr));
2364
2365         // now we need to cleanup the packet list
2366
2367         // mark the buffer as free
2368         Psnet_buffers[idx].sequence_number = -1;
2369         Psnet_lowest_id++;
2370
2371         return 1;
2372 }
2373
2374 #else 
2375
2376 // initialize the buffering system
2377 void psnet_buffer_init() {}
2378
2379 // buffer a packet (maintain order!)
2380 void psnet_buffer_packet(ubyte *data, int length) {}
2381
2382 // get the index of the next packet in order!
2383 int psnet_buffer_get_next() {   return -1; }
2384
2385 #endif
2386
2387 // ------------------------------------------------------------------------------------------------------
2388 // RELIABLE UDP FUNCTIONS
2389 //
2390
2391 // verbose debug output
2392 #define PSNET_RELIABLE_VERBOSE
2393
2394 // overall buffer space allocated to the buffers
2395 #define PSNET_RELIABLE_MAX_OUT_BUFFER_SIZE                                                      (1<<18)                 // 256k
2396 #define PSNET_RELIABLE_MAX_IN_BUFFER_SIZE                                                               (1<<12)                 // 4k
2397
2398 // outgoing reliable packets
2399 typedef struct reliable_packet_out {
2400         ubyte                   data[MAX_PACKET_SIZE];                                  // data in the original packet
2401         ushort          packet_size;                                                            // size of the original packet
2402         ushort          player_flags;                                                           // bitflags indexing (1<<N) into the Psnet_reliable_addr[N] array
2403         ushort          player_acks;                                                            // bitflags indexing (1<<N) into the Psnet_reliable_addr[N] array
2404         int                     player_stamps[MAX_PLAYERS];                     // timeouts for each player
2405         ubyte                   num_resends[MAX_PLAYERS];                               // # of times we've resent to a given player
2406         ushort          out_id;                                                                         // identifier of the packet
2407         fix                     age;                                                                                    // how old this packet is
2408 } reliable_packet_out;
2409
2410 // incoming reliable packets
2411 typedef struct reliable_packet_in {
2412         ushort          in_id;                                                                          // identifier of the received packet
2413         fix                     age;                                                                                    // when we received the packet
2414 } reliable_packet_in;
2415
2416 // # of outgoing and incoming buffers we'll allocate
2417 #define PSNET_RELIABLE_NUM_OUT_BUFFERS                                  (PSNET_RELIABLE_MAX_OUT_BUFFER_SIZE / sizeof(reliable_packet_out))
2418 #define PSNET_RELIABLE_NUM_IN_BUFFERS                                   (PSNET_RELIABLE_MAX_IN_BUFFER_SIZE / sizeof(reliable_packet_in))                                        
2419
2420 // timeout to be used for the packets
2421 #define PSNET_RELIABLE_TIMEOUT                                                  1500                            // in ms
2422
2423 // # of repeats to use
2424 #define PSNET_RELIABLE_REPEAT                                                           8                                       // repeat this many times max
2425
2426 // invalid id#
2427 #define PSNET_RELIABLE_INVALID                                                  0               
2428
2429 // ack code
2430 #define PSNET_RELIABLE_ACK                                                                      0xffff
2431
2432 // the outgoing and incoming buffers themselves
2433 reliable_packet_out *Psnet_reliable_out[PSNET_RELIABLE_NUM_OUT_BUFFERS];
2434 reliable_packet_in *Psnet_reliable_in[PSNET_RELIABLE_NUM_IN_BUFFERS];
2435
2436 // psnet reliable address list
2437 net_addr Psnet_reliable_addr[MAX_PLAYERS];                      // address of registered "reliable" addrs
2438 int Psnet_reliable_addr_flags;                                                  // bitflags indicating which of the above are valid
2439
2440 // my local identifier # (will only use lower 12 bits)
2441 ushort Psnet_reliable_local_id = 0x1;
2442
2443 // is the reliable system initialized
2444 int Psnet_reliable_inited = 0;
2445
2446 // # of times a packet has not been delivered
2447 int Psnet_reliable_fail_count = 0;
2448
2449 // # of times packets have had to be resent
2450 int Psnet_reliable_resend_count = 0;
2451
2452 // # of times we've run out of packets and had to overwrite existing ones
2453 int Psnet_reliable_overwrite_count = 0;
2454
2455 // forward declarations ------------------------------------------------------
2456
2457 // free up all used buffers 
2458 void psnet_reliable_free_all_buffers();
2459
2460 // get the index of the passed address or -1 if it doesn't exist
2461 int psnet_reliable_addr_index(net_addr *addr);
2462
2463 // get the index into the address array from the passed bitflag
2464 int psnet_reliable_index_addr(int flags);
2465
2466 // kill all outgoing packets belonging to the passed index
2467 void psnet_reliable_kill_outgoing(int index);
2468
2469 // generate a unique id #, given the passed in value and the address it came from, return PSNET_RELIABLE_INVALID
2470 // upper 12 bytes should be valid # and the lower 4 should be free for this function to fill in
2471 ushort psnet_reliable_get_unique_id(ushort id_num,net_addr *from);
2472
2473 // get the upper 12 bit version of my id# and increment the original
2474 ushort psnet_reliable_get_next_id();
2475
2476 // get the index of a free outgoing relible packet buffer, killing the oldest if necessary
2477 int psnet_reliable_get_free_outgoing();
2478
2479 // get the index of a free incoming relible packet buffer, killing the oldest if necessary
2480 int psnet_reliable_get_free_incoming();
2481
2482 // actually send the data contained with the reliable_packet_out
2483 int psnet_reliable_send_packet(reliable_packet_out *out,int force_index = 0);
2484
2485 // evaluate the status of a reliable packet - and free it up if the thing is _done_
2486 void psnet_reliable_evaluate_status(reliable_packet_out *out);
2487
2488 // determine if the passed id# exists in the in-packet list, return the instance where it exists, or -1 if it doesn't
2489 int psnet_reliable_find_in_id(ushort id_num);
2490
2491 // determine if the passed id# exists in the out-packet list, return the instance where it exists, or -1 if it doesn't
2492 int psnet_reliable_find_out_id(ushort id_num);
2493
2494 // send an ack to the specified address
2495 void psnet_reliable_send_ack(net_addr *addr,ushort id_num);
2496
2497
2498 // extern functions -----------------------------------------------------------
2499
2500 // initialize the psnet reliable system (return 0 on fail, 1 on success)
2501 int psnet_reliable_init()
2502 {
2503         int idx;
2504
2505         // if the system is already inited, do nothing
2506         if(Psnet_reliable_inited){
2507                 return 1;
2508         }
2509         
2510 #ifdef PSNET_RELIABLE_VERBOSE
2511         nprintf(("Network","PSNET RELIABLE SIZES : \n   OUT BUFFER SIZE : %d\n   OUT BUFFER COUNT %d\n   IN BUFFER SIZE %d\n   IN BUFFER COUNT %d\n",
2512                                 PSNET_RELIABLE_MAX_OUT_BUFFER_SIZE,PSNET_RELIABLE_NUM_OUT_BUFFERS,PSNET_RELIABLE_MAX_IN_BUFFER_SIZE,PSNET_RELIABLE_NUM_IN_BUFFERS));
2513 #endif
2514
2515         // null all buffers
2516         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2517                 Psnet_reliable_out[idx] = NULL;
2518         }
2519         for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2520                 Psnet_reliable_in[idx] = NULL;
2521         }
2522
2523         // initialize all outgoing buffers
2524         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2525                 Psnet_reliable_out[idx] = NULL;
2526                 Psnet_reliable_out[idx] = (reliable_packet_out*)malloc(sizeof(reliable_packet_out));
2527
2528                 // if we failed to allocate the buffer, return failure
2529                 if(Psnet_reliable_out[idx] == NULL){
2530                         psnet_reliable_free_all_buffers();
2531                         return 0;
2532                 }
2533                 memset(Psnet_reliable_out[idx],0,sizeof(reliable_packet_out));
2534         }
2535
2536         // initialize all incoming buffers
2537         for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2538                 Psnet_reliable_in[idx] = NULL;
2539                 Psnet_reliable_in[idx] = (reliable_packet_in*)malloc(sizeof(reliable_packet_in));
2540
2541                 // if we failed to allocate the buffer, return failure
2542                 if(Psnet_reliable_in[idx] == NULL){
2543                         psnet_reliable_free_all_buffers();
2544                         return 0;
2545                 }
2546                 memset(Psnet_reliable_in[idx],0,sizeof(reliable_packet_in));
2547         }
2548
2549         // blast the reliable address list free
2550         memset(Psnet_reliable_addr,0,sizeof(net_addr) * MAX_PLAYERS);
2551         Psnet_reliable_addr_flags = 0;
2552
2553         // set the system to be initialized
2554         Psnet_reliable_inited = 1;
2555
2556         // initialize my local id #
2557         Psnet_reliable_local_id = 0x1;
2558
2559         // initialize the packet delivery fail count
2560         Psnet_reliable_fail_count = 0;
2561
2562         // intialize the packet necessary resend count
2563         Psnet_reliable_resend_count = 0;
2564
2565         // initialize # of times we've run out of packets and had to overwrite existing ones
2566         Psnet_reliable_overwrite_count = 0;
2567
2568         // return success
2569         return 1;
2570 }
2571
2572 // shutdown the reliable system (free up buffers, etc)
2573 void psnet_reliable_close()
2574 {
2575         // if the system is not initialized, don't do anything
2576         if(!Psnet_reliable_inited){
2577                 return;
2578         }
2579
2580         // free up all buffers
2581         psnet_reliable_free_all_buffers();
2582
2583         // blast all addresses clean
2584         memset(Psnet_reliable_addr,0,sizeof(net_addr) * MAX_PLAYERS);
2585         Psnet_reliable_addr_flags = 0;
2586
2587         // set the system as being uninitialized
2588         Psnet_reliable_inited = 0;
2589 }
2590
2591 // notify the reliable system of a new address at index N
2592 void psnet_reliable_notify_new_addr(net_addr *addr,int index)
2593 {
2594         // copy in the address
2595         memcpy(&Psnet_reliable_addr[index],addr,sizeof(net_addr));
2596
2597         // set the bit indicating its validity
2598         Psnet_reliable_addr_flags |= (1<<index);
2599 }
2600
2601 // notify the reliable system of a drop at index N
2602 void psnet_reliable_notify_drop_addr(net_addr *addr)
2603 {
2604         int index;
2605
2606         // do a lookup for the address
2607         index = psnet_reliable_addr_index(addr);
2608         if(index != -1){                
2609                 // clear out all packets belonging exclusively to this address
2610                 psnet_reliable_kill_outgoing(index);
2611
2612                 // clear the address and its existence bit
2613                 memset(&Psnet_reliable_addr[index],0,sizeof(net_addr));
2614                 Psnet_reliable_addr_flags &= ~(1<<index);
2615         }
2616 }
2617
2618 // send a reliable data packet
2619 int psnet_reliable_send(ubyte *data,int packet_size,net_addr *addr)
2620 {
2621         int free_buffer;
2622         int to_index;
2623         reliable_packet_out *p;
2624         
2625         // if the system is not initialized, don't do anything
2626         if(!Psnet_reliable_inited){
2627                 return 0;
2628         }
2629
2630         // try and find a guy to send to 
2631         to_index = -1;
2632         to_index = psnet_reliable_addr_index(addr);
2633         if(to_index == -1){
2634                 nprintf(("Network","PSNET RELIABLE : could not find player for outgoing packet!\n"));
2635                 return 0;
2636         }
2637
2638         // attempt to get a free buffer
2639         free_buffer = -1;
2640         free_buffer = psnet_reliable_get_free_outgoing();
2641         if(free_buffer == -1){
2642                 Int3();                                         // should never happen - we should always overwrite the oldest buffer
2643         }
2644
2645         // setup the data for the outgoing packet
2646         p = Psnet_reliable_out[free_buffer];
2647         memcpy(p->data,data,packet_size);
2648         p->packet_size = (ushort)packet_size;
2649         p->player_flags |= (1<<to_index);
2650         memset(p->player_stamps,0xf,sizeof(int) * MAX_PLAYERS);
2651         p->player_stamps[to_index] = timestamp(PSNET_RELIABLE_TIMEOUT);
2652         p->out_id = psnet_reliable_get_next_id();
2653         p->age = timer_get_fixed_seconds();
2654
2655         // send the packet
2656         return psnet_reliable_send_packet(p);
2657 }
2658
2659 // process frame for all reliable stuff (call once per frame)
2660 void psnet_reliable_process()
2661 {
2662         int idx,s_idx;
2663         reliable_packet_out *p;
2664         
2665         // if the system is not initialized, don't do anything
2666         if(!Psnet_reliable_inited){
2667                 return;
2668         }
2669
2670         // go through all active packets
2671         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2672                 // if the packet is active
2673                 if(Psnet_reliable_out[idx]->out_id != PSNET_RELIABLE_INVALID){
2674                         p = Psnet_reliable_out[idx];
2675
2676                         // loop through all active players and see if we need to resend
2677                         for(s_idx=0;s_idx<MAX_PLAYERS;s_idx++){
2678                                 // if the packet is active for this player and he hasn't acked
2679                                 if(p->player_flags & (1<<s_idx) && !(p->player_acks & (1<<s_idx))){
2680                                         // if the timestamp has elapsed
2681                                         if((p->player_stamps[s_idx] != -1) && timestamp_elapsed(p->player_stamps[s_idx])){
2682                                                 // if we are at max resends, bomb!
2683                                                 if(p->num_resends[s_idx] >= PSNET_RELIABLE_REPEAT){
2684 #ifdef PSNET_RELIABLE_VERBOSE
2685                                                         nprintf(("Network","PSNET RELIABLE : packet failed to be delivered (%d retries) !!\n",PSNET_RELIABLE_REPEAT));
2686 #endif
2687                                                         p->player_flags &= ~(1<<s_idx);
2688
2689                                                         // increment the fail count
2690                                                         Psnet_reliable_fail_count++;
2691                                                 }
2692                                                 // otherwise resend the packet
2693                                                 else {
2694                                                         // actually send the data contained with the reliable_packet_out
2695                                                         psnet_reliable_send_packet(p,s_idx);
2696
2697                                                         // increment the resend count
2698                                                         Psnet_reliable_resend_count++;
2699
2700 #ifdef PSNET_RELIABLE_VERBOSE
2701                                                         nprintf(("Network","PSNET RELIABLE : resending packet\n"));
2702 #endif
2703                                                 }
2704                                         }
2705                                 }
2706                         }
2707
2708                         // evaluate if this packet has completed
2709                         psnet_reliable_evaluate_status(p);
2710                 }
2711         }
2712 }
2713
2714 // determine if the passed in reliable data should be processed, and sends an ack if necessary
2715 // return # of bytes which should be stripped off the data (reliable data header)
2716 int psnet_reliable_should_process(net_addr *addr,ubyte *data,int packet_size)
2717 {
2718         ushort id_num,ack_code,unique_id;
2719         int packet_index;
2720         int player_index;
2721         int free_index;
2722         reliable_packet_in *p;
2723
2724         // get the reliable packet id #
2725         memcpy(&id_num,data,sizeof(ushort));
2726
2727         // if the id# is an ack, get the id# do a lookup
2728         if(id_num == PSNET_RELIABLE_ACK){
2729 #ifdef PSNET_RELIABLE_VERBOSE
2730                 nprintf(("Network","PSNET RELIABLE : ACK 1\n"));
2731 #endif
2732
2733                 ack_code = id_num;
2734
2735                 // get the id#
2736                 memcpy(&id_num,data+2,sizeof(ushort));
2737
2738                 // get the packet index
2739                 // unique_id = psnet_reliable_get_unique_id(id_num,addr);
2740                 unique_id = id_num;
2741                 packet_index = psnet_reliable_find_out_id(unique_id);
2742                 player_index = psnet_reliable_addr_index(addr);                 
2743                 if((packet_index != -1) && (player_index != -1)){
2744 #ifdef PSNET_RELIABLE_VERBOSE
2745                         nprintf(("Network","PSNET RELIABLE : ACK 2\n"));
2746 #endif
2747
2748                         Psnet_reliable_out[packet_index]->player_acks |= (1<<player_index);
2749                         
2750                         // check to see if this packet is _done_
2751                         psnet_reliable_evaluate_status(Psnet_reliable_out[packet_index]);                       
2752                 }
2753
2754                 // return 4 bytes processed
2755                 return 4;
2756         }
2757
2758         // otherwise - see if this is a new packet
2759         packet_index = psnet_reliable_find_in_id(id_num);
2760         if(packet_index == -1){
2761                 // get a free index
2762                 free_index = -1;
2763                 free_index = psnet_reliable_get_free_incoming();
2764                 if(free_index == -1){
2765                         Int3();
2766                 }
2767
2768                 // setup the incoming packet
2769                 p = Psnet_reliable_in[free_index];
2770                 p->age = timer_get_fixed_seconds();
2771                 p->in_id = psnet_reliable_get_unique_id(id_num,addr);
2772
2773                 // send an ack
2774                 psnet_reliable_send_ack(addr,id_num);
2775
2776                 // return 2 bytes processed
2777                 return 2;
2778         }
2779         // send another ack for good measure
2780         else {
2781                 psnet_reliable_send_ack(addr,id_num);
2782         }
2783
2784         return 0;       
2785 }
2786
2787 // forward definitions --------------------------------------------
2788
2789 // free up all used buffers
2790 void psnet_reliable_free_all_buffers()
2791 {
2792         int idx;
2793
2794         // free all outgoing buffers
2795         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2796                 // if the buffer is not null, free it
2797                 if(Psnet_reliable_out[idx] != NULL){
2798                         free(Psnet_reliable_out[idx]);
2799                         Psnet_reliable_out[idx] = NULL;
2800                 }
2801         }
2802
2803         // free all incoming buffers
2804         for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2805                 // if the buffer is not null, free it
2806                 if(Psnet_reliable_in[idx] != NULL){
2807                         free(Psnet_reliable_in[idx]);
2808                         Psnet_reliable_in[idx] = NULL;
2809                 }
2810         }
2811 }
2812
2813 // get the index of the passed address or -1 if it doesn't exist
2814 int psnet_reliable_addr_index(net_addr *addr)
2815 {
2816         int idx;
2817
2818         // look through all valid addresses
2819         for(idx=0;idx<MAX_PLAYERS;idx++){
2820                 if((Psnet_reliable_addr_flags & (1<<idx)) && psnet_same(addr,&Psnet_reliable_addr[idx])){
2821                         return idx;
2822                 }
2823         }
2824
2825         // couldn't find the address
2826         return -1;
2827 }
2828
2829 // get the index into the address array from the passed bitflag
2830 int psnet_reliable_index_addr(int flags)
2831 {
2832         int idx;
2833
2834         // look through all the bits in the flags
2835         for(idx=0;idx<MAX_PLAYERS;idx++){
2836                 if(flags & (1<<idx)){
2837                         return idx;
2838                 }
2839         }
2840
2841         // couldn't find any
2842         return -1;
2843 }
2844
2845 // kill all outgoing packets belonging to the passed index
2846 void psnet_reliable_kill_outgoing(int index)
2847 {
2848         int idx;
2849
2850         // go through all buffers
2851         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2852                 if(Psnet_reliable_out[idx]->out_id != PSNET_RELIABLE_INVALID){
2853                         // if it is exclusively his, kill the whole packet
2854                         if(Psnet_reliable_out[idx]->player_flags == (1<<index)){
2855                                 memset(Psnet_reliable_out[idx],0,sizeof(reliable_packet_out));
2856                                 continue;
2857                         } 
2858                         // if it belongs to him and other players, kill his entry
2859                         else if(Psnet_reliable_out[idx]->player_flags & (1<<index)){
2860                                 Psnet_reliable_out[idx]->player_flags &= ~(1<<index);
2861                                 Psnet_reliable_out[idx]->num_resends[index] = 0;
2862                         }
2863                 }
2864         }
2865 }
2866
2867 // generate a unique id #, given the passed in value and the address it came from, return PSNET_RELIABLE_INVALID
2868 // upper 12 bytes should be valid # and the lower 4 should be free for this function to fill in
2869 ushort psnet_reliable_get_unique_id(ushort id_num,net_addr *from)
2870 {
2871         int idx;
2872         ushort cast;
2873         
2874         // if the lower 4 bits are not clear, we've got a problem
2875         if(id_num & 0xf){
2876                 Int3();
2877         }
2878
2879         // lookup through the Psnet_reliable_addr[] list and try and find the index
2880         for(idx=0;idx<MAX_PLAYERS;idx++){
2881                 if((idx == 1) /*(Psnet_reliable_addr_flags & (1<<idx)) && (psnet_same(from,&Psnet_reliable_addr[idx]))*/){
2882                         // fill in the lower 4 bits
2883                         cast = (ushort)idx;
2884                         id_num |= (cast & 0xf);
2885                         return id_num;
2886                 }
2887         }
2888
2889         // couldn't find an id#
2890         return PSNET_RELIABLE_INVALID;
2891 }
2892
2893 // get the upper 12 bit version of my id# and increment the original
2894 ushort psnet_reliable_get_next_id()
2895 {
2896         ushort id_num = Psnet_reliable_local_id;
2897
2898         // clear out the upper 4 bits
2899         id_num &= 0x0fff;
2900
2901         // shift 4 bits to the left
2902         id_num <<= 4;
2903
2904         // increment the local id #
2905         if(Psnet_reliable_local_id == 0x0fff){
2906                 Psnet_reliable_local_id = 0x1;
2907         } else {
2908                 Psnet_reliable_local_id++;
2909         }
2910
2911         // return the shifted value
2912         return id_num;
2913 }
2914
2915 // get the index of a free outgoing relible packet buffer, killing the oldest if necessary
2916 int psnet_reliable_get_free_outgoing()
2917 {
2918         fix oldest = -1;
2919         int oldest_index = -1;
2920         int idx;
2921
2922         // search through all buffers
2923         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2924                 if(Psnet_reliable_out[idx]->out_id == PSNET_RELIABLE_INVALID){
2925                         return idx;
2926                 }
2927
2928                 // keep track of the oldest packet
2929                 if((oldest_index == -1) || (Psnet_reliable_out[idx]->age < oldest)){
2930                         oldest_index = idx;
2931                         oldest = Psnet_reliable_out[idx]->age;
2932                 }
2933         }
2934
2935         // if we got here, all of our buffers are full, so we should kill the oldest one
2936         memset(Psnet_reliable_out[oldest_index],0,sizeof(reliable_packet_out));
2937         Psnet_reliable_overwrite_count = 0;
2938 #ifdef PSNET_RELIABLE_VERBOSE
2939         nprintf(("Network","PSNET RELIABLE : overwriting old send buffer\n"));
2940 #endif
2941         return oldest_index;
2942 }
2943
2944 // get the index of a free incoming relible packet buffer, killing the oldest if necessary
2945 int psnet_reliable_get_free_incoming()
2946 {
2947         fix oldest = -1;
2948         int oldest_index = -1;
2949         int idx;
2950
2951         // search through all buffers
2952         for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2953                 if(Psnet_reliable_in[idx]->in_id == PSNET_RELIABLE_INVALID){
2954                         return idx;
2955                 }
2956
2957                 // keep track of the oldest packet
2958                 if((oldest_index == -1) || (Psnet_reliable_in[idx]->age < oldest)){
2959                         oldest_index = idx;
2960                         oldest = Psnet_reliable_in[idx]->age;
2961                 }
2962         }
2963
2964         // if we got here, all of our buffers are full, so we should kill the oldest one
2965         memset(Psnet_reliable_in[oldest_index],0,sizeof(reliable_packet_in));   
2966 #ifdef PSNET_RELIABLE_VERBOSE
2967         nprintf(("Network","PSNET RELIABLE : overwriting old recv buffer\n"));
2968 #endif
2969         return oldest_index;
2970 }
2971
2972 // actually send the data contained with the reliable_packet_out
2973 int psnet_reliable_send_packet(reliable_packet_out *out,int force_index)
2974 {       
2975         ubyte data[MAX_PACKET_SIZE];    
2976         int idx,bytes_sent;
2977         int packet_size = 2 + out->packet_size;
2978
2979         // stick the identifier on the front of the packet
2980         memcpy(data,&out->out_id,sizeof(ushort));
2981
2982         // copy in the actual data
2983         memcpy(data+2,out->data,out->packet_size);
2984
2985         // send the packet and update the timestamp for all players
2986         
2987         // send to one specified player in the packet
2988         bytes_sent = 0;
2989         if(force_index != 0){
2990                 if(out->player_flags & (1<<force_index) && !(out->player_acks & (1<<force_index))){
2991                         bytes_sent = psnet_send(&Psnet_reliable_addr[force_index],data,packet_size,PSNET_FLAG_RAW,1);                   
2992                         out->player_stamps[force_index] = timestamp(PSNET_RELIABLE_TIMEOUT);
2993                         out->num_resends[force_index]++;
2994                 }
2995         }
2996         // send to all players contained in the packet
2997         else {
2998                 for(idx=0;idx<MAX_PLAYERS;idx++){
2999                         // if this guy is flagged and he exists and he hasn't already acked
3000                         if(out->player_flags & (1<<idx) && (Psnet_reliable_addr_flags & (1<<idx)) && !(out->player_acks & (1<<idx))){
3001                                 bytes_sent = psnet_send(&Psnet_reliable_addr[idx],data,packet_size,PSNET_FLAG_RAW,1);                           
3002                                 out->player_stamps[idx] = timestamp(PSNET_RELIABLE_TIMEOUT);
3003                                 out->num_resends[idx]++;
3004                         }
3005                 }
3006         }
3007
3008         // return success
3009         return bytes_sent;
3010 }
3011
3012 // evaluate the status of a reliable packet - and free it up if the thing is _done_
3013 void psnet_reliable_evaluate_status(reliable_packet_out *out)
3014 {
3015         int idx,ok;
3016
3017         // check to see if all players have acked or failed miserably
3018         ok = 1;
3019         for(idx=0;idx<MAX_PLAYERS;idx++){
3020                 // if the packet is active for this guy but he has not acked yet
3021                 if((out->player_flags & (1<<idx)) && !(out->player_acks & (1<<idx))){
3022                         ok = 0;
3023                         break;
3024                 }
3025         }
3026
3027         // if its ok to annihilate this packet, do so
3028         if(ok){
3029                 memset(out,0,sizeof(reliable_packet_out));
3030         }
3031 }
3032
3033 // determine if the passed id# exists in the in-packet list, return the instance where it exists, or -1 if it doesn't
3034 int psnet_reliable_find_in_id(ushort id_num)
3035 {
3036         int idx;
3037
3038         // if the id is 0, its invalid
3039         if(id_num == PSNET_RELIABLE_INVALID){
3040                 return -1;
3041         }
3042
3043         // look through all in packets
3044         for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
3045                 if(id_num == Psnet_reliable_in[idx]->in_id){
3046                         return idx;
3047                 }
3048         }
3049
3050         // couldn't find it 
3051         return -1;
3052 }
3053
3054 // determine if the passed id# exists in the out-packet list, return the instance where it exists, or -1 if it doesn't
3055 int psnet_reliable_find_out_id(ushort id_num)
3056 {
3057         int idx;
3058
3059         // if the id is 0, its invalid
3060         if(id_num == PSNET_RELIABLE_INVALID){
3061                 return -1;
3062         }
3063
3064         // look through all in packets
3065         for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
3066                 if(id_num == Psnet_reliable_out[idx]->out_id){
3067                         return idx;
3068                 }
3069         }
3070
3071         // couldn't find it 
3072         return -1;
3073 }
3074
3075 // send an ack to the specified address
3076 void psnet_reliable_send_ack(net_addr *addr,ushort id_num)
3077 {
3078         ubyte data[10];
3079         ushort val;
3080
3081         // add in the ack
3082         val = PSNET_RELIABLE_ACK;
3083         memcpy(data,&val,sizeof(ushort));
3084
3085         // add in the id#
3086         memcpy(data+2,&id_num,sizeof(ushort));
3087
3088         // send the data
3089         psnet_send(addr,data,4,PSNET_FLAG_RAW,Reliable_socket);
3090 }
3091
3092 #endif  // #ifndef PSNET2