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