]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/psnet2.cpp
use SDL_arraysize() instead of sizeof() where appropriate
[taylor/freespace2.git] / src / network / psnet2.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/Psnet2.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C file containing application level network-interface.
16  *
17  * $Log$
18  * Revision 1.14  2005/10/02 09:30:10  taylor
19  * sync up rest of big-endian network changes.  it should at least be as good as what's in FS2_Open now, only better :)
20  *
21  * Revision 1.13  2005/10/01 22:01:28  taylor
22  * some cleanup of earlier big-endian changes
23  *
24  * Revision 1.12  2004/07/04 11:39:06  taylor
25  * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
26  *
27  * Revision 1.11  2004/06/11 01:52:15  tigital
28  * byte-swapping changes for bigendian systems
29  *
30  * Revision 1.10  2003/08/03 16:10:30  taylor
31  * cleanup; compile warning fixes
32  *
33  * Revision 1.9  2002/07/27 19:52:54  relnev
34  * add missing structure packing
35  *
36  * Revision 1.8  2002/06/09 04:41:24  relnev
37  * added copyright header
38  *
39  * Revision 1.7  2002/06/02 05:31:17  relnev
40  * unstub
41  *
42  * Revision 1.6  2002/06/02 02:29:39  relnev
43  * net fixes
44  *
45  * Revision 1.5  2002/05/27 04:04:43  relnev
46  * 155 undefined references left
47  *
48  * Revision 1.4  2002/05/26 21:27:53  theoddone33
49  * More progress (I hate psnet2)
50  *
51  * Revision 1.3  2002/05/26 20:49:54  theoddone33
52  * More progress
53  *
54  * Revision 1.2  2002/05/07 03:16:48  theoddone33
55  * The Great Newline Fix
56  *
57  * Revision 1.1.1.1  2002/05/03 03:28:10  root
58  * Initial import.
59  *
60  * 
61  * 25    9/14/99 2:21p Dave
62  * Fixed observer mode joining and ingame stuff.
63  * 
64  * 24    9/10/99 9:44p Dave
65  * Bumped version # up. Make server reliable connects not have such a huge
66  * timeout. 
67  * 
68  * 23    9/07/99 4:01p Dave
69  * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
70  * does everything properly (setting up address when binding). Remove
71  * black rectangle background from UI_INPUTBOX.
72  * 
73  * 22    8/26/99 8:51p Dave
74  * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
75  * 
76  * 21    8/16/99 4:06p Dave
77  * Big honking checkin.
78  * 
79  * 20    7/26/99 5:50p Dave
80  * Revised ingame join. Better? We'll see....
81  * 
82  * 19    7/20/99 1:49p Dave
83  * Peter Drake build. Fixed some release build warnings.
84  * 
85  * 18    7/15/99 9:20a Andsager
86  * FS2_DEMO initial checkin
87  * 
88  * 17    7/03/99 4:08p Dave
89  * Fixed wss_slots size issues. Fixed potentially nasty bug in low level
90  * reliable code.
91  * 
92  * 16    6/25/99 5:02p Jasenw
93  * Removed old debug code.
94  * 
95  * 15    6/07/99 9:51p Dave
96  * Consolidated all multiplayer ports into one.
97  * 
98  * 14    4/30/99 12:18p Dave
99  * Several minor bug fixes.
100  * 
101  * 13    4/27/99 5:55p Dave
102  * Fixed Ras_connected bug with VSDK code.
103  * 
104  * 12    4/27/99 2:59p Dave
105  * Potential fix for reliable socket connection problem.
106  * 
107  * 11    4/23/99 11:07a Dave
108  * Added lots of debug multi.log output to psnet2
109  * 
110  * 10    4/12/99 10:07p Dave
111  * Made network startup more forgiving. Added checkmarks to dogfight
112  * screen for players who hit commit.
113  * 
114  * 9     3/10/99 6:50p Dave
115  * Changed the way we buffer packets for all clients. Optimized turret
116  * fired packets. Did some weapon firing optimizations.
117  * 
118  * 8     3/09/99 6:24p Dave
119  * More work on object update revamping. Identified several sources of
120  * unnecessary bandwidth.
121  * 
122  * 7     3/08/99 7:03p Dave
123  * First run of new object update system. Looks very promising.
124  * 
125  * 6     1/24/99 11:37p Dave
126  * First full rev of beam weapons. Very customizable. Removed some bogus
127  * Int3()'s in low level net code.
128  * 
129  * 5     1/06/99 2:24p Dave
130  * Stubs and release build fixes.
131  * 
132  * 4     11/20/98 11:16a Dave
133  * Fixed up IPX support a bit. Making sure that switching modes and
134  * loading/saving pilot files maintains proper state.
135  * 
136  * 3     11/19/98 4:19p Dave
137  * Put IPX sockets back in psnet. Consolidated all multiplayer config
138  * files into one.
139  * 
140  * 2     11/19/98 8:04a Dave
141  * Full support for D3-style reliable sockets. Revamped packet lag/loss
142  * system, made it receiver side and at the lowest possible level.
143  *
144  * $NoKeywords: $
145  */
146
147 #ifndef PLAT_UNIX
148 #include <windows.h>
149 #include <windowsx.h>
150 #include <winsock.h>
151 #include <wsipx.h>
152 #include <process.h>
153 #include <ras.h>
154 #include <raserror.h>
155 #else
156 #include <sys/types.h>
157 #include <sys/socket.h>
158 #include <netinet/in.h>
159 #include <arpa/inet.h>
160 #include <netdb.h>
161 #include <errno.h>
162 #endif
163 #include <stdio.h>
164 #include <limits.h>
165
166 #include "pstypes.h"
167 #include "psnet.h"
168 #include "multi.h"
169 #include "multiutil.h"
170 #include "multilag.h"
171 #include "osregistry.h"
172 #include "timer.h"
173 #include "multi_log.h"
174 #include "multi_rate.h"
175 #include "cmdline.h"
176
177 #ifdef PSNET2
178
179 // -------------------------------------------------------------------------------------------------------
180 // PSNET 2 DEFINES/VARS
181 //
182
183 int             Psnet_my_addr_valid;
184 net_addr_t Psnet_my_addr;
185
186 ubyte Null_address[6];
187
188 int Socket_type;
189 int Can_broadcast;                      // can we do broadcasting on our socket?
190 int Ipx_can_broadcast = 0;
191 int Tcp_can_broadcast = 0;
192
193 int Tcp_active = 0;
194 int Ipx_active = 0;
195
196 int Network_status;
197 int Tcp_failure_code = 0;
198 int Ipx_failure_code = 0;
199 int Ras_connected;
200 int Psnet_connection;
201
202 ushort  Psnet_default_port;
203
204 // specified their internet connnection type
205 #define NETWORK_CONNECTION_NONE                 1
206 #define NETWORK_CONNECTION_DIALUP               2
207 #define NETWORK_CONNECTION_LAN                  3
208
209 // defines and variables to indicate network connection status
210 #define NETWORK_STATUS_NOT_INITIALIZED  1
211 #define NETWORK_STATUS_NO_WINSOCK               2                       // winsock failed to initialize
212 #define NETWORK_STATUS_NO_PROTOCOL              3                       // TCP/IP doesn't appear to be loaded
213 #define NETWORK_STATUS_NO_RELIABLE              4
214 #define NETWORK_STATUS_RUNNING                  5                       // everything should be running
215
216 // defintion of structures that actually leave this machine.  psnet_send give us only
217 // the data that we want to send.  We will add a header onto this data (packet sequence
218 // number, possibly a checksum).  We must include a 2 byte flags variable into both structure
219 // since the receiving end of this packet must know whether or not to checksum the packet.
220
221 #define MAX_TOP_LAYER_PACKET_SIZE                       680
222
223 // use the pack pragma to pack these structures to 2 byte aligment.  Really only needed for
224 // the naked packet.
225 #define MAX_PACKET_BUFFERS              75
226
227 #ifndef PLAT_UNIX
228 #pragma pack(push, 2)
229 #endif
230
231 // definition for a non-checksum packet
232 typedef struct network_packet
233 {
234         int             sequence_number;
235         ushort  flags;
236         ubyte           data[MAX_TOP_LAYER_PACKET_SIZE];
237 } network_naked_packet;
238
239 // structure definition for our packet buffers
240 typedef struct network_packet_buffer
241 {
242         int             sequence_number;
243         int             len;    
244         net_addr_t      from_addr;
245         ubyte           data[MAX_TOP_LAYER_PACKET_SIZE];
246 } network_packet_buffer;
247
248 // struct for a bunch of network packet buffers
249 typedef struct network_packet_buffer_list {
250         network_packet_buffer psnet_buffers[MAX_PACKET_BUFFERS];
251         int psnet_seq_number;
252         int psnet_lowest_id;
253         int psnet_highest_id;
254 } network_packet_buffer_list;
255
256 #ifndef PLAT_UNIX
257 #pragma pack(pop)
258 #endif
259
260
261 #define MAXHOSTNAME                     128
262
263 #define MAX_RECEIVE_BUFSIZE     4096    // 32 K, eh?
264 #define MAX_SEND_RETRIES                20                      // number of retries when sending would block
265 #define MAX_LINGER_TIME                 0                       // in seconds -- when lingering to close a socket
266
267 //Reliable UDP stuff
268 //*******************************
269 #define MAXNETBUFFERS                   150             // Maximum network buffers (For between network and upper level functions, which is 
270                                                                                                         // required in case of out of order packets
271 #define NETRETRYTIME                            0.75f           // Time after sending before we resend
272 #define MIN_NET_RETRYTIME               0.2f
273 #define NETTIMEOUT                              30                      // Time after receiving the last packet before we drop that user
274 #define NETHEARTBEATTIME                3                       // How often to send a heartbeat
275 #define MAXRELIABLESOCKETS              40                      // Max reliable sockets to open at once...
276 #define NETBUFFERSIZE                   600             // Max size of a network packet
277
278 #define RELIABLE_CONNECT_TIME           7               // how long we'll wait for a response when doing a reliable connect
279
280 int Nettimeout = NETTIMEOUT;
281
282 // Reliable packet stuff
283 #define RNT_ACK                         1                               // ACK Packet
284 #define RNT_DATA                                2                               // Data Packet
285 #define RNT_DATA_COMP           3                               // Compressed Data Packet
286 #define RNT_REQ_CONN                    4                               // Requesting a connection
287 #define RNT_DISCONNECT          5                               // Disconnecting a connection
288 #define RNT_HEARTBEAT           6                               // Heartbeat -- send every NETHEARTBEATTIME
289 #define RNT_I_AM_HERE           7
290
291 #ifndef PLAT_UNIX
292 #pragma pack(push,r_udp)
293 #pragma pack(1)
294 #define PACKED
295 #else
296 #define PACKED __attribute__((packed))
297 #endif
298
299 typedef struct {
300         ubyte                   type;                                   // packet type
301         ubyte                   compressed;                     //
302         ushort          seq;                                    // sequence packet 0-65535 used for ACKing also
303         ushort          data_len;                       // length of data
304         float                   send_time;                      // Time the packet was sent, if an ACK the time the packet being ACK'd was sent.
305         ubyte           data[NETBUFFERSIZE];    // Packet data
306 } PACKED reliable_header;
307
308 #define RELIABLE_PACKET_HEADER_ONLY_SIZE (sizeof(reliable_header)-NETBUFFERSIZE)
309 #define MAX_PING_HISTORY        10
310
311 typedef struct {
312         ubyte buffer[NETBUFFERSIZE];
313
314 } PACKED reliable_net_sendbuffer;
315
316 typedef struct {
317         ubyte buffer[NETBUFFERSIZE];
318 } PACKED reliable_net_rcvbuffer;
319
320 typedef struct {
321         reliable_net_sendbuffer *sbuffers[MAXNETBUFFERS];       // This is an array of pointers for quick sorting
322         unsigned short ssequence[MAXNETBUFFERS];                                // This is the sequence number of the given packet
323         float timesent[MAXNETBUFFERS];
324         int send_len[MAXNETBUFFERS];
325         reliable_net_rcvbuffer  *rbuffers[MAXNETBUFFERS];
326         int recv_len[MAXNETBUFFERS];
327         unsigned short rsequence[MAXNETBUFFERS];                                // This is the sequence number of the given packet
328         float last_packet_received;                                                             // For a given connection, this is the last packet we received
329         float last_packet_sent;
330         struct sockaddr addr;                                                                                                   // struct sockaddr of our peer
331         ushort status;                                                                                                  // Status of this connection
332         unsigned short oursequence;                                                             // This is the next sequence number the application is expecting
333         unsigned short theirsequence;                                                           // This is the next sequence number the peer is expecting
334         net_addr_t      net_addr;                                                                                       // A FS2 network address structure
335         ubyte connection_type;                                                                          // IPX, IP, modem, etc.
336         float pings[MAX_PING_HISTORY];
337         ubyte ping_pos;
338         unsigned int num_ping_samples;
339         float mean_ping;        
340 } reliable_socket;
341
342 reliable_socket Reliable_sockets[MAXRELIABLESOCKETS];
343
344 // sockets for IPX and TCP (unreliable)
345 SOCKET IPX_socket;
346 SOCKET TCP_socket;
347
348 // the sockets that the game will use when selecting network type
349 SOCKET Unreliable_socket = INVALID_SOCKET;
350
351 // blah
352 // SOCKET Reliable_UDP_socket = INVALID_SOCKET;
353 // SOCKET Reliable_IPX_socket = INVALID_SOCKET;
354
355 float First_sent_iamhere = 0;
356 float Last_sent_iamhere = 0;
357
358 #define CONNECTSEQ 0x142                                                                                // Magic number for starting a connection, just so it isn't 0
359
360 unsigned int Serverconn = 0xffffffff;
361
362 #ifndef PLAT_UNIX
363 #pragma pack(pop,r_udp)
364 #endif
365 #undef PACKED
366
367 //*******************************
368
369 // top layer buffers
370 network_packet_buffer_list Psnet_top_buffers[PSNET_NUM_TYPES];
371
372 // -------------------------------------------------------------------------------------------------------
373 // PSNET 2 FORWARD DECLARATIONS
374 //
375
376 // if the string is a legally formatted ip string
377 int psnet_is_valid_numeric_ip(char *ip);
378
379 // functions to get the status of a RAS connection
380 unsigned int psnet_ras_status();
381
382 // set some options on a socket
383 void psnet_socket_options( SOCKET sock );
384
385 // initialize ipx socket
386 int psnet_init_ipx();
387
388 // initialize tcp socket
389 int psnet_init_tcp();
390
391 // get time in seconds
392 float psnet_get_time();
393
394 // returns the ip address of this machine. use for calling bind() with to associate with the proper
395 // IP address and network device.
396 int psnet_get_ip();
397
398 // initialize reliable sockets
399 int psnet_init_rel_tcp(int port, int should_listen);
400 int psnet_init_rel_ipx(int port, int should_listen);
401
402 // shutdown reliable sockets
403 void psnet_rel_close();
404
405 // initialize the buffering system
406 void psnet_buffer_init(network_packet_buffer_list *l);
407
408 // buffer a packet (maintain order!)
409 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr_t *from);
410
411 // get the index of the next packet in order!
412 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr_t *from);
413
414
415 // -------------------------------------------------------------------------------------------------------
416 // PSNET 2 TOP LAYER FUNCTIONS - these functions simply buffer and store packets based upon type (see PSNET_TYPE_* defines)
417 //
418
419 // wrappers around select() and recvfrom() for lagging/losing data
420 int RECVFROM(SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen, int psnet_type)
421 {
422         network_packet_buffer_list *l;
423         net_addr_t addr;
424         int ret;
425         int ret_len;
426
427         // bad type
428         SDL_assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
429         if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
430                 return -1;
431         }       
432         l = &Psnet_top_buffers[psnet_type];
433
434         // if we have no buffer! The user should have made sure this wasn't the case by calling SELECT()
435         ret = psnet_buffer_get_next(l, (ubyte*)buf, &ret_len, &addr);
436         if(!ret){
437                 Int3();
438                 return -1;
439         }
440
441         // otherwise, stuff the outgoing data
442         switch ( Socket_type ) {
443         case NET_IPX:                   
444 #ifdef PLAT_UNIX
445                 STUB_FUNCTION;
446 #else
447                 ((SOCKADDR_IPX*)from)->sa_socket = htons(addr.port);
448                 memcpy(((SOCKADDR_IPX*)from)->sa_nodenum, addr.addr, 6);
449                 memcpy(((SOCKADDR_IPX*)from)->sa_netnum, addr.net_id, 4);               
450                 ((SOCKADDR_IPX*)from)->sa_family = AF_IPX;              
451                 *fromlen = sizeof(SOCKADDR_IPX);
452 #endif
453                 break;
454
455         case NET_TCP:                   
456                 ((struct sockaddr_in*)from)->sin_port = htons(addr.port);
457 #ifdef PLAT_UNIX
458                 memcpy(&((struct sockaddr_in*)from)->sin_addr.s_addr, addr.addr, 4);
459 #else
460                 memcpy(&((struct sockaddr_in*)from)->sin_addr.S_un.S_addr, addr.addr, 4);
461 #endif
462                 ((struct sockaddr_in*)from)->sin_family = AF_INET;
463                 *fromlen = sizeof(struct sockaddr_in);
464                 break;
465
466         default:
467                 SDL_assert(0);
468                 break;
469         }
470
471         // return bytes read
472         return ret_len;
473 }
474
475 #ifdef PLAT_UNIX
476 #define FAR
477 #endif
478 // wrappers around select() and recvfrom() for lagging/losing data
479 int SELECT(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, struct timeval FAR * timeout, int psnet_type)
480 {
481         network_packet_buffer_list *l;
482
483         // if this is a check for writability, just return the select 
484         if(writefds != NULL){
485                 return select(nfds, readfds, writefds, exceptfds, timeout);
486         }       
487         
488         // bad type
489         SDL_assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
490         if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
491                 return -1;
492         }       
493         l = &Psnet_top_buffers[psnet_type];     
494
495         // do we have any buffers in here?      
496         if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
497                 return 0;
498         }
499
500         // yo
501         return 1;
502 }
503
504 // wrappers around sendto to sorting through different packet types
505 int SENDTO(SOCKET s, char * buf, int len, int flags, sockaddr *to, int tolen, int psnet_type)
506 {       
507         char outbuf[MAX_TOP_LAYER_PACKET_SIZE + 150];           
508
509         // stuff type
510         outbuf[0] = (char)psnet_type;
511         memcpy(&outbuf[1], buf, len);
512
513         // is the socket writeable?
514         
515         // send it
516         return sendto(s, outbuf, len + 1, flags, (struct sockaddr*)to, tolen);
517 }
518
519 // call this once per frame to read everything off of our socket
520 void PSNET_TOP_LAYER_PROCESS()
521 {
522         // read socket stuff
523         struct sockaddr_in ip_addr;                             // UDP/TCP socket structure
524 #ifndef PLAT_UNIX
525         SOCKADDR_IPX ipx_addr;                  // IPX socket structure
526 #endif
527         fd_set  rfds;
528         timeval timeout;
529         int read_len;
530 #ifndef PLAT_UNIX       
531         int from_len;
532 #else
533         socklen_t from_len;
534 #endif
535         net_addr_t      from_addr;      
536         network_naked_packet packet_read;               
537
538         // clear the addresses to remove compiler warnings
539         memset(&ip_addr, 0, sizeof(struct sockaddr_in));
540 #ifndef PLAT_UNIX
541         memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
542 #endif
543
544         if ( Network_status != NETWORK_STATUS_RUNNING ) {
545                 ml_printf("Network ==> socket not inited in PSNET_TOP_LAYER_PROCESS\n");
546                 return;
547         }
548
549         while ( 1 ) {           
550                 // check if there is any data on the socket to be read.  The amount of data that can be 
551                 // atomically read is stored in len.
552
553                 FD_ZERO(&rfds);
554                 FD_SET( Unreliable_socket, &rfds );
555                 timeout.tv_sec = 0;
556                 timeout.tv_usec = 0;
557
558 #ifndef PLAT_UNIX
559                 if ( select( -1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
560 #else
561                 if ( select( Unreliable_socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {              
562 #endif          
563                         ml_printf("Error %d doing a socket select on read\n", WSAGetLastError());
564                         break;
565                 }
566
567                 // if the read file descriptor is not set, then bail!
568                 if ( !FD_ISSET(Unreliable_socket, &rfds) ){
569                         return;
570                 }
571
572                 // get data off the socket and process
573                 read_len = SOCKET_ERROR;
574                 switch ( Socket_type ) {
575                 case NET_IPX:
576 #ifndef PLAT_UNIX
577                         from_len = sizeof(SOCKADDR_IPX);                        
578                         read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0,  (struct sockaddr*)&ipx_addr, &from_len);
579 #endif
580                         break;
581
582                 case NET_TCP:
583                         from_len = sizeof(struct sockaddr_in);
584                         read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0,  (struct sockaddr*)&ip_addr, &from_len);
585                         break;
586                 
587                 default:
588                         SDL_assert(0);
589                         return;
590                 }
591
592                 // set the from_addr for storage into the packet buffer structure
593                 from_addr.type = Socket_type;
594
595                 switch ( Socket_type ) {
596                 case NET_IPX:                   
597 #ifndef PLAT_UNIX
598                         from_addr.port = ntohs( ipx_addr.sa_socket );                   
599                         memcpy(from_addr.addr, ipx_addr.sa_nodenum, 6 );
600                         memcpy(from_addr.net_id, ipx_addr.sa_netnum, 4 );
601 #endif
602                         break;
603
604                 case NET_TCP:                   
605                         from_addr.port = ntohs( ip_addr.sin_port );                     
606                         memset(from_addr.addr, 0x00, 6);
607 #ifndef PLAT_UNIX
608                         memcpy(from_addr.addr, &ip_addr.sin_addr.S_un.S_addr, 4);
609 #else
610                         memcpy(from_addr.addr, &ip_addr.sin_addr.s_addr, 4);
611 #endif
612                         break;
613
614                 default:
615                         SDL_assert(0);
616                         return;
617                         // break;
618                 }
619
620                 if ( read_len == SOCKET_ERROR ) {
621                         // int x = WSAGetLastError();
622                         ml_printf("Socket error on socket_get_data()");
623                         break;
624                 }               
625
626                 // determine the packet type
627                 int packet_type = packet_read.data[0];          
628                 // mprintf(("TOP LAYER PACKET  %d!\n", packet_type));
629                 if((packet_type < 0) || (packet_type >= PSNET_NUM_TYPES)){
630                         Int3();
631                 } else {                
632                         // buffer the packet
633                         psnet_buffer_packet(&Psnet_top_buffers[packet_type], packet_read.data + 1, read_len - 1, &from_addr);
634                 }
635         }
636 }
637
638
639 // -------------------------------------------------------------------------------------------------------
640 // PSNET 2 FUNCTIONS
641 //
642
643 // initialize psnet to use the specified port
644 void psnet_init( int protocol, int port_num )
645 {       
646         const char *internet_connection;
647 #ifndef PLAT_UNIX
648         WSADATA wsa_data;               
649 #endif
650         int idx;
651         Tcp_active = 0;
652         Ipx_active = 0;
653
654 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
655         return;
656 #endif
657
658         // GAME PORT INITIALIZATION STUFF
659         if ( Network_status == NETWORK_STATUS_RUNNING ){
660                 ml_string("Skipping psnet_init() because network already running");
661                 return;
662         }
663
664         // 'lan' should be a safe default in 2015
665         internet_connection = os_config_read_string("Network", "NetworkConnection", "LAN");
666
667         if ( !SDL_strcasecmp(internet_connection, NOX("dialup")) ) {
668                 ml_string("psnet_init() detected dialup connection");
669
670                 Psnet_connection = NETWORK_CONNECTION_DIALUP;
671         } else if ( !SDL_strcasecmp(internet_connection, NOX("lan")) ) {
672                 ml_string("psnet_init() detected lan connection");
673
674                 Psnet_connection = NETWORK_CONNECTION_LAN;
675         } else {
676                 ml_string("psnet_init() detected no connection");
677
678                 Psnet_connection = NETWORK_CONNECTION_NONE;
679         }
680
681         Network_status = NETWORK_STATUS_NO_WINSOCK;
682 #ifndef PLAT_UNIX
683         if (WSAStartup(0x101, &wsa_data )){
684                 return;
685         }
686 #endif
687
688         // get the port for running this game on.  Be careful that it cannot be out of bounds
689         Psnet_default_port = DEFAULT_GAME_PORT;
690         if ( (port_num > 1023) && (port_num < USHRT_MAX) ) {
691                 Psnet_default_port = (ushort)port_num;
692         }
693
694         // initialize TCP now   
695         Tcp_active = 1;
696         if(!psnet_init_tcp()){
697                 ml_printf("Error on TCP startup %d\n", Tcp_failure_code);               
698
699                 Tcp_active = 0;
700         } else {
701                 if(!psnet_init_rel_tcp(Psnet_default_port + 1, 0)){
702                         ml_printf("Network", "Error on TCP startup %d\n", Tcp_failure_code);                    
703
704                         Tcp_active = 0;
705                 }
706         }
707
708         // clear reliable sockets
709         reliable_socket *rsocket;
710         int j;  
711         for(j=0; j<MAXRELIABLESOCKETS; j++){
712                 rsocket=&Reliable_sockets[j];
713                 memset(rsocket,0,sizeof(reliable_socket));
714         }
715
716         // initialize IPX not
717 #ifndef PLAT_UNIX
718         Ipx_active = 1;
719         if(!psnet_init_ipx()){
720                 ml_printf("Network", "Error on IPX startup %d\n", Ipx_failure_code);            
721
722                 Ipx_active = 0;
723         } else {
724                 if(!psnet_init_rel_ipx(Psnet_default_port + 1, 0)){
725                         ml_printf("Network", "Error on IPX startup %d\n", Ipx_failure_code);                    
726
727                         Ipx_active = 0;
728                 }
729         }
730 #else
731         Ipx_active = 0;
732 #endif
733
734         // determine if we've successfully initialized the protocol we want
735         if(!Tcp_active && !Ipx_active){ 
736                 Network_status = NETWORK_STATUS_NO_PROTOCOL;            
737
738                 ml_string("No protocol in psnet_init()!");
739         }
740
741         // specified network timeout    
742         Nettimeout = NETTIMEOUT;
743         if(Cmdline_timeout > 0){
744                 Nettimeout = Cmdline_timeout;
745         }
746
747         // set ras status
748         psnet_ras_status();     
749
750         if(Network_status != NETWORK_STATUS_NO_PROTOCOL){                       
751                 // set network to be running
752                 Network_status = NETWORK_STATUS_RUNNING;        
753         
754                 // determine if our socket can broadcast
755                 Can_broadcast = Tcp_can_broadcast || Ipx_can_broadcast;                         
756         
757                 // initialize all packet type buffers
758                 for(idx=0; idx<PSNET_NUM_TYPES; idx++){
759                         psnet_buffer_init(&Psnet_top_buffers[idx]);
760                 }
761         }
762 }
763
764 // shutdown psnet
765 void psnet_close()
766 {
767         if ( Network_status != NETWORK_STATUS_RUNNING ){
768                 return;
769         }
770
771 #ifndef PLAT_UNIX
772         WSACancelBlockingCall();                
773 #endif
774
775         if ( TCP_socket != (int)INVALID_SOCKET ) {
776                 shutdown( TCP_socket, 1 );
777                 closesocket( TCP_socket );
778         }
779
780         if ( IPX_socket != (int)INVALID_SOCKET ) {
781                 shutdown( IPX_socket, 1 );
782                 closesocket( IPX_socket );
783         }
784
785 #ifndef PLAT_UNIX
786         if (WSACleanup())       {
787                 //Warning( LOCATION, "Error closing wsock!\n" );
788         }
789 #endif
790
791         // close down all reliable sockets - this forces them to
792         // send a disconnect to any remote machines     
793         psnet_rel_close();
794         
795         Network_status = NETWORK_STATUS_NOT_INITIALIZED;
796 }
797
798 // set the protocol to use
799 int psnet_use_protocol( int protocol )
800 {
801 #ifndef PLAT_UNIX
802         int len;
803         SOCKADDR_IPX    ipx_addr;
804 #else
805         socklen_t len;
806 #endif
807         struct sockaddr_in              ip_addr;
808
809         // zero out my address
810         Psnet_my_addr_valid = 0;
811         memset( &Psnet_my_addr, 0, sizeof(Psnet_my_addr) );
812
813         // wait until we choose a protocol to determine if we can broadcast
814         Can_broadcast = 0;
815
816         ml_string("In psnet_use_protocol()");
817
818         switch ( protocol ) {
819         case NET_IPX:           
820 #ifndef PLAT_UNIX
821                 ml_string("psnet_use_protocol() selecting IPX");
822
823                 // assign the IPX_* sockets to the socket values used elsewhere
824                 Unreliable_socket = IPX_socket;         
825
826                 Can_broadcast = Ipx_can_broadcast;
827                 if(Can_broadcast){
828                         ml_printf("Psnet : IPX broadcast\n");
829                 }
830
831                 // get the socket name for the IPX_socket, and put it into My_addr
832                 len = sizeof(SOCKADDR_IPX);
833                 if ( getsockname(IPX_socket, (struct sockaddr *)&ipx_addr, &len) == SOCKET_ERROR ) {
834                         ml_printf("Unable to get sock name for IPX unreliable socket (%d)\n", WSAGetLastError() );
835                         return 0;
836                 }
837
838                 memcpy(Psnet_my_addr.net_id, ipx_addr.sa_netnum, 4);
839                 memcpy(Psnet_my_addr.addr, ipx_addr.sa_nodenum, 6);
840                 Psnet_my_addr.port = Psnet_default_port;
841
842                 ml_printf("Psnet using - NET_IPX\n");
843 #endif
844                 break;
845
846         case NET_TCP:
847                 if ( Network_status != NETWORK_STATUS_RUNNING ){
848                         ml_string("Network_status != NETWORK_STATUS_RUNNING in NET_TCP in psnet_use_protocol()");
849                         return 0;
850                 }
851
852                 // assign the TCP_* sockets to the socket values used elsewhere
853                 Unreliable_socket = TCP_socket;         
854
855                 Can_broadcast = Tcp_can_broadcast;
856                 if(Can_broadcast){
857                         ml_printf("Psnet : TCP broadcast\n");
858                 }
859
860                 // get the socket name for the IPX_socket, and put it into My_addr
861                 len = sizeof(struct sockaddr_in);
862                 if ( getsockname(TCP_socket, (struct sockaddr *)&ip_addr, &len) == SOCKET_ERROR ) {
863                         ml_printf("Unable to get sock name for TCP unreliable socket (%d)\n", WSAGetLastError() );                      
864
865                         return 0;
866                 }
867                 
868                 memset(Psnet_my_addr.net_id, 0, 4);
869                 memcpy(Psnet_my_addr.addr, &ip_addr.sin_addr, 6);
870                 Psnet_my_addr.port = Psnet_default_port;
871
872                 ml_printf("Psnet using - NET_TCP\n");
873                 break;
874
875         default:
876                 Int3();
877                 return 0;
878         }
879
880         Psnet_my_addr.type = protocol;
881         Socket_type = protocol;
882
883         return 1;
884 }
885
886 // get the status of the network
887 int psnet_get_network_status()
888 {
889         // first case is when "none" is selected
890         if ( Psnet_connection == NETWORK_CONNECTION_NONE ) {
891                 return NETWORK_ERROR_NO_TYPE;
892         }
893
894         // first, check the connection status of the network
895         if ( Network_status == NETWORK_STATUS_NO_WINSOCK )
896                 return NETWORK_ERROR_NO_WINSOCK;
897
898         if ( Network_status == NETWORK_STATUS_NO_PROTOCOL ){
899                 return NETWORK_ERROR_NO_PROTOCOL;
900         }
901         
902         // network is running -- be sure that the RAS people know to connect if they currently cannot.
903         
904         if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
905                 // if on a dialup connection, be sure that RAS is active.
906                 if ( !Ras_connected ) {
907                         return NETWORK_ERROR_CONNECT_TO_ISP;
908                 }
909         } else if ( Psnet_connection == NETWORK_CONNECTION_LAN ) {
910                 // if on a LAN, and they have a dialup connection active, return error to indicate that they need
911                 // to pick the right connection type
912                 if ( Ras_connected ) {
913                         return NETWORK_ERROR_LAN_AND_RAS;
914                 }
915         }
916         return NETWORK_ERROR_NONE;
917 }
918
919 // convert a net_addr to a string
920 char* psnet_addr_to_string( char * text, const int max_textlen, net_addr_t * address )
921 {
922
923         if ( Network_status != NETWORK_STATUS_RUNNING )         {
924                 SDL_strlcpy( text, XSTR("[no networking]",910), max_textlen );
925                 return text;
926         }
927
928         in_addr temp_addr;
929
930         switch ( address->type ) {
931                 case NET_IPX:
932                         SDL_snprintf(text, max_textlen, "%x %x %x %x: %x %x %x %x %x %x", address->net_id[0],
933                                                                                                                                                         address->net_id[1],
934                                                                                                                                                         address->net_id[2],
935                                                                                                                                                         address->net_id[3],
936                                                                                                                                                         address->addr[0],
937                                                                                                                                                         address->addr[1],
938                                                                                                                                                         address->addr[2],
939                                                                                                                                                         address->addr[3],
940                                                                                                                                                         address->addr[4],
941                                                                                                                                                         address->addr[5]);
942                         break;
943
944                 case NET_TCP:
945                         memcpy(&temp_addr.s_addr, address->addr, 4);
946                         SDL_strlcpy( text, inet_ntoa(temp_addr), max_textlen );
947                         break;
948
949                 default:
950                         // SDL_assert(0);
951                         break;
952
953         } // end switch
954         
955         return text;
956 }
957
958 // convert a string to a net addr
959 void psnet_string_to_addr( net_addr_t * address, char * text, const int max_textlen )
960 {
961         struct hostent *he;
962         char str[255], *c, *port;
963         in_addr addr;
964
965         if ( Network_status != NETWORK_STATUS_RUNNING ) {
966                 SDL_strlcpy( text, XSTR("[no networking]",910), max_textlen );
967                 return;
968         }
969
970         // copy the text string to local storage to look for ports
971         SDL_assert( strlen(text) < 255 );
972         SDL_strlcpy(str, text, SDL_arraysize(str));
973         c = strrchr(str, ':');
974         port = NULL;
975         if ( c ) {
976                 *c = '\0';
977                 port = c+1;
978         }
979
980         switch ( address->type ) {
981                 case NET_IPX:         
982                         Int3();         // no support for this yet
983                         break;
984
985                 case NET_TCP:
986                         addr.s_addr = inet_addr(str);
987                         // if we get INADDR_NONE returns, then we need to try and resolve the host
988                         // name
989                         if ( addr.s_addr == INADDR_NONE ) {
990                                 he = gethostbyname( str );
991                                 // returns a non-null pointer if successful, so get the address
992                                 if ( he ) {
993                                         addr.s_addr = ((in_addr *)(he->h_addr))->s_addr;                        // this is the address in network byte order
994                                 } else {
995                                         addr.s_addr = INADDR_NONE;
996                                 }
997                         }
998
999                         memset(address->addr, 0x00, 6);
1000                         memcpy(address->addr, &addr.s_addr, 4);
1001                         if ( port ){
1002                                 address->port = (ushort)(atoi(port));
1003                         }
1004                         break;
1005
1006                 default:
1007                         SDL_assert(0);
1008                         break;
1009
1010         } // end switch
1011 }
1012
1013 // compare 2 addresses
1014 int psnet_same( net_addr_t * a1, net_addr_t * a2 )
1015 {
1016         return !memcmp(a1->addr, a2->addr, 6);          
1017 }
1018
1019 // send data unreliably
1020 int psnet_send( net_addr_t * who_to, void * data, int len, int np_index )
1021 {
1022         // send data unreliably
1023         SOCKET send_sock;
1024         struct sockaddr_in sockaddr;                            // UDP/TCP socket structure
1025 #ifndef PLAT_UNIX
1026         SOCKADDR_IPX ipx_addr;                          // IPX socket structure
1027 #endif
1028         int ret, send_len;
1029         ubyte iaddr[6], *send_data;
1030         short port;
1031         fd_set  wfds;
1032         struct timeval timeout; 
1033
1034         // always use the reliable socket
1035         send_sock = Unreliable_socket;          
1036
1037         if ( Network_status != NETWORK_STATUS_RUNNING ) {
1038                 ml_printf("Network ==> Socket not inited in psnet_send\n");
1039                 return 0;
1040         }
1041
1042         if ( psnet_same( who_to, &Psnet_my_addr) ){
1043                 return 0;
1044         }
1045
1046         memset(iaddr, 0x00, 6);
1047         memcpy(iaddr, who_to->addr, 6);
1048
1049         if ( memcmp(iaddr, Null_address, 6) == 0) {
1050                 ml_printf("Network ==> send to address is 0 in psnet_send\n");
1051                 return 0;
1052         }
1053         
1054         port = who_to->port;
1055                 
1056         if ( port == 0) {
1057                 ml_printf("Network ==> destination port %d invalid in psnet_send\n", port);
1058                 return 0;
1059         }
1060
1061         // stuff the data with the type 
1062         send_data = (ubyte*)data;
1063         send_len = len;
1064
1065         FD_ZERO(&wfds);
1066         FD_SET( send_sock, &wfds );
1067         timeout.tv_sec = 0;
1068         timeout.tv_usec = 0;
1069
1070 #ifndef PLAT_UNIX
1071         if ( SELECT( -1, NULL, &wfds, NULL, &timeout, PSNET_TYPE_UNRELIABLE) == SOCKET_ERROR ) {
1072 #else
1073         if ( SELECT( send_sock+1, NULL, &wfds, NULL, &timeout, PSNET_TYPE_UNRELIABLE) == SOCKET_ERROR ) {       
1074 #endif
1075                 ml_printf("Error on blocking select for write %d\n", WSAGetLastError() );
1076                 return 0;
1077         }
1078
1079         // if the write file descriptor is not set, then bail!
1080         if ( !FD_ISSET(send_sock, &wfds ) ){
1081                 return 0;
1082         }
1083
1084         ret = SOCKET_ERROR;
1085         switch ( who_to->type ) {
1086                 case NET_IPX:
1087 #ifndef PLAT_UNIX
1088                         ipx_addr.sa_socket = htons(port);
1089                         ipx_addr.sa_family = AF_IPX;
1090                         memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1091                         memcpy(ipx_addr.sa_netnum, who_to->net_id, 4);
1092                                 
1093                         ret = SENDTO(send_sock, (char *)send_data, send_len, 0, (struct sockaddr*)&ipx_addr, sizeof(ipx_addr), PSNET_TYPE_UNRELIABLE);
1094
1095                         multi_rate_add(np_index, "ipx", send_len);
1096                         if ( (ret != SOCKET_ERROR) && (ret != send_len) ){
1097                                 // ml_printf("requested to send %d bytes -- sent %d instead!!!\n", send_len, ret);
1098                         }
1099 #endif
1100                         break;
1101
1102                 case NET_TCP:
1103                         sockaddr.sin_family = AF_INET; 
1104                         memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1105                         sockaddr.sin_port = htons(port); 
1106
1107                         multi_rate_add(np_index, "udp(h)", send_len + UDP_HEADER_SIZE);
1108                         multi_rate_add(np_index, "udp", send_len);
1109                         ret = SENDTO( send_sock, (char *)send_data, send_len, 0, (struct sockaddr*)&sockaddr, sizeof(sockaddr), PSNET_TYPE_UNRELIABLE );
1110                         break;
1111
1112                 default:
1113                         SDL_assert(0);  // unknown protocol
1114                         break;
1115
1116         } // end switch
1117
1118         if ( ret != SOCKET_ERROR )      {
1119                 return 1;
1120         }
1121         //Warning( LOCATION, "Couldn't send data (0x%x)!\n", WSAGetLastError() ); 
1122         return 0;
1123 }
1124
1125 // get data from the unreliable socket
1126 int psnet_get( void * data, net_addr_t * from_addr )
1127 {                                       
1128         int buffer_size;
1129
1130         // try and get a free buffer and return its size
1131         if(psnet_buffer_get_next(&Psnet_top_buffers[PSNET_TYPE_UNRELIABLE], (ubyte*)data, &buffer_size, from_addr)){
1132                 return buffer_size;
1133         }
1134
1135         // return nothing
1136         return 0;
1137 }
1138
1139 // broadcast data on unreliable socket
1140 int psnet_broadcast( net_addr_t * who_to, void * data, int len )
1141 {
1142         if ( Network_status != NETWORK_STATUS_RUNNING ) {
1143                 ml_printf("Network ==> Socket not inited in psnet_broadcast\n");
1144                 return 0;
1145         }
1146
1147         if ( !Can_broadcast ) {
1148                 ml_printf("Cannot broadcast -- returning without doing anything\n");
1149                 return 0;
1150         }
1151
1152         ubyte broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1153
1154         // broadcasting works on a local subnet which is all we really want to do for now anyway.
1155         // we might keep this in as an option for freespace later.
1156         switch ( who_to->type ) {
1157                 case NET_IPX:
1158                 case NET_TCP:
1159                         memcpy(who_to->addr, broadcast, 6);
1160                         psnet_send(who_to, data, len);
1161                         break;
1162         
1163         } // end switch
1164
1165         return 1;
1166 }
1167
1168 // flush all sockets
1169 void psnet_flush()
1170 {
1171         ubyte data[MAX_TOP_LAYER_PACKET_SIZE + 250];
1172         net_addr_t from_addr;
1173
1174         while ( psnet_get( data, &from_addr ) > 0 ) ;
1175 }
1176
1177 // if the passed string is a valid IP string
1178 int psnet_is_valid_ip_string( char *ip_string, int allow_port )
1179 {
1180         in_addr addr;
1181         struct hostent *host_ent;
1182         char str[255], *c;
1183
1184         // our addresses may have ports, so make local copy and remove port number
1185         SDL_assert( strlen(ip_string) < 255 );
1186         SDL_strlcpy(str, ip_string, SDL_arraysize(str));
1187         c = strrchr(str, ':');
1188         if ( c ){
1189                 *c = '\0';
1190         }       
1191
1192         addr.s_addr = inet_addr(ip_string);
1193         if ( addr.s_addr != INADDR_NONE ){
1194                 // make sure the ip string is a valid format string
1195                 if(psnet_is_valid_numeric_ip(ip_string)){
1196                         return 1;
1197                 }
1198         }
1199
1200         // try name resolution
1201         host_ent = gethostbyname( ip_string );
1202         if ( !host_ent ){
1203                 return 0;
1204         }
1205
1206         // valid host entry so return 1;
1207         return 1;
1208 }
1209
1210
1211 // -------------------------------------------------------------------------------------------------------
1212 // PSNET 2 RELIABLE SOCKET FUNCTIONS
1213 //
1214
1215 // compare 2 pings
1216 int psnet_rel_ping_compare( const void *arg1, const void *arg2 )
1217 {
1218         float *ping1 = (float *)arg1;
1219         float *ping2 = (float *)arg2;
1220         
1221         if(*ping1==*ping2) return 0;
1222         else if(*ping1>*ping2) return 1;
1223         else if(*ping1<*ping2) return -1;
1224
1225         return 0;
1226 }
1227
1228 void psnet_rel_send_ack(struct sockaddr *raddr, unsigned int sig, ubyte link_type, float time_sent)
1229 {
1230         int sig_tmp;
1231         reliable_header ack_header;
1232         ack_header.type = RNT_ACK;      
1233         ack_header.data_len = sizeof(unsigned int);
1234         ack_header.send_time = INTEL_FLOAT( time_sent );
1235         sig_tmp = INTEL_INT( sig );
1236         memcpy(&ack_header.data,&sig_tmp,sizeof(unsigned int));
1237         switch (link_type) {
1238         case NET_IPX:
1239                 if(!Ipx_active){
1240                         ml_string("No IPX in rel_send_ack()");
1241                         return;
1242                 }               
1243                 SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1244                 break;
1245         case NET_TCP:
1246                 if(!Tcp_active){
1247                         ml_string("No TCP in rel_send_ack()");
1248                         return;
1249                 }
1250                 SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1251                 break;
1252         default:                
1253                 ml_string("Unknown protocol type in nw_SendReliable()");
1254                 // Int3();
1255                 break;
1256         }       
1257 }
1258
1259 // function to shutdown and close the given socket.  It takes a couple of things into consideration
1260 // when closing, such as possibly reiniting reliable sockets if they are closed here.
1261 void psnet_rel_close_socket( PSNET_SOCKET_RELIABLE *sockp )
1262 {
1263         reliable_header diss_conn_header;
1264
1265         // if the socket is out of range
1266         if(*sockp>=MAXRELIABLESOCKETS)
1267         {
1268                 ml_printf("Invalid socket id passed to nw_NewCloseSocket() -- %d\n",*sockp);
1269                 return;
1270         }       
1271         ml_printf("Closing socket %d\n",*sockp);
1272         
1273         // go through every buffer and "free it up(tm)"
1274         int i;
1275         for(i=0;i<MAXNETBUFFERS;i++){
1276                 if(Reliable_sockets[*sockp].rbuffers[i]){
1277                         if(Reliable_sockets[*sockp].rbuffers[i] != NULL){
1278                                 free(Reliable_sockets[*sockp].rbuffers[i]);
1279                         }
1280                         Reliable_sockets[*sockp].rbuffers[i] = NULL;
1281                         Reliable_sockets[*sockp].rsequence[i] = 0;
1282                 }
1283                 if(Reliable_sockets[*sockp].sbuffers[i]){
1284                         if(Reliable_sockets[*sockp].sbuffers[i] != NULL){
1285                                 free(Reliable_sockets[*sockp].sbuffers[i]);
1286                         }
1287                         Reliable_sockets[*sockp].sbuffers[i] = NULL;
1288                         Reliable_sockets[*sockp].rsequence[i] = 0;
1289                 }
1290         }
1291
1292         // send a disconnect packet to the socket on the other end
1293         diss_conn_header.type = RNT_DISCONNECT;
1294         diss_conn_header.seq = CONNECTSEQ;
1295         diss_conn_header.data_len = 0;
1296         if(*sockp==Serverconn){
1297                 Serverconn = 0xffffffff;
1298         }
1299         switch ( Reliable_sockets[*sockp].connection_type ) {
1300                 case NET_IPX:
1301                         if(!Ipx_active){
1302                                  return;
1303                         }
1304                         SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1305                         break;
1306                 case NET_TCP:
1307                         if(!Tcp_active){
1308                                 return;
1309                         }
1310                         SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1311                         break;
1312                 default:
1313                         ml_printf("Unknown protocol type in nw_CloseSocket()!\n");                      
1314                         // Int3();
1315                         break;
1316         }
1317         memset(&Reliable_sockets[*sockp],0,sizeof(reliable_socket));
1318         Reliable_sockets[*sockp].status = RNF_UNUSED;   
1319 }
1320
1321 // function to check the status of the reliable socket and try to re-initialize it if necessary.
1322 // win95 seems to have trouble doing a reinit of the socket immediately after close, so this
1323 // function exists to check the status, and reinitialize if we need to
1324 int psnet_rel_check()
1325 {
1326         return 1;
1327 }
1328
1329 // send data reliably
1330 int psnet_rel_send(PSNET_SOCKET_RELIABLE socketid, ubyte *data, int length, int np_index)
1331 {               
1332         int i;
1333         int bytesout = 0;
1334         reliable_socket *rsocket;       
1335         
1336         if(socketid >= MAXRELIABLESOCKETS){
1337                 ml_printf("Invalid socket id passed to psnet_rel_send() -- %d\n",socketid);
1338                 return -1;
1339         }
1340
1341         SDL_assert( length < (int)(sizeof(reliable_header)) );
1342         psnet_rel_work();
1343
1344         rsocket=&Reliable_sockets[socketid];
1345         if(rsocket->status!=RNF_CONNECTED) {
1346                 //We can't send because this isn't a connected reliable socket.
1347                 ml_printf("Can't send packet because of status %d in nw_SendReliable(). socket = %d\n",rsocket->status,socketid);
1348                 return -1;
1349         }
1350         
1351         // Add the new packet to the sending list and send it.
1352         for(i=0;i<MAXNETBUFFERS;i++){
1353                 if(NULL==rsocket->sbuffers[i]){                 
1354                         reliable_header send_header;
1355                         int send_this_packet=1;                 
1356                         
1357                         rsocket->send_len[i] = length;
1358                         rsocket->sbuffers[i] = (reliable_net_sendbuffer *)malloc(sizeof(reliable_net_sendbuffer));
1359                 
1360                         memcpy(rsocket->sbuffers[i]->buffer,data,length);       
1361
1362                         send_header.seq = INTEL_SHORT( rsocket->theirsequence );
1363                         rsocket->ssequence[i] = rsocket->theirsequence;
1364                         
1365                         memcpy(send_header.data,data,length);
1366                         send_header.data_len = INTEL_SHORT( (ushort)length );
1367                         send_header.type = RNT_DATA;
1368                         send_header.send_time = psnet_get_time();
1369                         send_header.send_time = INTEL_FLOAT( send_header.send_time );
1370                         // struct sockaddr_in * rsockaddr = (struct sockaddr_in *)&rsocket->addr;
1371                                         
1372                         if (send_this_packet){
1373                                 switch ( rsocket->connection_type ){
1374                                         case NET_IPX:
1375                                                 if(!Ipx_active){
1376                                                         return 0;
1377                                                 }
1378                                                 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1379                                                 break;
1380                                         case NET_TCP:
1381                                                 if(!Tcp_active){
1382                                                         return 0;
1383                                                 }
1384                                                 multi_rate_add(np_index, "tcp(h)", RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i]);
1385                                                 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1386                                                 break;
1387                                         default:
1388                                                 ml_printf("Unknown protocol type in nw_SendReliable()!\n");
1389                                                 Int3();
1390                                                 break;
1391                                 }               
1392                         }
1393                         if((bytesout==SOCKET_ERROR)&&(WSAEWOULDBLOCK==WSAGetLastError())){
1394                                 //This will cause it to try to send again next frame. (or sooner)
1395                                 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1396                         } else {
1397                                 rsocket->timesent[i] = psnet_get_time();
1398                         }
1399                         
1400                                                 
1401                         rsocket->theirsequence++;
1402                         return bytesout;
1403                 }
1404         }
1405         ml_printf("PSNET RELIABLE SEND BUFFER OVERRUN. socket = %d\n",socketid);        
1406         // Int3();
1407         return 0;
1408 }
1409
1410 // Return codes:
1411 // -1 socket not connected
1412 // 0 No packet ready to receive
1413 // >0 Buffer filled with the number of bytes recieved
1414 int psnet_rel_get(PSNET_SOCKET socketid, ubyte *buffer, int max_len)
1415 {       
1416         int i;
1417         
1418         reliable_socket *rsocket = NULL;
1419         psnet_rel_work();
1420         if(socketid >= MAXRELIABLESOCKETS){
1421                 ml_printf("Invalid socket id passed to nw_NewReceiveReliable() -- %d\n",socketid);
1422                 return -1;
1423         }
1424         rsocket = &Reliable_sockets[socketid];
1425         if( (RNF_CONNECTED!=rsocket->status) && (RNF_LIMBO!=rsocket->status) ){
1426                 ml_printf("Can't receive packet because it isn't connected in nw_ReceiveReliable(). socket = %d\n",socketid);
1427                 return 0;
1428         }
1429         //If the buffer position is the position we are waiting for, fill in 
1430         //the buffer we received in the call to this function and return true                   
1431
1432         for(i=0; i<MAXNETBUFFERS; i++){
1433                 if((rsocket->rsequence[i] == rsocket->oursequence) && rsocket->rbuffers[i]){
1434                         memcpy(buffer,rsocket->rbuffers[i]->buffer, rsocket->recv_len[i]);
1435                         free(rsocket->rbuffers[i]);
1436                         rsocket->rbuffers[i] = NULL;
1437                         rsocket->rsequence[i] = 0;                      
1438                         rsocket->oursequence++;
1439                         return rsocket->recv_len[i];
1440                 }
1441         }
1442
1443         return 0;       
1444 }
1445
1446 // process all active reliable sockets
1447 void psnet_rel_work()
1448 {
1449         int i,j;
1450         int rcode = -1;
1451         int max_len = NETBUFFERSIZE;
1452         fd_set read_fds;                   
1453         struct timeval timeout;
1454         static reliable_header rcv_buff;
1455         static struct sockaddr rcv_addr;
1456         int bytesin = 0;
1457         int addrlen = sizeof(struct sockaddr);
1458         timeout.tv_sec=0;            
1459         timeout.tv_usec=0;
1460
1461         PSNET_TOP_LAYER_PROCESS();
1462                 
1463         // negotitate initial connection with the server
1464         reliable_socket *rsocket = NULL;
1465         if(Serverconn != 0xffffffff){
1466                 //Check to see if we need to send a packet out.
1467                 if((Reliable_sockets[Serverconn].status==RNF_LIMBO) && ((Serverconn != 0xffffffff) && fl_abs((psnet_get_time() - Last_sent_iamhere))>NETRETRYTIME) ){
1468                         reliable_header conn_header;
1469                         //Now send I_AM_HERE packet
1470                         conn_header.type = RNT_I_AM_HERE;
1471                         conn_header.seq = (ushort)(~CONNECTSEQ);
1472                         conn_header.data_len = 0;
1473                         Last_sent_iamhere = psnet_get_time();
1474                         int ret = SOCKET_ERROR;
1475                         switch ( Reliable_sockets[Serverconn].connection_type ) {
1476                         case NET_IPX:
1477                                 if(!Ipx_active){
1478                                         ml_printf("Unable to use this network connection type in nw_WorkReliable()\n");
1479                                         Int3();
1480                                         return;
1481                                 }
1482                                 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1483                                 break;
1484                         case NET_TCP:
1485                                 if(!Tcp_active){
1486                                         ml_printf("Unable to use this network connection type in nw_WorkReliable()\n");
1487                                         Int3();
1488                                         return;
1489                                 }
1490                                 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1491                                 break;
1492                         default:
1493                                 ml_printf("Unknown protocol type in nw_WorkReliable()!\n");
1494                                 Int3();
1495                                 break;
1496                         }
1497                                 
1498                         if((ret == SOCKET_ERROR) && (WSAEWOULDBLOCK == WSAGetLastError())){
1499                                 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time()-NETRETRYTIME;
1500                         } else {
1501                                 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time();
1502                         }
1503                 }
1504         }
1505
1506         ubyte link_type;
1507         net_addr_t d3_rcv_addr;
1508         struct sockaddr_in *rcvaddr;
1509         int ipx_has_data = 0;
1510         int udp_has_data = 0;
1511         do {            
1512                 rsocket = NULL;
1513                 //Check IPX and UDP
1514                 if(Ipx_active && (Socket_type == NET_IPX)){
1515                         FD_ZERO(&read_fds);
1516                         FD_SET(Unreliable_socket, &read_fds);    
1517 #ifndef PLAT_UNIX                       
1518                         ipx_has_data = SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1519 #else
1520                         ipx_has_data = SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1521 #endif                  
1522                 }
1523                 if(Tcp_active && (Socket_type == NET_TCP)){
1524                         FD_ZERO(&read_fds);
1525                         FD_SET(Unreliable_socket, &read_fds);
1526 #ifndef PLAT_UNIX                       
1527                         udp_has_data = SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1528 #else
1529                         udp_has_data = SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1530 #endif                  
1531                 }
1532                 bytesin = 0;
1533                 addrlen = sizeof(struct sockaddr);
1534                 if(ipx_has_data){
1535 #ifndef PLAT_UNIX
1536                         SOCKADDR_IPX *ipx_addr = (SOCKADDR_IPX *)&rcv_addr;
1537                         memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1538                         memset(&rcv_addr,0,sizeof(struct sockaddr));
1539                         bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header),0,(struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1540                         memcpy(d3_rcv_addr.addr, ipx_addr->sa_nodenum, 6);
1541                         memcpy(d3_rcv_addr.net_id, ipx_addr->sa_netnum, 4);                             
1542                         d3_rcv_addr.type = NET_IPX;
1543                         link_type = NET_IPX;
1544 #endif
1545                 } else if(udp_has_data){
1546                         struct sockaddr_in *tcp_addr = (struct sockaddr_in *)&rcv_addr;
1547                         memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1548                         memset(&rcv_addr,0,sizeof(struct sockaddr));
1549                         bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header), 0, (struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1550                         rcv_buff.seq = INTEL_SHORT( rcv_buff.seq );
1551                         rcv_buff.data_len = INTEL_SHORT( rcv_buff.data_len );
1552                         rcv_buff.send_time = INTEL_FLOAT( rcv_buff.send_time );
1553                         memcpy(d3_rcv_addr.addr, &tcp_addr->sin_addr.s_addr, 4);
1554                         d3_rcv_addr.port = tcp_addr->sin_port;
1555                         d3_rcv_addr.type = NET_TCP;
1556                         link_type = NET_TCP;
1557                 } else {
1558                         //Neither socket had data waiting
1559                         break;
1560                 }               
1561
1562                 if(bytesin==-1){
1563                         ml_printf("recvfrom returned an error! -- %d\n",WSAGetLastError());
1564                         //Int3();//See Kevin                    
1565                         return;
1566                 }
1567                 if(bytesin){
1568                         //Someone wants to connect, so find a slot
1569                         if(rcv_buff.type == RNT_REQ_CONN){
1570                                 for(i=1; i<MAXRELIABLESOCKETS; i++){
1571                                         if( (Reliable_sockets[i].status == RNF_CONNECTED) || (Reliable_sockets[i].status == RNF_LIMBO) ){
1572                                                 //if(memcmp(&rcv_addr,&reliable_sockets[i].addr,sizeof(struct sockaddr))==0)
1573                                                 if(memcmp(&d3_rcv_addr, &Reliable_sockets[i].net_addr, sizeof(net_addr_t)) == 0){
1574                                                         //We already have a reliable link to this user, so we will ignore it...
1575                                                         ml_printf("Received duplicate connection request. %d\n",i);
1576                                                         //reliable_sockets[i].last_packet_received = timer_GetTime();
1577                                                         psnet_rel_send_ack(&Reliable_sockets[i].addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1578                                                         //We will change this as a hack to prevent later code from hooking us up
1579                                                         rcv_buff.type = 0xff;
1580                                                         continue;
1581                                                 }
1582                                         }
1583                                 }
1584                                 for(i=1; i<MAXRELIABLESOCKETS; i++){
1585                                         if(Reliable_sockets[i].status == RNF_UNUSED){
1586                                                 //Add the new connection here.
1587                                                 Reliable_sockets[i].connection_type=link_type;
1588                                                 memcpy(&Reliable_sockets[i].net_addr, &d3_rcv_addr, sizeof(net_addr_t));
1589                                                 memcpy(&Reliable_sockets[i].addr ,&rcv_addr, sizeof(struct sockaddr));
1590                                                 Reliable_sockets[i].ping_pos = 0;
1591                                                 Reliable_sockets[i].num_ping_samples = 0;
1592                                                 Reliable_sockets[i].status = RNF_LIMBO;
1593                                                 Reliable_sockets[i].last_packet_received = psnet_get_time();
1594                                                 rsocket = &Reliable_sockets[i];
1595                                                 rcvaddr = (struct sockaddr_in *)&rcv_addr;
1596                                                 ml_printf("Connect from %s:%d\n", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port));
1597                                                 break;
1598                                         }
1599                                 }
1600                                 if(i==MAXRELIABLESOCKETS){
1601                                         //No more connections!
1602                                         ml_printf("Out of incoming reliable connection sockets\n");
1603                                         //Int3();//See Kevin
1604                                         continue;
1605                                 }
1606                                 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);                        
1607                         }
1608                         
1609                         //Find out if this is a packet from someone we were expecting a packet.
1610                         rcvaddr = (struct sockaddr_in *)&rcv_addr;
1611                         for(i=1; i<MAXRELIABLESOCKETS; i++){
1612                                 if(memcmp(&d3_rcv_addr,&Reliable_sockets[i].net_addr,sizeof(net_addr_t)) == 0){
1613                                         rsocket=&Reliable_sockets[i];
1614                                         break;
1615                                 }                               
1616                         }
1617                         if(rsocket == NULL){
1618                                 ml_printf("Received reliable data from unconnected client.\n");
1619                                 ml_printf("Received from %s:%d\n",inet_ntoa(rcvaddr->sin_addr),rcvaddr->sin_port);
1620                                 continue ;
1621                         }
1622                         rsocket->last_packet_received = psnet_get_time();
1623                         
1624                         if(rsocket->status != RNF_CONNECTED){
1625                                 //Get out of limbo
1626                                 if(rsocket->status == RNF_LIMBO){
1627                                         //this is our connection to the server
1628                                         if(Serverconn != 0xffffffff){
1629                                                 if(rcv_buff.type == RNT_ACK){
1630                                                         ushort *acknum = (ushort *)&rcv_buff.data;
1631                                                         if(*acknum == (~CONNECTSEQ & 0xffff)){
1632                                                                 rsocket->status = RNF_CONNECTED;
1633                                                                 ml_printf("Got ACK for IAMHERE!\n");
1634                                                         }
1635                                                         continue;
1636                                                 }
1637                                         } else if(rcv_buff.type == RNT_I_AM_HERE){
1638                                                 rsocket->status = RNF_CONNECTING;
1639                                                 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);                
1640                                                 ml_printf("Got IAMHERE!\n");
1641                                                 continue;
1642                                         }
1643                                 }
1644                                 if((rcv_buff.type == RNT_DATA) && (Serverconn != 0xffffffff)){
1645                                         rsocket->status = RNF_CONNECTED;
1646                                 } else {                                        
1647                                         rsocket->last_packet_received = psnet_get_time();
1648                                         continue;
1649                                 }                               
1650                         }
1651                         //Update the last recv variable so we don't need a heartbeat
1652                         rsocket->last_packet_received = psnet_get_time();
1653
1654                         if(rcv_buff.type == RNT_HEARTBEAT){
1655                                 continue;
1656                         }
1657                         if(rcv_buff.type == RNT_ACK){
1658                                 //Update ping time
1659                                 rsocket->num_ping_samples++;
1660                                 
1661                                 rsocket->pings[rsocket->ping_pos] = rsocket->last_packet_received - rcv_buff.send_time;                         
1662                                 if(rsocket->num_ping_samples >= MAX_PING_HISTORY){
1663                                         float sort_ping[MAX_PING_HISTORY];
1664                                         for(int a=0;a<MAX_PING_HISTORY;a++){
1665                                                 sort_ping[a] = rsocket->pings[a];
1666                                         }
1667
1668                                         qsort(sort_ping ,MAX_PING_HISTORY, sizeof(float), psnet_rel_ping_compare);
1669                                         rsocket->mean_ping = ((sort_ping[MAX_PING_HISTORY/2]+sort_ping[(MAX_PING_HISTORY/2)+1]))/2;                                     
1670                                 }
1671                                 rsocket->ping_pos++;
1672                                 if(rsocket->ping_pos >= MAX_PING_HISTORY){
1673                                         rsocket->ping_pos=0;                            
1674                                 }
1675
1676                                 // if this is an ack for a send buffer on the socket, kill the send buffer. its done
1677                                 for(i=0; i<MAXNETBUFFERS; i++){
1678                                         unsigned int *acksig = (unsigned int *)&rcv_buff.data;
1679                                         if(rsocket){
1680                                                 if(rsocket->sbuffers[i]){
1681                                                         if(rsocket->ssequence[i] == INTEL_INT(*acksig) ){                                                               
1682                                                                 SDL_assert(rsocket->sbuffers[i] != NULL);
1683                                                                 free(rsocket->sbuffers[i]);
1684                                                                 rsocket->sbuffers[i] = NULL;    
1685                                                                 rsocket->ssequence[i] = 0;
1686                                                         }
1687                                                 }
1688                                         }
1689                                 }
1690                                 //remove that packet from the send buffer
1691                                 rsocket->last_packet_received = psnet_get_time();
1692                                 continue;
1693                         }
1694
1695                         if(rcv_buff.type == RNT_DATA_COMP){
1696                                 //More2Come
1697                                 //Decompress it. Put it back in the buffer. Process it as RNT_DATA
1698                                 rcv_buff.type = RNT_DATA;
1699                         }
1700                         if(rcv_buff.type == RNT_DATA){                          
1701                                 //If the data is out of order by >= MAXNETBUFFERS-1 ignore that packet for now
1702                                 int seqdelta;
1703                                 seqdelta = rcv_buff.seq - rsocket->oursequence;
1704                                 if(seqdelta<0) seqdelta = seqdelta*-1;
1705                                 if(seqdelta>=MAXNETBUFFERS - 1){
1706                                         ml_printf("Received reliable packet out of order!\n");
1707                                         //It's out of order, so we won't ack it, which will mean we will get it again soon.
1708                                         continue;
1709                                 }
1710                                 //else move data into the proper buffer position
1711                                 int savepacket=1;
1712                                 
1713                                 if(rsocket->oursequence < (0xffff - (MAXNETBUFFERS-1))){
1714                                         if (rsocket->oursequence > rcv_buff.seq){
1715                                                 savepacket = 0;
1716                                         }
1717                                 } else {
1718                                         //Sequence is high, so prepare for wrap around
1719                                         if( ((unsigned short)(rcv_buff.seq + rsocket->oursequence)) > (MAXNETBUFFERS-1)){
1720                                                 savepacket = 0; 
1721                                         }
1722                                 }
1723
1724                                 for(i=0; i<MAXNETBUFFERS; i++){
1725                                         if( (NULL != rsocket->rbuffers[i]) && (rsocket->rsequence[i] == rcv_buff.seq)){
1726                                                 //Received duplicate packet!                                            
1727                                                 savepacket = 0;
1728                                         }
1729                                 }
1730                                 if(savepacket){
1731                                         for(i=0; i<MAXNETBUFFERS; i++){
1732                                                 if(NULL == rsocket->rbuffers[i]){                                                       
1733                                                         if(rcv_buff.data_len>max_len){
1734                                                                 rsocket->recv_len[i] = rcv_buff.data_len;
1735                                                         } else {
1736                                                                 rsocket->recv_len[i] = rcv_buff.data_len; 
1737                                                         }
1738                                                         rsocket->rbuffers[i] = (reliable_net_rcvbuffer *)malloc(sizeof(reliable_net_rcvbuffer));
1739                                                         memcpy(rsocket->rbuffers[i]->buffer,rcv_buff.data,rsocket->recv_len[i]);        
1740                                                         rsocket->rsequence[i] = rcv_buff.seq;                                                   
1741                                                         break;
1742                                                 }
1743                                         }
1744                                 }
1745                                 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);                
1746                         }
1747                         
1748                 }
1749         } while((ipx_has_data>0) || (udp_has_data>0));
1750         
1751         // Go through each reliable socket that is connected and do any needed work.
1752         for(j=0; j<MAXRELIABLESOCKETS; j++){
1753                 rsocket=&Reliable_sockets[j];
1754
1755                 if(Serverconn == 0xffffffff){
1756                         if(rsocket->status==RNF_LIMBO){
1757                                 if(fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout){
1758                                         ml_printf("Reliable (but in limbo) socket (%d) timed out in nw_WorkReliable().\n",j);
1759                                         memset(rsocket,0,sizeof(reliable_socket));
1760                                         rsocket->status = RNF_UNUSED;//Won't work if this is an outgoing connection.
1761                                 }
1762                         }
1763                 } else {
1764                         if((rsocket->status == RNF_LIMBO) && (fl_abs((psnet_get_time() - First_sent_iamhere)) > Nettimeout)){
1765                                 rsocket->status = RNF_BROKEN;
1766                                 ml_printf("Reliable socket (%d) timed out in nw_WorkReliable().\n",j);
1767                         }
1768                 }
1769                 
1770                 if(rsocket->status == RNF_CONNECTED){
1771                         float retry_packet_time;
1772                         if((rsocket->mean_ping==0) || (rsocket->mean_ping > (NETRETRYTIME*4))){
1773                                 retry_packet_time = NETRETRYTIME;
1774                         } else {
1775                                 if(rsocket->mean_ping<MIN_NET_RETRYTIME) {
1776                                         retry_packet_time = (float)MIN_NET_RETRYTIME;                                   
1777                                 } else {
1778                                         retry_packet_time = ((float)(float)rsocket->mean_ping * (float)1.25);                                   
1779                                 }
1780                         }
1781                         //Iterate through send buffers.  
1782                         for(i=0;i<MAXNETBUFFERS;i++){
1783                                 // send again
1784                                 if((rsocket->sbuffers[i]) && (fl_abs((psnet_get_time() - rsocket->timesent[i])) >= retry_packet_time)) {
1785                                         reliable_header send_header;                                    
1786                                         send_header.send_time = psnet_get_time();
1787                                         send_header.send_time = INTEL_FLOAT( send_header.send_time );
1788                                         send_header.seq = INTEL_SHORT( rsocket->ssequence[i] );
1789                                         memcpy(send_header.data,rsocket->sbuffers[i]->buffer,rsocket->send_len[i]);
1790                                         send_header.data_len = INTEL_SHORT( (ushort)rsocket->send_len[i] );
1791                                         send_header.type = RNT_DATA;
1792                                         if(rsocket->connection_type == NET_TCP){
1793                                                 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1794                                         } else if(rsocket->connection_type == NET_IPX){
1795                                                 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1796                                         }
1797                                         if((rcode == SOCKET_ERROR) && (WSAEWOULDBLOCK == WSAGetLastError())){
1798                                                 //The packet didn't get sent, flag it to try again next frame
1799                                                 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1800                                         } else {
1801                                                 rsocket->last_packet_sent = psnet_get_time();
1802                                                 rsocket->timesent[i] = psnet_get_time();
1803                                         }
1804                                         
1805                                 }//getcwd
1806                         }
1807
1808                         if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_sent)) > NETHEARTBEATTIME)) {
1809                                 reliable_header send_header;                            
1810                                 send_header.send_time = psnet_get_time();
1811                                 send_header.send_time = INTEL_FLOAT( send_header.send_time );
1812                                 send_header.seq = 0;
1813                                 send_header.data_len = 0;
1814                                 send_header.type = RNT_HEARTBEAT;
1815
1816                                 rcode = -1;
1817                                 if(rsocket->connection_type == NET_TCP){
1818                                         rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1819                                 } else if(rsocket->connection_type == NET_IPX){
1820                                         rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1821                                 }
1822                                 if((rcode != SOCKET_ERROR) && (WSAEWOULDBLOCK != WSAGetLastError())){
1823                                         //It must have been sent
1824                                         rsocket->last_packet_sent = psnet_get_time();
1825                                 }
1826                         }
1827
1828                         if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout)){
1829                                 //This socket is hosed.....inform someone?
1830                                 ml_printf("Reliable Socket (%d) timed out in nw_WorkReliable().\n",j);
1831                                 rsocket->status = RNF_BROKEN;
1832                         }
1833                 }
1834         }       
1835 }
1836
1837 // get the status of a reliable socket, see RNF_* defines above
1838 int psnet_rel_get_status(PSNET_SOCKET_RELIABLE socketid)
1839 {       
1840         if(socketid >= MAXRELIABLESOCKETS){             
1841                 return -1;
1842         }
1843
1844         return Reliable_sockets[socketid].status;
1845 }
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         struct sockaddr_in *ip_addr;                            // UDP/TCP socket structure
1852 #ifndef PLAT_UNIX
1853         SOCKADDR_IPX *ipx_addr;                 // IPX socket structure 
1854 #endif
1855         
1856         psnet_rel_work();
1857         int i;
1858         for(i=1; i<MAXRELIABLESOCKETS; i++){
1859                 if(Reliable_sockets[i].status == RNF_CONNECTING){
1860                         Reliable_sockets[i].status = RNF_CONNECTED;
1861                         //memcpy(from_addr,&reliable_sockets[i].addr,sizeof(struct sockaddr));
1862                         ml_printf("New reliable connection in nw_CheckListenSocket().\n");
1863                         
1864                         switch ( Reliable_sockets[i].connection_type ){
1865                         case NET_IPX:
1866 #ifndef PLAT_UNIX
1867                                 ipx_addr = (SOCKADDR_IPX *)&Reliable_sockets[i].addr;
1868                                 memset(from_addr, 0x00, sizeof(net_addr_t));
1869                                 from_addr->port = ntohs( ipx_addr->sa_socket );
1870                                 from_addr->type = NET_IPX;
1871                                 memcpy(from_addr->addr, ipx_addr->sa_nodenum, 6 );
1872                                 memcpy(from_addr->net_id, ipx_addr->sa_netnum, 4 );
1873 #endif
1874                                 break;
1875
1876                         case NET_TCP:
1877                                 ip_addr = (struct sockaddr_in *)&Reliable_sockets[i].addr;
1878                                 memset(from_addr, 0x00, sizeof(net_addr_t));
1879                                 from_addr->port = ntohs( ip_addr->sin_port );
1880                                 from_addr->type = NET_TCP;
1881 #ifndef PLAT_UNIX
1882                                 memcpy(from_addr->addr, &ip_addr->sin_addr.S_un.S_addr, 4);
1883 #else
1884                                 memcpy(from_addr->addr, &ip_addr->sin_addr.s_addr, 4);
1885 #endif
1886                                 break;
1887                         
1888                         default:
1889                                 Int3();
1890                                 break;
1891                         }
1892                         /*
1893                         char dbg_output[50];
1894                         nw_GetNumbersFromHostAddress(from_addr,dbg_output);
1895                         mprintf((0,"Got address from: %s\n",dbg_output));
1896                         */
1897                         return i;
1898                 }
1899         }
1900         return INVALID_SOCKET;  
1901 }
1902
1903 // attacmpt to connect() to the server's tcp socket.  socket parameter is simply assigned to the
1904 // Reliable_socket socket created in psnet_init
1905 void psnet_rel_connect_to_server(PSNET_SOCKET *socket, net_addr_t *server_addr)
1906 {       
1907         //Send out a RNT_REQ_CONN packet, and wait for it to be acked.
1908         struct sockaddr_in sockaddr;                            // UDP/TCP socket structure
1909 #ifndef PLAT_UNIX
1910         SOCKADDR_IPX ipx_addr;                          // IPX socket structure
1911 #endif
1912         struct sockaddr *addr = NULL;                                           // pointer to struct sockaddr to make coding easier
1913         struct sockaddr rcv_addr;
1914         int addrlen;
1915         ubyte iaddr[6];
1916         ushort port;
1917 //      float time_sent_req = 0;
1918         float first_sent_req = 0;
1919         static reliable_header conn_header;
1920         static reliable_header ack_header;
1921         int bytesin;
1922         struct timeval timeout;
1923         fd_set read_fds;
1924         int i;
1925         *socket = INVALID_SOCKET;       
1926         
1927         memset(iaddr, 0x00, 6);
1928         memcpy(iaddr, &server_addr->addr, 6);
1929         port = (ushort)(server_addr->port);     // Talk to the server listen port
1930         
1931         conn_header.type = RNT_REQ_CONN;
1932         conn_header.seq = CONNECTSEQ;
1933         conn_header.data_len = 0;
1934         
1935         timeout.tv_sec=0;            
1936         timeout.tv_usec=0;
1937
1938         if((server_addr->type == NET_IPX) && (!Ipx_active)){
1939                 return;
1940         }
1941         if((server_addr->type == NET_TCP) && (!Tcp_active)){
1942                 return;
1943         }
1944         //Flush out any left overs
1945         if(Tcp_active && (Socket_type == NET_TCP)){
1946                 FD_ZERO(&read_fds);
1947                 FD_SET(Unreliable_socket, &read_fds);    
1948 #ifndef PLAT_UNIX               
1949                 while(SELECT(0, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE)){
1950 #else
1951                 while(SELECT(Unreliable_socket+1, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE)){               
1952 #endif          
1953                         addrlen = sizeof(struct sockaddr);
1954                         bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1955                         if(bytesin==-1){
1956                                 //Int3();//See Kevin
1957                                 ml_printf("UDP recvfrom returned an error! -- %d\n",WSAGetLastError());
1958                                 break;
1959                                 //return;
1960                         }
1961                         FD_ZERO(&read_fds);
1962                         FD_SET(Unreliable_socket, &read_fds);    
1963                 }
1964         }
1965         if(Ipx_active && (Socket_type == NET_IPX)){
1966                 FD_ZERO(&read_fds);
1967                 FD_SET(Unreliable_socket, &read_fds);    
1968 #ifndef PLAT_UNIX               
1969                 while(SELECT(0, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE))
1970 #else
1971                 while(SELECT(Unreliable_socket+1, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE))                
1972 #endif          
1973                 {
1974                         addrlen = sizeof(struct sockaddr);
1975                         bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1976                         if(bytesin==-1)
1977                         {
1978                                 //Int3();//See Kevin
1979                                 ml_printf("IPX recvfrom returned an error! -- %d\n",WSAGetLastError());
1980                                 break;
1981                         }
1982                         FD_ZERO(&read_fds);
1983                         FD_SET(Unreliable_socket, &read_fds);    
1984                 }
1985         }
1986         memset(&ack_header,0,sizeof(reliable_header));
1987         bytesin = 0;
1988         SOCKET typeless_sock = 0;
1989         net_addr_t d3_rcv_addr;
1990         memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1991
1992         switch ( server_addr->type ){
1993                 case NET_IPX:
1994 #ifndef PLAT_UNIX
1995                         ipx_addr.sa_family = AF_IPX;
1996                         memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1997                         memcpy(ipx_addr.sa_netnum, server_addr->net_id, 4);
1998                         ipx_addr.sa_socket = htons(port);
1999                         addr = (struct sockaddr *)&ipx_addr;
2000                         if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE) ){
2001                                 ml_printf("Unable to send IPX packet in nw_ConnectToServer()! -- %d\n",WSAGetLastError());
2002                                 return;
2003                         }
2004                         typeless_sock = Unreliable_socket;
2005                         memcpy(d3_rcv_addr.addr,ipx_addr.sa_nodenum, 6);
2006                         memcpy(d3_rcv_addr.net_id,ipx_addr.sa_netnum, 4);                               
2007                         d3_rcv_addr.type = NET_IPX;
2008 #endif
2009                         break;
2010                 case NET_TCP:
2011                         sockaddr.sin_family = AF_INET; 
2012                         memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
2013                         sockaddr.sin_port = htons(port); 
2014                         addr = (struct sockaddr *)&sockaddr;
2015                         if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE) ){
2016                                 ml_printf("Unable to send UDP packet in nw_ConnectToServer()! -- %d\n",WSAGetLastError());
2017                                 return;
2018                         }
2019                         memcpy(d3_rcv_addr.addr, &sockaddr.sin_addr.s_addr, 4);
2020                         d3_rcv_addr.port = sockaddr.sin_port;
2021                         d3_rcv_addr.type = NET_TCP;
2022                         typeless_sock = Unreliable_socket;
2023                         break;
2024
2025                 default:
2026                         ml_printf("Network","Unknown protocol type in nw_ConnectToServer()!\n");
2027                         Int3();
2028                         return;
2029         }               
2030
2031         
2032         first_sent_req = psnet_get_time();
2033 //      time_sent_req = psnet_get_time();
2034         
2035         //Wait until we get a response from the server or we timeout
2036         
2037         do {
2038                 PSNET_TOP_LAYER_PROCESS();
2039
2040                 FD_ZERO(&read_fds);
2041                 FD_SET(typeless_sock, &read_fds);
2042 #ifndef PLAT_UNIX               
2043                 if(SELECT(0, &read_fds, NULL,NULL,&timeout, PSNET_TYPE_RELIABLE)){
2044 #else
2045                 if(SELECT(typeless_sock+1, &read_fds, NULL,NULL,&timeout, PSNET_TYPE_RELIABLE)){
2046 #endif          
2047                         ml_string("selected() in psnet_rel_connect_to_server()");
2048
2049                         addrlen = sizeof(struct sockaddr);
2050                         bytesin = RECVFROM(typeless_sock,(char *)&ack_header,sizeof(reliable_header),0,(struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
2051                         if(bytesin==-1){
2052                                 ml_printf("recvfrom returned an error! -- %d\n",WSAGetLastError());
2053                                 Int3();//See Kevin
2054                                 return;                         
2055                         }
2056                         
2057                         ml_string("received data after select in psnet_rel_connect_to_server()");
2058                         if(bytesin){    
2059                                 ml_string("about to check ack_header.type");
2060                                 if(ack_header.type == RNT_ACK){
2061                                         short *acknum = (short *)&ack_header.data;
2062                                         if(*acknum == CONNECTSEQ){                                              
2063                                                 for(i=1; i<MAXRELIABLESOCKETS; i++){
2064                                                         if(Reliable_sockets[i].status==RNF_UNUSED){
2065                                                                 //Add the new connection here.
2066                                                                 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
2067                                                                 Reliable_sockets[i].connection_type = (ubyte)server_addr->type;
2068                                                                 memcpy(&Reliable_sockets[i].net_addr,&d3_rcv_addr,sizeof(net_addr_t));
2069                                                                 Reliable_sockets[i].last_packet_received = psnet_get_time();
2070                                                                 memcpy(&Reliable_sockets[i].addr,&rcv_addr,sizeof(struct sockaddr));
2071                                                                 Reliable_sockets[i].status = RNF_LIMBO;
2072                                                                 *socket = i;
2073                                                                 ml_printf("Succesfully connected to server in nw_ConnectToServer().\n");
2074                                                                 //Now send I_AM_HERE packet
2075                                                                 conn_header.type = RNT_I_AM_HERE;
2076                                                                 conn_header.seq = (ushort)(~CONNECTSEQ);
2077                                                                 conn_header.data_len = 0;
2078                                                                 Serverconn = i;
2079                                                                 First_sent_iamhere = psnet_get_time();
2080                                                                 Last_sent_iamhere = psnet_get_time();
2081                                                                 int rcode = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
2082                                                                 if(rcode == SOCKET_ERROR){
2083                                                                         *socket = INVALID_SOCKET;
2084                                                                         Reliable_sockets[i].status = RNF_UNUSED;
2085                                                                         memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
2086                                                                         ml_printf("Unable to send packet in nw_ConnectToServer()\n");
2087                                                                         return;
2088                                                                 }
2089                                                                 Reliable_sockets[i].last_packet_sent = psnet_get_time();
2090                                                                 float f;
2091                                                                 f = psnet_get_time();
2092                                                                 while((fl_abs((psnet_get_time() - f))<2) && (Reliable_sockets[i].status != RNF_CONNECTING)){
2093                                                                         psnet_rel_work();
2094                                                                 }
2095                                                                         
2096                                                                 return;
2097                                                         }
2098                                                 }
2099                                                 ml_printf("Out of reliable socket space in nw_ConnectToServer().\n");
2100                                                 return;                                         
2101                                         } else ml_printf("Received out of sequence ACK in nw_ConnectToServer().\n");
2102                                 } else ml_printf("Received something that isn't an ACK in nw_ConnectToServer().\n");
2103                         } else ml_printf("Received 0 bytes from recvfrom() in nw_ConnectToServer().\n");
2104                 }
2105                 /*
2106                 if((psnet_get_time()-time_sent_req)>2)
2107                 {
2108                         ml_printf("Resending connect request.\n");
2109                         int ret = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
2110                         if(ret != SOCKET_ERROR){
2111                                 time_sent_req = psnet_get_time();
2112                         } else {
2113                                 ml_printf("Error sending connection request! -- %d\n",WSAGetLastError() );
2114                         }
2115                 }
2116                 */
2117
2118         } while(fl_abs((psnet_get_time() - first_sent_req)) < RELIABLE_CONNECT_TIME);   
2119 }
2120
2121 // returns the ip address of this computer
2122 /*
2123 int psnet_rel_get_ip()
2124 {
2125         char local[255];
2126         LPHOSTENT hostent;
2127         struct sockaddr_in local_address;
2128         int ret;
2129         
2130         // Get the local host name
2131         memset(&local_address, 0, sizeof(local_address));
2132         ret = gethostname(local, 255 );
2133         if (ret != SOCKET_ERROR ){
2134                 // Resolve host name for local address
2135                 hostent = gethostbyname((char *)local);
2136                 if ( hostent ){
2137                         local_address.sin_addr.s_addr = *((u_long FAR *)(hostent->h_addr));
2138                 }
2139         } else {
2140                 ml_string("SOCKET_ERROR in psnet_rel_get_ip()!");
2141         }
2142         ml_printf(%s:%d\n", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port)
2143         return local_address.sin_addr.s_addr;
2144 }
2145 */
2146
2147 // returns the ip address of this computer
2148 int psnet_get_ip()
2149 {       
2150         struct sockaddr_in local_address;
2151
2152         if(Psnet_connection == NETWORK_CONNECTION_DIALUP){      
2153                 local_address.sin_addr.s_addr = psnet_ras_status();
2154                 if(local_address.sin_addr.s_addr == INADDR_NONE){
2155                         local_address.sin_addr.s_addr = INADDR_ANY;
2156                 }
2157         } else {
2158                 // Init local address to zero
2159                 local_address.sin_addr.s_addr = INADDR_ANY;                     
2160         }
2161
2162         // NOTE: for memeory checkers, do NOT try to free this
2163         ml_printf("psnet_get_ip() reports IP : %s\n", inet_ntoa(local_address.sin_addr));
2164         
2165         return local_address.sin_addr.s_addr;
2166 }
2167
2168 // initialize reliable sockets
2169 int psnet_init_rel_tcp(int port, int should_listen)
2170 {
2171         /*
2172         struct sockaddr_in sockaddr;
2173
2174         sockaddr.sin_port = htons((ushort)port);
2175         sockaddr.sin_family = AF_INET; 
2176         unsigned int my_ip;
2177         ml_printf("Setting up reliable sockets.\n");
2178
2179         my_ip = psnet_get_ip();
2180
2181         memcpy(&sockaddr.sin_addr.s_addr, &my_ip, sizeof(uint));        
2182                         
2183         Reliable_UDP_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP );
2184         if(INVALID_SOCKET == Reliable_UDP_socket){
2185                 ml_printf("Unable to create reliable UDP socket -- %d\n", WSAGetLastError() );
2186                 
2187                 return 0;
2188         } else if(bind(Reliable_UDP_socket,(struct sockaddr *)&sockaddr,sizeof(struct sockaddr))!=0){
2189                 ml_printf("Unable to bind reliable socket -- %d\n", WSAGetLastError() );
2190                 
2191                 return 0;
2192         }       
2193         
2194         // make any reliable sockets which we create that aren't listening non-blocking sockets
2195         int error;
2196         unsigned long arg;
2197
2198         arg = TRUE;
2199         error = ioctlsocket( Reliable_UDP_socket, FIONBIO, &arg );
2200         if ( error == SOCKET_ERROR ) {
2201                 ml_printf("Unable to make reliable UDP socket non-blocking -- %d\n", WSAGetLastError() );
2202                 
2203                 return 0;
2204         }
2205         */      
2206
2207         // success
2208         return 1;
2209 }
2210
2211 // initialize reliable sockets
2212 int psnet_init_rel_ipx(int port, int should_listen)
2213 {       
2214 #ifdef PLAT_UNIX
2215         return 0;
2216 #else
2217         /*
2218         SOCKADDR_IPX ipx_addr;          
2219
2220         memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
2221         ipx_addr.sa_family = AF_IPX;
2222         ipx_addr.sa_socket = htons((ushort)port);
2223                                 
2224         Reliable_IPX_socket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
2225         if(INVALID_SOCKET == Reliable_IPX_socket){
2226                 ml_printf("Unable to create reliable IPX socket -- %d\n", WSAGetLastError() );
2227                 
2228                 return 0;
2229         } else if(bind(Reliable_IPX_socket,(struct sockaddr *)&ipx_addr,sizeof(struct sockaddr))!=0){
2230                 ml_printf("Unable to bind reliable IPX socket -- %d\n", WSAGetLastError() );
2231                 
2232                 return 0;
2233         }       
2234         
2235         // make any reliable sockets which we create that aren't listening non-blocking sockets
2236         int error;
2237         unsigned long arg;
2238
2239         arg = TRUE;
2240         error = ioctlsocket( Reliable_IPX_socket, FIONBIO, &arg );
2241         if ( error == SOCKET_ERROR ) {
2242                 ml_printf("Unable to make reliable IPX socket non-blocking -- %d\n", WSAGetLastError() );
2243                 
2244                 return 0;
2245         }
2246         */      
2247
2248         // success
2249         return 1;
2250 #endif
2251 }
2252
2253 void psnet_rel_close()
2254 {
2255         int idx;
2256         PSNET_SOCKET_RELIABLE sock;
2257
2258         // kill all sockets
2259         for(idx=0; idx<MAXRELIABLESOCKETS; idx++){
2260                 if(Reliable_sockets[idx].status != RNF_UNUSED){
2261                         sock = idx;
2262                         psnet_rel_close_socket(&sock);
2263                 }
2264         }
2265 }
2266
2267 // ------------------------------------------------------------------------------------------------------
2268 // PACKET BUFFERING FUNCTIONS
2269 //
2270
2271 // initialize the buffering system
2272 void psnet_buffer_init(network_packet_buffer_list *l)
2273 {
2274         int idx;
2275         
2276         // blast the buffer clean
2277         memset(l->psnet_buffers, 0, sizeof(network_packet_buffer) * MAX_PACKET_BUFFERS);
2278         
2279         // set all buffer sequence #'s to -1
2280         for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){                
2281                 l->psnet_buffers[idx].sequence_number = -1;
2282         }
2283
2284         // initialize the sequence #
2285         l->psnet_seq_number = 0;
2286         l->psnet_lowest_id = -1;
2287         l->psnet_highest_id = -1;
2288 }
2289
2290 // buffer a packet (maintain order!)
2291 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr_t *from)
2292 {
2293         int idx;
2294         int found_buf = 0;
2295         
2296         // find the first empty packet
2297         for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2298                 if(l->psnet_buffers[idx].sequence_number == -1){
2299                         found_buf = 1;
2300                         break;
2301                 }
2302         }
2303
2304         // if we didn't find the buffer, report an overrun
2305         if(!found_buf){
2306                 ml_printf("WARNING - Buffer overrun in psnet\n");
2307         } else {
2308                 // copy in the data
2309                 memcpy(l->psnet_buffers[idx].data, data, length);
2310                 l->psnet_buffers[idx].len = length;
2311                 memcpy(&l->psnet_buffers[idx].from_addr, from, sizeof(net_addr_t));
2312                 l->psnet_buffers[idx].sequence_number = l->psnet_seq_number;
2313                 
2314                 // keep track of the highest id#
2315                 l->psnet_highest_id = l->psnet_seq_number++;
2316
2317                 // set the lowest id# for the first time
2318                 if(l->psnet_lowest_id == -1){
2319                         l->psnet_lowest_id = l->psnet_highest_id;
2320                 }
2321         }
2322 }
2323
2324 // get the index of the next packet in order!
2325 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr_t *from)
2326 {       
2327         int idx;
2328         int found_buf = 0;
2329
2330         // if there are no buffers, do nothing
2331         if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
2332                 return 0;
2333         }
2334
2335         // search until we find the lowest packet index id#
2336         for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2337                 // if we found the buffer
2338                 if(l->psnet_buffers[idx].sequence_number == l->psnet_lowest_id){
2339                         found_buf = 1;
2340                         break;
2341                 }
2342         }
2343
2344         // at this point, we should _always_ have found the buffer
2345         SDL_assert(found_buf);  
2346         
2347         // copy out the buffer data
2348         memcpy(data, l->psnet_buffers[idx].data, l->psnet_buffers[idx].len);
2349         *length = l->psnet_buffers[idx].len;
2350         memcpy(from, &l->psnet_buffers[idx].from_addr, sizeof(net_addr_t));
2351
2352         // now we need to cleanup the packet list
2353
2354         // mark the buffer as free
2355         l->psnet_buffers[idx].sequence_number = -1;
2356         l->psnet_lowest_id++;
2357
2358         return 1;
2359 }
2360
2361 // -------------------------------------------------------------------------------------------------------
2362 // PSNET 2 FORWARD DEFINITIONS
2363 //
2364
2365 // if the string is a legally formatted ip string
2366 int psnet_is_valid_numeric_ip(char *ip)
2367 {
2368         char *token;
2369         char copy[100];
2370         int val1,val2,val3,val4;
2371
2372         // get the first ip value
2373         SDL_strlcpy(copy, ip, SDL_arraysize(copy));
2374         token = strtok(copy,".");
2375         if(token == NULL){
2376                 return 0;
2377         } else {
2378                 // get the value of the token
2379                 val1 = atoi(token);
2380                 if((val1 < 0) || (val1 > 255)){
2381                         return 0;
2382                 }
2383         }
2384
2385         // second ip value
2386         token = strtok(NULL,".");
2387         if(token == NULL){
2388                 return 0;
2389         } else {
2390                 // get the value of the token
2391                 val2 = atoi(token);
2392                 if((val2 < 0) || (val2 > 255)){
2393                         return 0;
2394                 }
2395         }
2396
2397         // third ip value
2398         token = strtok(NULL,".");
2399         if(token == NULL){
2400                 return 0;
2401         } else {
2402                 // get the value of the token
2403                 val3 = atoi(token);
2404                 if((val3 < 0) || (val3 > 255)){
2405                         return 0;
2406                 }
2407         }
2408
2409         // third ip value
2410         token = strtok(NULL,"");
2411         if(token == NULL){
2412                 return 0;
2413         } else {
2414                 // get the value of the token
2415                 val4 = atoi(token);
2416                 if((val4 < 0) || (val4 > 255)){
2417                         return 0;
2418                 }
2419         }
2420
2421         // make sure he hasn't entered all 0's
2422         if((val1 == 0) && (val2 == 0) && (val3 == 0) && (val4 == 0)){
2423                 return 0;
2424         }
2425
2426         // valid
2427         return 1;
2428 }
2429
2430 // function called from high level FreeSpace code to determine the status of the networking
2431 // code returns one of a handful of macros
2432 #ifndef PLAT_UNIX
2433 DWORD (__stdcall *pRasEnumConnections)(LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections) = NULL;
2434 DWORD (__stdcall *pRasGetConnectStatus)(HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) = NULL;
2435 DWORD (__stdcall *pRasGetProjectionInfo)(HRASCONN hrasconn, RASPROJECTION rasprojection, LPVOID lpprojection, LPDWORD lpcb ) = NULL;
2436
2437 // functions to get the status of a RAS connection
2438 unsigned int psnet_ras_status()
2439 {
2440         int rval;
2441         unsigned long size, num_connections, i;
2442         RASCONN rasbuffer[25];
2443         HINSTANCE ras_handle;
2444         unsigned long rasip=0;
2445         RASPPPIP projection;
2446         // int Ras_connected;
2447
2448         Ras_connected = 0;
2449
2450         // first, call a LoadLibrary to load the RAS api
2451         ras_handle = LoadLibrary( (LPCWSTR)"rasapi32.dll" );
2452         if ( ras_handle == NULL ) {
2453                 return INADDR_ANY;
2454         }
2455
2456         pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, "RasEnumConnectionsA");
2457         if (!pRasEnumConnections)       {
2458                 FreeLibrary( ras_handle );
2459                 return INADDR_ANY;
2460         }
2461         pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, "RasGetConnectStatusA");
2462         if (!pRasGetConnectStatus)      {
2463                 FreeLibrary( ras_handle );
2464                 return INADDR_ANY;
2465         }
2466         pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, "RasGetProjectionInfoA");
2467         if (!pRasGetProjectionInfo)     {
2468                 FreeLibrary( ras_handle );
2469                 return INADDR_ANY;
2470         }
2471
2472         size = sizeof(rasbuffer);
2473         rasbuffer[0].dwSize = sizeof(RASCONN);
2474
2475         rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2476         if ( rval ) {
2477                 FreeLibrary( ras_handle );
2478                 return INADDR_ANY;
2479         }
2480
2481         // JAS: My computer gets to this point, but I have no RAS connections,
2482         // so just exit
2483         if ( num_connections < 1 )      {
2484                 ml_string("Found no RAS connections");
2485                 FreeLibrary( ras_handle );
2486                 return INADDR_ANY;
2487         }
2488
2489         ml_printf("Found %d connections", num_connections);
2490
2491         for (i = 0; i < num_connections; i++ ) {
2492                 RASCONNSTATUS status;
2493                 unsigned long size;
2494
2495                 ml_printf("Connection %d:", i);
2496                 ml_printf("Entry Name: %s", rasbuffer[i].szEntryName);
2497                 ml_printf("Device Type: %s", rasbuffer[i].szDeviceType);
2498                 ml_printf("Device Name: %s", rasbuffer[i].szDeviceName);
2499
2500                 // get the connection status
2501                 status.dwSize = sizeof(RASCONNSTATUS);
2502                 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2503                 if ( rval != 0 ) {
2504                         FreeLibrary( ras_handle );
2505                         return INADDR_ANY;
2506                 }
2507
2508                 // get the projection informatiom
2509                 size = sizeof(projection);
2510                 projection.dwSize = size;
2511                 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2512                 if ( rval != 0 ) {
2513                         FreeLibrary( ras_handle );
2514                         return INADDR_ANY;
2515                 }
2516
2517                 ml_printf("IP Address: %s", projection.szIpAddress);
2518         }
2519
2520         Ras_connected = 1;
2521
2522         FreeLibrary( ras_handle );
2523         rasip = inet_addr((const char *)projection.szIpAddress);
2524         if(rasip==INADDR_NONE){
2525                 return INADDR_ANY;
2526         }
2527
2528         //The ip of the RAS connection
2529         return rasip;
2530 }
2531 #else
2532 unsigned int psnet_ras_status()
2533 {
2534         STUB_FUNCTION;
2535         
2536         return INADDR_ANY;
2537 }
2538 #endif
2539  
2540 // functions to get the status of a RAS connection
2541 /*
2542 void psnet_ras_status()
2543 {
2544         int rval;
2545         unsigned long size, num_connections, i;
2546         RASCONN rasbuffer[25];
2547         HINSTANCE ras_handle;
2548
2549         Ras_connected = 0;
2550
2551         // first, call a LoadLibrary to load the RAS api
2552         ras_handle = LoadLibrary( NOX("rasapi32.dll") );
2553         if ( ras_handle == NULL ) {
2554                 return;
2555         }
2556
2557         pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, NOX("RasEnumConnectionsA"));
2558         if (!pRasEnumConnections)       {
2559                 FreeLibrary( ras_handle );
2560                 return;
2561         }
2562         pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, NOX("RasGetConnectStatusA"));
2563         if (!pRasGetConnectStatus)      {
2564                 FreeLibrary( ras_handle );
2565                 return;
2566         }
2567         pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, NOX("RasGetProjectionInfoA"));
2568         if (!pRasGetProjectionInfo)     {
2569                 FreeLibrary( ras_handle );
2570                 return;
2571         }
2572
2573         size = sizeof(rasbuffer);
2574         rasbuffer[0].dwSize = sizeof(RASCONN);
2575
2576         rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2577         if ( rval ) {
2578                 FreeLibrary( ras_handle );
2579                 return;
2580         }
2581
2582         // JAS: My computer gets to this point, but I have no RAS connections,
2583         // so just exit
2584         if ( num_connections < 1 )      {
2585                 ml_printf("Found no connections\n" ); 
2586                 FreeLibrary( ras_handle );
2587                 return;
2588         }
2589
2590         ml_printf("Found %d connections\n", num_connections);
2591
2592         for (i = 0; i < num_connections; i++ ) {
2593                 RASCONNSTATUS status;
2594                 RASPPPIP projection;
2595                 unsigned long size;
2596
2597                 ml_printf("Connection %d:\n", i);
2598                 ml_printf("Entry Name: %s\n", rasbuffer[i].szEntryName);
2599                 ml_printf("Device Type: %s\n", rasbuffer[i].szDeviceType);
2600                 ml_printf("Device Name: %s\n", rasbuffer[i].szDeviceName);
2601
2602                 // get the connection status
2603                 status.dwSize = sizeof(RASCONNSTATUS);
2604                 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2605                 if ( rval != 0 ) {
2606                         FreeLibrary( ras_handle );
2607                         return;
2608                 }
2609
2610                 ml_printf("\tStatus: %s\n", (status.rasconnstate==RASCS_Connected)?"Connected":"Not Connected");
2611
2612                 // get the projection informatiom
2613                 size = sizeof(projection);
2614                 projection.dwSize = size;
2615                 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2616                 if ( rval != 0 ) {
2617                         FreeLibrary( ras_handle );
2618                         return;
2619                 }
2620
2621                 ml_printf("IP Address: %s", projection.szIpAddress));
2622         }
2623
2624         Ras_connected = 1;
2625
2626         FreeLibrary( ras_handle );
2627 }
2628 */
2629
2630 // set some options on a socket
2631 void psnet_socket_options( SOCKET sock )
2632 {
2633         int broadcast;//, ret;
2634 #ifndef PLAT_UNIX
2635         int cursize, cursizesize, bufsize; 
2636 #else
2637         socklen_t cursize, cursizesize, bufsize; 
2638 #endif
2639
2640         // Set the mode of the socket to allow broadcasting.  We need to be able to broadcast
2641         // when a game is searched for in IPX mode.
2642         broadcast = 1;
2643         if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast) )){
2644                 Can_broadcast = 0;
2645         } else {
2646                 Can_broadcast = 1;
2647         }
2648
2649         // reuseaddr
2650         // setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&broadcast, sizeof(broadcast) );
2651
2652         // try and increase the size of my receive buffer
2653         bufsize = MAX_RECEIVE_BUFSIZE;
2654         
2655         // set the current size of the receive buffer
2656         cursizesize = sizeof(int);
2657         getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&cursize, &cursizesize);
2658         // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2659         /*ret =*/ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize));
2660         /*if ( ret == SOCKET_ERROR ) {
2661                 int wserr;
2662
2663                 wserr = WSAGetLastError();
2664                 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
2665                         // break;
2666         }*/
2667         // }
2668         getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&cursize, &cursizesize);
2669         ml_printf("Receive buffer set to %d\n", cursize);
2670
2671         // set the current size of the send buffer
2672         cursizesize = sizeof(int);
2673         getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&cursize, &cursizesize);
2674         // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2675         /*ret =*/ setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize));
2676         /*if ( ret == SOCKET_ERROR ) {
2677                 int wserr;
2678
2679                 wserr = WSAGetLastError();
2680                 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) ){
2681                         // break;
2682                 // }
2683         }*/
2684         getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&cursize, &cursizesize);
2685         ml_printf("Send buffer set to %d\n", cursize);
2686 }
2687
2688 // initialize ipx socket
2689 int psnet_init_ipx()
2690 {       
2691 #ifdef PLAT_UNIX
2692         return 0;
2693 #else
2694         SOCKADDR_IPX sockaddr;
2695
2696         IPX_socket = INVALID_SOCKET;    
2697         
2698         IPX_socket = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );
2699         if ( IPX_socket == INVALID_SOCKET ) {
2700                 Ipx_failure_code = WSAGetLastError();
2701                 ml_printf("Error on IPX startup %d\n", Ipx_failure_code);
2702                 return 0;
2703         }
2704
2705         // bind the socket
2706         memset(&sockaddr,0,sizeof(SOCKADDR_IPX));
2707         sockaddr.sa_family = AF_IPX;    
2708         sockaddr.sa_socket = htons( Psnet_default_port );
2709         if ( bind(IPX_socket, (struct sockaddr*)&sockaddr, sizeof (SOCKADDR_IPX)) == SOCKET_ERROR) {
2710                 Ipx_failure_code = WSAGetLastError();
2711                 ml_printf("Couldn't bind IPX socket (%d)! Invalidating IPX\n", Ipx_failure_code ); 
2712                 return 0;
2713         }
2714
2715         // set socket options
2716         psnet_socket_options( IPX_socket );             
2717         Ipx_can_broadcast = Can_broadcast;
2718
2719         // success
2720         return 1;
2721 #endif
2722 }
2723
2724 // initialize tcp socket
2725 int psnet_init_tcp()
2726 {       
2727         struct sockaddr_in sockaddr;
2728
2729         TCP_socket = INVALID_SOCKET;    
2730         
2731         TCP_socket = socket( AF_INET, SOCK_DGRAM, 0 );
2732         if ( TCP_socket == (int)INVALID_SOCKET ) {
2733                 Tcp_failure_code = WSAGetLastError();
2734                 ml_printf("Error on TCP startup %d\n", Tcp_failure_code);
2735                 return 0;
2736         }
2737
2738         // bind the socket
2739         memset(&sockaddr,0,sizeof(struct sockaddr_in));
2740         sockaddr.sin_family = AF_INET; 
2741         sockaddr.sin_addr.s_addr = psnet_get_ip();
2742         sockaddr.sin_port = htons( Psnet_default_port );
2743         if ( bind(TCP_socket, (struct sockaddr*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
2744                 Tcp_failure_code = WSAGetLastError();
2745                 ml_printf("Couldn't bind TCP socket (%d)! Invalidating TCP\n", Tcp_failure_code ); 
2746                 return 0;
2747         }
2748
2749         // set socket options
2750         psnet_socket_options( TCP_socket );             
2751         Tcp_can_broadcast = Can_broadcast;
2752
2753         // success
2754         return 1;
2755 }
2756
2757 // get time in seconds
2758 float psnet_get_time()
2759 {               
2760         return (float)timer_get_milliseconds() / 1000.0f;
2761 }
2762
2763 // mark a socket as having received data
2764 void psnet_mark_received(PSNET_SOCKET_RELIABLE socket)
2765 {
2766         // valid socket?
2767         if((socket == 0xffffffff) || (socket >= MAXRELIABLESOCKETS)){
2768                 return;
2769         }
2770
2771         // mark it
2772         Reliable_sockets[socket].last_packet_received = psnet_get_time();
2773 }
2774
2775 #endif  //  if PSNET2
2776