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