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