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