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