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