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