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