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