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