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