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