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