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