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