2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Network/Psnet2.cpp $
15 * C file containing application level network-interface.
18 * Revision 1.13 2005/10/01 22:01:28 taylor
19 * some cleanup of earlier big-endian changes
21 * Revision 1.12 2004/07/04 11:39:06 taylor
22 * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
24 * Revision 1.11 2004/06/11 01:52:15 tigital
25 * byte-swapping changes for bigendian systems
27 * Revision 1.10 2003/08/03 16:10:30 taylor
28 * cleanup; compile warning fixes
30 * Revision 1.9 2002/07/27 19:52:54 relnev
31 * add missing structure packing
33 * Revision 1.8 2002/06/09 04:41:24 relnev
34 * added copyright header
36 * Revision 1.7 2002/06/02 05:31:17 relnev
39 * Revision 1.6 2002/06/02 02:29:39 relnev
42 * Revision 1.5 2002/05/27 04:04:43 relnev
43 * 155 undefined references left
45 * Revision 1.4 2002/05/26 21:27:53 theoddone33
46 * More progress (I hate psnet2)
48 * Revision 1.3 2002/05/26 20:49:54 theoddone33
51 * Revision 1.2 2002/05/07 03:16:48 theoddone33
52 * The Great Newline Fix
54 * Revision 1.1.1.1 2002/05/03 03:28:10 root
58 * 25 9/14/99 2:21p Dave
59 * Fixed observer mode joining and ingame stuff.
61 * 24 9/10/99 9:44p Dave
62 * Bumped version # up. Make server reliable connects not have such a huge
65 * 23 9/07/99 4:01p Dave
66 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
67 * does everything properly (setting up address when binding). Remove
68 * black rectangle background from UI_INPUTBOX.
70 * 22 8/26/99 8:51p Dave
71 * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
73 * 21 8/16/99 4:06p Dave
74 * Big honking checkin.
76 * 20 7/26/99 5:50p Dave
77 * Revised ingame join. Better? We'll see....
79 * 19 7/20/99 1:49p Dave
80 * Peter Drake build. Fixed some release build warnings.
82 * 18 7/15/99 9:20a Andsager
83 * FS2_DEMO initial checkin
85 * 17 7/03/99 4:08p Dave
86 * Fixed wss_slots size issues. Fixed potentially nasty bug in low level
89 * 16 6/25/99 5:02p Jasenw
90 * Removed old debug code.
92 * 15 6/07/99 9:51p Dave
93 * Consolidated all multiplayer ports into one.
95 * 14 4/30/99 12:18p Dave
96 * Several minor bug fixes.
98 * 13 4/27/99 5:55p Dave
99 * Fixed Ras_connected bug with VSDK code.
101 * 12 4/27/99 2:59p Dave
102 * Potential fix for reliable socket connection problem.
104 * 11 4/23/99 11:07a Dave
105 * Added lots of debug multi.log output to psnet2
107 * 10 4/12/99 10:07p Dave
108 * Made network startup more forgiving. Added checkmarks to dogfight
109 * screen for players who hit commit.
111 * 9 3/10/99 6:50p Dave
112 * Changed the way we buffer packets for all clients. Optimized turret
113 * fired packets. Did some weapon firing optimizations.
115 * 8 3/09/99 6:24p Dave
116 * More work on object update revamping. Identified several sources of
117 * unnecessary bandwidth.
119 * 7 3/08/99 7:03p Dave
120 * First run of new object update system. Looks very promising.
122 * 6 1/24/99 11:37p Dave
123 * First full rev of beam weapons. Very customizable. Removed some bogus
124 * Int3()'s in low level net code.
126 * 5 1/06/99 2:24p Dave
127 * Stubs and release build fixes.
129 * 4 11/20/98 11:16a Dave
130 * Fixed up IPX support a bit. Making sure that switching modes and
131 * loading/saving pilot files maintains proper state.
133 * 3 11/19/98 4:19p Dave
134 * Put IPX sockets back in psnet. Consolidated all multiplayer config
137 * 2 11/19/98 8:04a Dave
138 * Full support for D3-style reliable sockets. Revamped packet lag/loss
139 * system, made it receiver side and at the lowest possible level.
146 #include <windowsx.h>
151 #include <raserror.h>
153 #include <sys/types.h>
154 #include <sys/socket.h>
155 #include <netinet/in.h>
156 #include <arpa/inet.h>
166 #include "multiutil.h"
167 #include "multilag.h"
168 #include "osregistry.h"
170 #include "multi_log.h"
171 #include "multi_rate.h"
176 // -------------------------------------------------------------------------------------------------------
177 // PSNET 2 DEFINES/VARS
180 BOOL Psnet_my_addr_valid;
181 net_addr_t Psnet_my_addr;
183 ubyte Null_address[6];
186 int Can_broadcast; // can we do broadcasting on our socket?
187 int Ipx_can_broadcast = 0;
188 int Tcp_can_broadcast = 0;
194 int Tcp_failure_code = 0;
195 int Ipx_failure_code = 0;
197 int Psnet_connection;
199 ushort Psnet_default_port;
201 // specified their internet connnection type
202 #define NETWORK_CONNECTION_NONE 1
203 #define NETWORK_CONNECTION_DIALUP 2
204 #define NETWORK_CONNECTION_LAN 3
206 // defines and variables to indicate network connection status
207 #define NETWORK_STATUS_NOT_INITIALIZED 1
208 #define NETWORK_STATUS_NO_WINSOCK 2 // winsock failed to initialize
209 #define NETWORK_STATUS_NO_PROTOCOL 3 // TCP/IP doesn't appear to be loaded
210 #define NETWORK_STATUS_NO_RELIABLE 4
211 #define NETWORK_STATUS_RUNNING 5 // everything should be running
213 // defintion of structures that actually leave this machine. psnet_send give us only
214 // the data that we want to send. We will add a header onto this data (packet sequence
215 // number, possibly a checksum). We must include a 2 byte flags variable into both structure
216 // since the receiving end of this packet must know whether or not to checksum the packet.
218 #define MAX_TOP_LAYER_PACKET_SIZE 680
220 // use the pack pragma to pack these structures to 2 byte aligment. Really only needed for
222 #define MAX_PACKET_BUFFERS 75
225 #pragma pack(push, 2)
228 // definition for a non-checksum packet
229 typedef struct network_packet
233 ubyte data[MAX_TOP_LAYER_PACKET_SIZE];
234 } network_naked_packet;
236 // structure definition for our packet buffers
237 typedef struct network_packet_buffer
241 net_addr_t from_addr;
242 ubyte data[MAX_TOP_LAYER_PACKET_SIZE];
243 } network_packet_buffer;
245 // struct for a bunch of network packet buffers
246 typedef struct network_packet_buffer_list {
247 network_packet_buffer psnet_buffers[MAX_PACKET_BUFFERS];
248 int psnet_seq_number;
250 int psnet_highest_id;
251 } network_packet_buffer_list;
258 #define MAXHOSTNAME 128
260 #define MAX_RECEIVE_BUFSIZE 4096 // 32 K, eh?
261 #define MAX_SEND_RETRIES 20 // number of retries when sending would block
262 #define MAX_LINGER_TIME 0 // in seconds -- when lingering to close a socket
265 //*******************************
266 #define MAXNETBUFFERS 150 // Maximum network buffers (For between network and upper level functions, which is
267 // required in case of out of order packets
268 #define NETRETRYTIME 0.75f // Time after sending before we resend
269 #define MIN_NET_RETRYTIME 0.2f
270 #define NETTIMEOUT 30 // Time after receiving the last packet before we drop that user
271 #define NETHEARTBEATTIME 3 // How often to send a heartbeat
272 #define MAXRELIABLESOCKETS 40 // Max reliable sockets to open at once...
273 #define NETBUFFERSIZE 600 // Max size of a network packet
275 #define RELIABLE_CONNECT_TIME 7 // how long we'll wait for a response when doing a reliable connect
277 int Nettimeout = NETTIMEOUT;
279 // Reliable packet stuff
280 #define RNT_ACK 1 // ACK Packet
281 #define RNT_DATA 2 // Data Packet
282 #define RNT_DATA_COMP 3 // Compressed Data Packet
283 #define RNT_REQ_CONN 4 // Requesting a connection
284 #define RNT_DISCONNECT 5 // Disconnecting a connection
285 #define RNT_HEARTBEAT 6 // Heartbeat -- send every NETHEARTBEATTIME
286 #define RNT_I_AM_HERE 7
289 #pragma pack(push,r_udp)
293 #define PACKED __attribute__((packed))
297 ubyte type; // packet type
299 ushort seq; // sequence packet 0-65535 used for ACKing also
300 ushort data_len; // length of data
301 float send_time; // Time the packet was sent, if an ACK the time the packet being ACK'd was sent.
302 ubyte data[NETBUFFERSIZE]; // Packet data
303 } PACKED reliable_header;
305 #define RELIABLE_PACKET_HEADER_ONLY_SIZE (sizeof(reliable_header)-NETBUFFERSIZE)
306 #define MAX_PING_HISTORY 10
309 ubyte buffer[NETBUFFERSIZE];
311 } PACKED reliable_net_sendbuffer;
314 ubyte buffer[NETBUFFERSIZE];
315 } PACKED reliable_net_rcvbuffer;
318 reliable_net_sendbuffer *sbuffers[MAXNETBUFFERS]; // This is an array of pointers for quick sorting
319 unsigned short ssequence[MAXNETBUFFERS]; // This is the sequence number of the given packet
320 float timesent[MAXNETBUFFERS];
321 int send_len[MAXNETBUFFERS];
322 reliable_net_rcvbuffer *rbuffers[MAXNETBUFFERS];
323 int recv_len[MAXNETBUFFERS];
324 unsigned short rsequence[MAXNETBUFFERS]; // This is the sequence number of the given packet
325 float last_packet_received; // For a given connection, this is the last packet we received
326 float last_packet_sent;
327 SOCKADDR addr; // SOCKADDR of our peer
328 ushort status; // Status of this connection
329 unsigned short oursequence; // This is the next sequence number the application is expecting
330 unsigned short theirsequence; // This is the next sequence number the peer is expecting
331 net_addr_t net_addr; // A FS2 network address structure
332 ubyte connection_type; // IPX, IP, modem, etc.
333 float pings[MAX_PING_HISTORY];
335 unsigned int num_ping_samples;
339 reliable_socket Reliable_sockets[MAXRELIABLESOCKETS];
341 // sockets for IPX and TCP (unreliable)
345 // the sockets that the game will use when selecting network type
346 SOCKET Unreliable_socket = INVALID_SOCKET;
349 // SOCKET Reliable_UDP_socket = INVALID_SOCKET;
350 // SOCKET Reliable_IPX_socket = INVALID_SOCKET;
352 float First_sent_iamhere = 0;
353 float Last_sent_iamhere = 0;
355 #define CONNECTSEQ 0x142 // Magic number for starting a connection, just so it isn't 0
357 unsigned int Serverconn = 0xffffffff;
360 #pragma pack(pop,r_udp)
364 //*******************************
367 network_packet_buffer_list Psnet_top_buffers[PSNET_NUM_TYPES];
369 // -------------------------------------------------------------------------------------------------------
370 // PSNET 2 FORWARD DECLARATIONS
373 // if the string is a legally formatted ip string
374 int psnet_is_valid_numeric_ip(char *ip);
376 // functions to get the status of a RAS connection
377 unsigned int psnet_ras_status();
379 // set some options on a socket
380 void psnet_socket_options( SOCKET sock );
382 // initialize ipx socket
383 int psnet_init_ipx();
385 // initialize tcp socket
386 int psnet_init_tcp();
388 // get time in seconds
389 float psnet_get_time();
391 // returns the ip address of this machine. use for calling bind() with to associate with the proper
392 // IP address and network device.
395 // initialize reliable sockets
396 int psnet_init_rel_tcp(int port, int should_listen);
397 int psnet_init_rel_ipx(int port, int should_listen);
399 // shutdown reliable sockets
400 void psnet_rel_close();
402 // initialize the buffering system
403 void psnet_buffer_init(network_packet_buffer_list *l);
405 // buffer a packet (maintain order!)
406 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr_t *from);
408 // get the index of the next packet in order!
409 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr_t *from);
412 // -------------------------------------------------------------------------------------------------------
413 // PSNET 2 TOP LAYER FUNCTIONS - these functions simply buffer and store packets based upon type (see PSNET_TYPE_* defines)
416 // wrappers around select() and recvfrom() for lagging/losing data
417 int RECVFROM(SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen, int psnet_type)
419 network_packet_buffer_list *l;
425 Assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
426 if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
429 l = &Psnet_top_buffers[psnet_type];
431 // if we have no buffer! The user should have made sure this wasn't the case by calling SELECT()
432 ret = psnet_buffer_get_next(l, (ubyte*)buf, &ret_len, &addr);
438 // otherwise, stuff the outgoing data
439 switch ( Socket_type ) {
444 ((SOCKADDR_IPX*)from)->sa_socket = htons(addr.port);
445 memcpy(((SOCKADDR_IPX*)from)->sa_nodenum, addr.addr, 6);
446 memcpy(((SOCKADDR_IPX*)from)->sa_netnum, addr.net_id, 4);
447 ((SOCKADDR_IPX*)from)->sa_family = AF_IPX;
448 *fromlen = sizeof(SOCKADDR_IPX);
453 ((SOCKADDR_IN*)from)->sin_port = htons(addr.port);
455 memcpy(&((SOCKADDR_IN*)from)->sin_addr.s_addr, addr.addr, 4);
457 memcpy(&((SOCKADDR_IN*)from)->sin_addr.S_un.S_addr, addr.addr, 4);
459 ((SOCKADDR_IN*)from)->sin_family = AF_INET;
460 *fromlen = sizeof(SOCKADDR_IN);
475 // wrappers around select() and recvfrom() for lagging/losing data
476 int SELECT(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, struct timeval FAR * timeout, int psnet_type)
478 network_packet_buffer_list *l;
480 // if this is a check for writability, just return the select
481 if(writefds != NULL){
482 return select(nfds, readfds, writefds, exceptfds, timeout);
486 Assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
487 if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
490 l = &Psnet_top_buffers[psnet_type];
492 // do we have any buffers in here?
493 if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
501 // wrappers around sendto to sorting through different packet types
502 int SENDTO(SOCKET s, char * buf, int len, int flags, sockaddr *to, int tolen, int psnet_type)
504 char outbuf[MAX_TOP_LAYER_PACKET_SIZE + 150];
507 outbuf[0] = (char)psnet_type;
508 memcpy(&outbuf[1], buf, len);
510 // is the socket writeable?
513 return sendto(s, outbuf, len + 1, flags, (SOCKADDR*)to, tolen);
516 // call this once per frame to read everything off of our socket
517 void PSNET_TOP_LAYER_PROCESS()
520 SOCKADDR_IN ip_addr; // UDP/TCP socket structure
522 SOCKADDR_IPX ipx_addr; // IPX socket structure
532 net_addr_t from_addr;
533 network_naked_packet packet_read;
535 // clear the addresses to remove compiler warnings
536 memset(&ip_addr, 0, sizeof(SOCKADDR_IN));
538 memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
541 if ( Network_status != NETWORK_STATUS_RUNNING ) {
542 ml_printf("Network ==> socket not inited in PSNET_TOP_LAYER_PROCESS\n");
547 // check if there is any data on the socket to be read. The amount of data that can be
548 // atomically read is stored in len.
551 FD_SET( Unreliable_socket, &rfds );
556 if ( select( -1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
558 if ( select( Unreliable_socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
560 ml_printf("Error %d doing a socket select on read\n", WSAGetLastError());
564 // if the read file descriptor is not set, then bail!
565 if ( !FD_ISSET(Unreliable_socket, &rfds) ){
569 // get data off the socket and process
570 read_len = SOCKET_ERROR;
571 switch ( Socket_type ) {
574 from_len = sizeof(SOCKADDR_IPX);
575 read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0, (SOCKADDR*)&ipx_addr, &from_len);
580 from_len = sizeof(SOCKADDR_IN);
581 read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0, (SOCKADDR*)&ip_addr, &from_len);
589 // set the from_addr for storage into the packet buffer structure
590 from_addr.type = Socket_type;
592 switch ( Socket_type ) {
595 from_addr.port = ntohs( ipx_addr.sa_socket );
596 memcpy(from_addr.addr, ipx_addr.sa_nodenum, 6 );
597 memcpy(from_addr.net_id, ipx_addr.sa_netnum, 4 );
602 from_addr.port = ntohs( ip_addr.sin_port );
603 memset(from_addr.addr, 0x00, 6);
605 memcpy(from_addr.addr, &ip_addr.sin_addr.S_un.S_addr, 4);
607 memcpy(from_addr.addr, &ip_addr.sin_addr.s_addr, 4);
617 if ( read_len == SOCKET_ERROR ) {
618 // int x = WSAGetLastError();
619 ml_printf("Socket error on socket_get_data()");
623 // determine the packet type
624 int packet_type = packet_read.data[0];
625 // mprintf(("TOP LAYER PACKET %d!\n", packet_type));
626 if((packet_type < 0) || (packet_type >= PSNET_NUM_TYPES)){
630 psnet_buffer_packet(&Psnet_top_buffers[packet_type], packet_read.data + 1, read_len - 1, &from_addr);
636 // -------------------------------------------------------------------------------------------------------
640 // initialize psnet to use the specified port
641 void psnet_init( int protocol, int port_num )
643 char *internet_connection;
651 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
655 // GAME PORT INITIALIZATION STUFF
656 if ( Network_status == NETWORK_STATUS_RUNNING ){
657 ml_string("Skipping psnet_init() because network already running");
661 internet_connection = os_config_read_string(NULL, "NetworkConnection", "none");
662 if ( !stricmp(internet_connection, NOX("dialup")) ) {
663 ml_string("psnet_init() detected dialup connection");
665 Psnet_connection = NETWORK_CONNECTION_DIALUP;
666 } else if ( !stricmp(internet_connection, NOX("lan")) ) {
667 ml_string("psnet_init() detected lan connection");
669 Psnet_connection = NETWORK_CONNECTION_LAN;
671 ml_string("psnet_init() detected no connection");
673 Psnet_connection = NETWORK_CONNECTION_NONE;
676 Network_status = NETWORK_STATUS_NO_WINSOCK;
678 if (WSAStartup(0x101, &wsa_data )){
683 // get the port for running this game on. Be careful that it cannot be out of bounds
684 Psnet_default_port = DEFAULT_GAME_PORT;
685 if ( (port_num > 1023) && (port_num < USHRT_MAX) ) {
686 Psnet_default_port = (ushort)port_num;
689 // initialize TCP now
691 if(!psnet_init_tcp()){
692 ml_printf("Error on TCP startup %d\n", Tcp_failure_code);
696 if(!psnet_init_rel_tcp(Psnet_default_port + 1, 0)){
697 ml_printf("Network", "Error on TCP startup %d\n", Tcp_failure_code);
703 // clear reliable sockets
704 reliable_socket *rsocket;
706 for(j=0; j<MAXRELIABLESOCKETS; j++){
707 rsocket=&Reliable_sockets[j];
708 memset(rsocket,0,sizeof(reliable_socket));
711 // initialize IPX not
714 if(!psnet_init_ipx()){
715 ml_printf("Network", "Error on IPX startup %d\n", Ipx_failure_code);
719 if(!psnet_init_rel_ipx(Psnet_default_port + 1, 0)){
720 ml_printf("Network", "Error on IPX startup %d\n", Ipx_failure_code);
729 // determine if we've successfully initialized the protocol we want
730 if(!Tcp_active && !Ipx_active){
731 Network_status = NETWORK_STATUS_NO_PROTOCOL;
733 ml_string("No protocol in psnet_init()!");
736 // specified network timeout
737 Nettimeout = NETTIMEOUT;
738 if(Cmdline_timeout > 0){
739 Nettimeout = Cmdline_timeout;
745 if(Network_status != NETWORK_STATUS_NO_PROTOCOL){
746 // set network to be running
747 Network_status = NETWORK_STATUS_RUNNING;
749 // determine if our socket can broadcast
750 Can_broadcast = Tcp_can_broadcast || Ipx_can_broadcast;
752 // initialize all packet type buffers
753 for(idx=0; idx<PSNET_NUM_TYPES; idx++){
754 psnet_buffer_init(&Psnet_top_buffers[idx]);
762 if ( Network_status != NETWORK_STATUS_RUNNING ){
767 WSACancelBlockingCall();
770 if ( TCP_socket != (int)INVALID_SOCKET ) {
771 shutdown( TCP_socket, 1 );
772 closesocket( TCP_socket );
775 if ( IPX_socket != (int)INVALID_SOCKET ) {
776 shutdown( IPX_socket, 1 );
777 closesocket( IPX_socket );
782 //Warning( LOCATION, "Error closing wsock!\n" );
786 // close down all reliable sockets - this forces them to
787 // send a disconnect to any remote machines
790 Network_status = NETWORK_STATUS_NOT_INITIALIZED;
793 // set the protocol to use
794 int psnet_use_protocol( int protocol )
798 SOCKADDR_IPX ipx_addr;
804 // zero out my address
805 Psnet_my_addr_valid = 0;
806 memset( &Psnet_my_addr, 0, sizeof(Psnet_my_addr) );
808 // wait until we choose a protocol to determine if we can broadcast
811 ml_string("In psnet_use_protocol()");
813 switch ( protocol ) {
816 ml_string("psnet_use_protocol() selecting IPX");
818 // assign the IPX_* sockets to the socket values used elsewhere
819 Unreliable_socket = IPX_socket;
821 Can_broadcast = Ipx_can_broadcast;
823 ml_printf("Psnet : IPX broadcast\n");
826 // get the socket name for the IPX_socket, and put it into My_addr
827 len = sizeof(SOCKADDR_IPX);
828 if ( getsockname(IPX_socket, (SOCKADDR *)&ipx_addr, &len) == SOCKET_ERROR ) {
829 ml_printf("Unable to get sock name for IPX unreliable socket (%d)\n", WSAGetLastError() );
833 memcpy(Psnet_my_addr.net_id, ipx_addr.sa_netnum, 4);
834 memcpy(Psnet_my_addr.addr, ipx_addr.sa_nodenum, 6);
835 Psnet_my_addr.port = Psnet_default_port;
837 ml_printf("Psnet using - NET_IPX\n");
842 if ( Network_status != NETWORK_STATUS_RUNNING ){
843 ml_string("Network_status != NETWORK_STATUS_RUNNING in NET_TCP in psnet_use_protocol()");
847 // assign the TCP_* sockets to the socket values used elsewhere
848 Unreliable_socket = TCP_socket;
850 Can_broadcast = Tcp_can_broadcast;
852 ml_printf("Psnet : TCP broadcast\n");
855 // get the socket name for the IPX_socket, and put it into My_addr
856 len = sizeof(SOCKADDR_IN);
857 if ( getsockname(TCP_socket, (SOCKADDR *)&ip_addr, &len) == SOCKET_ERROR ) {
858 ml_printf("Unable to get sock name for TCP unreliable socket (%d)\n", WSAGetLastError() );
863 memset(Psnet_my_addr.net_id, 0, 4);
864 memcpy(Psnet_my_addr.addr, &ip_addr.sin_addr, 6);
865 Psnet_my_addr.port = Psnet_default_port;
867 ml_printf("Psnet using - NET_TCP\n");
875 Psnet_my_addr.type = protocol;
876 Socket_type = protocol;
881 // get the status of the network
882 int psnet_get_network_status()
884 // first case is when "none" is selected
885 if ( Psnet_connection == NETWORK_CONNECTION_NONE ) {
886 return NETWORK_ERROR_NO_TYPE;
889 // first, check the connection status of the network
890 if ( Network_status == NETWORK_STATUS_NO_WINSOCK )
891 return NETWORK_ERROR_NO_WINSOCK;
893 if ( Network_status == NETWORK_STATUS_NO_PROTOCOL ){
894 return NETWORK_ERROR_NO_PROTOCOL;
897 // network is running -- be sure that the RAS people know to connect if they currently cannot.
899 if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
900 // if on a dialup connection, be sure that RAS is active.
901 if ( !Ras_connected ) {
902 return NETWORK_ERROR_CONNECT_TO_ISP;
904 } else if ( Psnet_connection == NETWORK_CONNECTION_LAN ) {
905 // if on a LAN, and they have a dialup connection active, return error to indicate that they need
906 // to pick the right connection type
907 if ( Ras_connected ) {
908 return NETWORK_ERROR_LAN_AND_RAS;
911 return NETWORK_ERROR_NONE;
914 // convert a net_addr to a string
915 char* psnet_addr_to_string( char * text, net_addr_t * address )
918 if ( Network_status != NETWORK_STATUS_RUNNING ) {
919 strcpy( text, XSTR("[no networking]",910) );
925 switch ( address->type ) {
927 sprintf(text, "%x %x %x %x: %x %x %x %x %x %x", address->net_id[0],
940 memcpy(&temp_addr.s_addr, address->addr, 4);
941 strcpy( text, inet_ntoa(temp_addr) );
953 // convert a string to a net addr
954 void psnet_string_to_addr( net_addr_t * address, char * text )
957 char str[255], *c, *port;
960 if ( Network_status != NETWORK_STATUS_RUNNING ) {
961 strcpy( text, XSTR("[no networking]",910) );
965 // copy the text string to local storage to look for ports
966 Assert( strlen(text) < 255 );
968 c = strrchr(str, ':');
975 switch ( address->type ) {
977 Int3(); // no support for this yet
981 addr.s_addr = inet_addr(str);
982 // if we get INADDR_NONE returns, then we need to try and resolve the host
984 if ( addr.s_addr == INADDR_NONE ) {
985 he = gethostbyname( str );
986 // returns a non-null pointer if successful, so get the address
988 addr.s_addr = ((in_addr *)(he->h_addr))->s_addr; // this is the address in network byte order
990 addr.s_addr = INADDR_NONE;
994 memset(address->addr, 0x00, 6);
995 memcpy(address->addr, &addr.s_addr, 4);
997 address->port = (ushort)(atoi(port));
1008 // compare 2 addresses
1009 int psnet_same( net_addr_t * a1, net_addr_t * a2 )
1011 return !memcmp(a1->addr, a2->addr, 6);
1014 // send data unreliably
1015 int psnet_send( net_addr_t * who_to, void * data, int len, int np_index )
1017 // send data unreliably
1019 SOCKADDR_IN sockaddr; // UDP/TCP socket structure
1021 SOCKADDR_IPX ipx_addr; // IPX socket structure
1024 ubyte iaddr[6], *send_data;
1027 struct timeval timeout;
1029 // always use the reliable socket
1030 send_sock = Unreliable_socket;
1032 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1033 ml_printf("Network ==> Socket not inited in psnet_send\n");
1037 if ( psnet_same( who_to, &Psnet_my_addr) ){
1041 memset(iaddr, 0x00, 6);
1042 memcpy(iaddr, who_to->addr, 6);
1044 if ( memcmp(iaddr, Null_address, 6) == 0) {
1045 ml_printf("Network ==> send to address is 0 in psnet_send\n");
1049 port = who_to->port;
1052 ml_printf("Network ==> destination port %d invalid in psnet_send\n", port);
1056 // stuff the data with the type
1057 send_data = (ubyte*)data;
1061 FD_SET( send_sock, &wfds );
1063 timeout.tv_usec = 0;
1066 if ( SELECT( -1, NULL, &wfds, NULL, &timeout, PSNET_TYPE_UNRELIABLE) == SOCKET_ERROR ) {
1068 if ( SELECT( send_sock+1, NULL, &wfds, NULL, &timeout, PSNET_TYPE_UNRELIABLE) == SOCKET_ERROR ) {
1070 ml_printf("Error on blocking select for write %d\n", WSAGetLastError() );
1074 // if the write file descriptor is not set, then bail!
1075 if ( !FD_ISSET(send_sock, &wfds ) ){
1080 switch ( who_to->type ) {
1083 ipx_addr.sa_socket = htons(port);
1084 ipx_addr.sa_family = AF_IPX;
1085 memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1086 memcpy(ipx_addr.sa_netnum, who_to->net_id, 4);
1088 ret = SENDTO(send_sock, (char *)send_data, send_len, 0, (SOCKADDR*)&ipx_addr, sizeof(ipx_addr), PSNET_TYPE_UNRELIABLE);
1090 multi_rate_add(np_index, "ipx", send_len);
1091 if ( (ret != SOCKET_ERROR) && (ret != send_len) ){
1092 // ml_printf("requested to send %d bytes -- sent %d instead!!!\n", send_len, ret);
1098 sockaddr.sin_family = AF_INET;
1099 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1100 sockaddr.sin_port = htons(port);
1102 multi_rate_add(np_index, "udp(h)", send_len + UDP_HEADER_SIZE);
1103 multi_rate_add(np_index, "udp", send_len);
1104 ret = SENDTO( send_sock, (char *)send_data, send_len, 0, (SOCKADDR*)&sockaddr, sizeof(sockaddr), PSNET_TYPE_UNRELIABLE );
1108 Assert(0); // unknown protocol
1113 if ( ret != SOCKET_ERROR ) {
1116 //Warning( LOCATION, "Couldn't send data (0x%x)!\n", WSAGetLastError() );
1120 // get data from the unreliable socket
1121 int psnet_get( void * data, net_addr_t * from_addr )
1125 // try and get a free buffer and return its size
1126 if(psnet_buffer_get_next(&Psnet_top_buffers[PSNET_TYPE_UNRELIABLE], (ubyte*)data, &buffer_size, from_addr)){
1134 // broadcast data on unreliable socket
1135 int psnet_broadcast( net_addr_t * who_to, void * data, int len )
1137 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1138 ml_printf("Network ==> Socket not inited in psnet_broadcast\n");
1142 if ( !Can_broadcast ) {
1143 ml_printf("Cannot broadcast -- returning without doing anything\n");
1147 ubyte broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1149 // broadcasting works on a local subnet which is all we really want to do for now anyway.
1150 // we might keep this in as an option for freespace later.
1151 switch ( who_to->type ) {
1154 memcpy(who_to->addr, broadcast, 6);
1155 psnet_send(who_to, data, len);
1163 // flush all sockets
1166 ubyte data[MAX_TOP_LAYER_PACKET_SIZE + 250];
1167 net_addr_t from_addr;
1169 while ( psnet_get( data, &from_addr ) > 0 ) ;
1172 // if the passed string is a valid IP string
1173 int psnet_is_valid_ip_string( char *ip_string, int allow_port )
1176 struct hostent *host_ent;
1179 // our addresses may have ports, so make local copy and remove port number
1180 Assert( strlen(ip_string) < 255 );
1181 strcpy(str, ip_string);
1182 c = strrchr(str, ':');
1187 addr.s_addr = inet_addr(ip_string);
1188 if ( addr.s_addr != INADDR_NONE ){
1189 // make sure the ip string is a valid format string
1190 if(psnet_is_valid_numeric_ip(ip_string)){
1195 // try name resolution
1196 host_ent = gethostbyname( ip_string );
1201 // valid host entry so return 1;
1206 // -------------------------------------------------------------------------------------------------------
1207 // PSNET 2 RELIABLE SOCKET FUNCTIONS
1211 int psnet_rel_ping_compare( const void *arg1, const void *arg2 )
1213 float *ping1 = (float *)arg1;
1214 float *ping2 = (float *)arg2;
1216 if(*ping1==*ping2) return 0;
1217 else if(*ping1>*ping2) return 1;
1218 else if(*ping1<*ping2) return -1;
1223 void psnet_rel_send_ack(SOCKADDR *raddr, unsigned int sig, ubyte link_type, float time_sent)
1226 reliable_header ack_header;
1227 ack_header.type = RNT_ACK;
1228 ack_header.data_len = sizeof(unsigned int);
1229 ack_header.send_time = INTEL_FLOAT( &time_sent );
1230 sig_tmp = INTEL_INT( sig );
1231 memcpy(&ack_header.data,&sig_tmp,sizeof(unsigned int));
1232 switch (link_type) {
1235 ml_string("No IPX in rel_send_ack()");
1238 ret = SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1242 ml_string("No TCP in rel_send_ack()");
1245 ret = SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1248 ml_string("Unknown protocol type in nw_SendReliable()");
1254 // function to shutdown and close the given socket. It takes a couple of things into consideration
1255 // when closing, such as possibly reiniting reliable sockets if they are closed here.
1256 void psnet_rel_close_socket( PSNET_SOCKET_RELIABLE *sockp )
1258 reliable_header diss_conn_header;
1260 // if the socket is out of range
1261 if(*sockp>=MAXRELIABLESOCKETS)
1263 ml_printf("Invalid socket id passed to nw_NewCloseSocket() -- %d\n",*sockp);
1266 ml_printf("Closing socket %d\n",*sockp);
1268 // go through every buffer and "free it up(tm)"
1270 for(i=0;i<MAXNETBUFFERS;i++){
1271 if(Reliable_sockets[*sockp].rbuffers[i]){
1272 if(Reliable_sockets[*sockp].rbuffers[i] != NULL){
1273 free(Reliable_sockets[*sockp].rbuffers[i]);
1275 Reliable_sockets[*sockp].rbuffers[i] = NULL;
1276 Reliable_sockets[*sockp].rsequence[i] = 0;
1278 if(Reliable_sockets[*sockp].sbuffers[i]){
1279 if(Reliable_sockets[*sockp].sbuffers[i] != NULL){
1280 free(Reliable_sockets[*sockp].sbuffers[i]);
1282 Reliable_sockets[*sockp].sbuffers[i] = NULL;
1283 Reliable_sockets[*sockp].rsequence[i] = 0;
1287 // send a disconnect packet to the socket on the other end
1288 diss_conn_header.type = RNT_DISCONNECT;
1289 diss_conn_header.seq = CONNECTSEQ;
1290 diss_conn_header.data_len = 0;
1291 if(*sockp==Serverconn){
1292 Serverconn = 0xffffffff;
1294 switch ( Reliable_sockets[*sockp].connection_type ) {
1299 SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1305 SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1308 ml_printf("Unknown protocol type in nw_CloseSocket()!\n");
1312 memset(&Reliable_sockets[*sockp],0,sizeof(reliable_socket));
1313 Reliable_sockets[*sockp].status = RNF_UNUSED;
1316 // function to check the status of the reliable socket and try to re-initialize it if necessary.
1317 // win95 seems to have trouble doing a reinit of the socket immediately after close, so this
1318 // function exists to check the status, and reinitialize if we need to
1319 int psnet_rel_check()
1324 // send data reliably
1325 int psnet_rel_send(PSNET_SOCKET_RELIABLE socketid, ubyte *data, int length, int np_index)
1329 reliable_socket *rsocket;
1331 if(socketid >= MAXRELIABLESOCKETS){
1332 ml_printf("Invalid socket id passed to psnet_rel_send() -- %d\n",socketid);
1336 Assert( length < (int)(sizeof(reliable_header)) );
1339 rsocket=&Reliable_sockets[socketid];
1340 if(rsocket->status!=RNF_CONNECTED) {
1341 //We can't send because this isn't a connected reliable socket.
1342 ml_printf("Can't send packet because of status %d in nw_SendReliable(). socket = %d\n",rsocket->status,socketid);
1346 // Add the new packet to the sending list and send it.
1347 for(i=0;i<MAXNETBUFFERS;i++){
1348 if(NULL==rsocket->sbuffers[i]){
1349 reliable_header send_header;
1350 int send_this_packet=1;
1352 rsocket->send_len[i] = length;
1353 rsocket->sbuffers[i] = (reliable_net_sendbuffer *)malloc(sizeof(reliable_net_sendbuffer));
1355 memcpy(rsocket->sbuffers[i]->buffer,data,length);
1357 send_header.seq = INTEL_SHORT( rsocket->theirsequence );
1358 rsocket->ssequence[i] = rsocket->theirsequence;
1360 memcpy(send_header.data,data,length);
1361 send_header.data_len = INTEL_SHORT( (ushort)length );
1362 send_header.type = RNT_DATA;
1363 send_header.send_time = psnet_get_time();
1364 send_header.send_time = INTEL_FLOAT( &send_header.send_time );
1365 // SOCKADDR_IN * rsockaddr = (SOCKADDR_IN *)&rsocket->addr;
1367 if (send_this_packet){
1368 switch ( rsocket->connection_type ){
1373 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1379 multi_rate_add(np_index, "tcp(h)", RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i]);
1380 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1383 ml_printf("Unknown protocol type in nw_SendReliable()!\n");
1388 if((bytesout==SOCKET_ERROR)&&(WSAEWOULDBLOCK==WSAGetLastError())){
1389 //This will cause it to try to send again next frame. (or sooner)
1390 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1392 rsocket->timesent[i] = psnet_get_time();
1396 rsocket->theirsequence++;
1400 ml_printf("PSNET RELIABLE SEND BUFFER OVERRUN. socket = %d\n",socketid);
1406 // -1 socket not connected
1407 // 0 No packet ready to receive
1408 // >0 Buffer filled with the number of bytes recieved
1409 int psnet_rel_get(PSNET_SOCKET socketid, ubyte *buffer, int max_len)
1413 reliable_socket *rsocket = NULL;
1415 if(socketid >= MAXRELIABLESOCKETS){
1416 ml_printf("Invalid socket id passed to nw_NewReceiveReliable() -- %d\n",socketid);
1419 rsocket = &Reliable_sockets[socketid];
1420 if( (RNF_CONNECTED!=rsocket->status) && (RNF_LIMBO!=rsocket->status) ){
1421 ml_printf("Can't receive packet because it isn't connected in nw_ReceiveReliable(). socket = %d\n",socketid);
1424 //If the buffer position is the position we are waiting for, fill in
1425 //the buffer we received in the call to this function and return true
1427 for(i=0; i<MAXNETBUFFERS; i++){
1428 if((rsocket->rsequence[i] == rsocket->oursequence) && rsocket->rbuffers[i]){
1429 memcpy(buffer,rsocket->rbuffers[i]->buffer, rsocket->recv_len[i]);
1430 free(rsocket->rbuffers[i]);
1431 rsocket->rbuffers[i] = NULL;
1432 rsocket->rsequence[i] = 0;
1433 rsocket->oursequence++;
1434 return rsocket->recv_len[i];
1441 // process all active reliable sockets
1442 void psnet_rel_work()
1446 int max_len = NETBUFFERSIZE;
1449 static reliable_header rcv_buff;
1450 static SOCKADDR rcv_addr;
1452 int addrlen = sizeof(SOCKADDR);
1453 unsigned int rcvid;//The id of who we actually received a packet from, as opposed to socketid parm
1457 PSNET_TOP_LAYER_PROCESS();
1459 // negotitate initial connection with the server
1460 reliable_socket *rsocket = NULL;
1461 if(Serverconn != 0xffffffff){
1462 //Check to see if we need to send a packet out.
1463 if((Reliable_sockets[Serverconn].status==RNF_LIMBO) && ((Serverconn != 0xffffffff) && fl_abs((psnet_get_time() - Last_sent_iamhere))>NETRETRYTIME) ){
1464 reliable_header conn_header;
1465 //Now send I_AM_HERE packet
1466 conn_header.type = RNT_I_AM_HERE;
1467 conn_header.seq = (ushort)(~CONNECTSEQ);
1468 conn_header.data_len = 0;
1469 Last_sent_iamhere = psnet_get_time();
1470 int ret = SOCKET_ERROR;
1471 switch ( Reliable_sockets[Serverconn].connection_type ) {
1474 ml_printf("Unable to use this network connection type in nw_WorkReliable()\n");
1478 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1482 ml_printf("Unable to use this network connection type in nw_WorkReliable()\n");
1486 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1489 ml_printf("Unknown protocol type in nw_WorkReliable()!\n");
1494 if((ret == SOCKET_ERROR) && (WSAEWOULDBLOCK == WSAGetLastError())){
1495 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time()-NETRETRYTIME;
1497 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time();
1503 net_addr_t d3_rcv_addr;
1504 SOCKADDR_IN *rcvaddr,*rsockaddr;
1505 int ipx_has_data = 0;
1506 int udp_has_data = 0;
1510 if(Ipx_active && (Socket_type == NET_IPX)){
1512 FD_SET(Unreliable_socket, &read_fds);
1514 ipx_has_data = SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1516 ipx_has_data = SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1519 if(Tcp_active && (Socket_type == NET_TCP)){
1521 FD_SET(Unreliable_socket, &read_fds);
1523 udp_has_data = SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1525 udp_has_data = SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1529 addrlen = sizeof(SOCKADDR);
1532 SOCKADDR_IPX *ipx_addr = (SOCKADDR_IPX *)&rcv_addr;
1533 memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1534 memset(&rcv_addr,0,sizeof(SOCKADDR));
1535 bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1536 memcpy(d3_rcv_addr.addr, ipx_addr->sa_nodenum, 6);
1537 memcpy(d3_rcv_addr.net_id, ipx_addr->sa_netnum, 4);
1538 d3_rcv_addr.type = NET_IPX;
1539 link_type = NET_IPX;
1541 } else if(udp_has_data){
1542 SOCKADDR_IN *tcp_addr = (SOCKADDR_IN *)&rcv_addr;
1543 memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1544 memset(&rcv_addr,0,sizeof(SOCKADDR));
1545 bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header), 0, (SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1546 rcv_buff.seq = INTEL_SHORT( rcv_buff.seq );
1547 rcv_buff.data_len = INTEL_SHORT( rcv_buff.data_len );
1548 rcv_buff.send_time = INTEL_FLOAT( &rcv_buff.send_time );
1549 memcpy(d3_rcv_addr.addr, &tcp_addr->sin_addr.s_addr, 4);
1550 d3_rcv_addr.port = tcp_addr->sin_port;
1551 d3_rcv_addr.type = NET_TCP;
1552 link_type = NET_TCP;
1554 //Neither socket had data waiting
1559 ml_printf("recvfrom returned an error! -- %d\n",WSAGetLastError());
1560 //Int3();//See Kevin
1564 //Someone wants to connect, so find a slot
1565 if(rcv_buff.type == RNT_REQ_CONN){
1566 for(i=1; i<MAXRELIABLESOCKETS; i++){
1567 if( (Reliable_sockets[i].status == RNF_CONNECTED) || (Reliable_sockets[i].status == RNF_LIMBO) ){
1568 //if(memcmp(&rcv_addr,&reliable_sockets[i].addr,sizeof(SOCKADDR))==0)
1569 if(memcmp(&d3_rcv_addr, &Reliable_sockets[i].net_addr, sizeof(net_addr_t)) == 0){
1570 //We already have a reliable link to this user, so we will ignore it...
1571 ml_printf("Received duplicate connection request. %d\n",i);
1572 //reliable_sockets[i].last_packet_received = timer_GetTime();
1573 psnet_rel_send_ack(&Reliable_sockets[i].addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1574 //We will change this as a hack to prevent later code from hooking us up
1575 rcv_buff.type = 0xff;
1580 for(i=1; i<MAXRELIABLESOCKETS; i++){
1581 if(Reliable_sockets[i].status == RNF_UNUSED){
1582 //Add the new connection here.
1583 Reliable_sockets[i].connection_type=link_type;
1584 memcpy(&Reliable_sockets[i].net_addr, &d3_rcv_addr, sizeof(net_addr_t));
1585 memcpy(&Reliable_sockets[i].addr ,&rcv_addr, sizeof(SOCKADDR));
1586 Reliable_sockets[i].ping_pos = 0;
1587 Reliable_sockets[i].num_ping_samples = 0;
1588 Reliable_sockets[i].status = RNF_LIMBO;
1589 Reliable_sockets[i].last_packet_received = psnet_get_time();
1590 rsocket = &Reliable_sockets[i];
1591 rcvaddr = (SOCKADDR_IN *)&rcv_addr;
1592 ml_printf("Connect from %s:%d\n", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port));
1596 if(i==MAXRELIABLESOCKETS){
1597 //No more connections!
1598 ml_printf("Out of incoming reliable connection sockets\n");
1599 //Int3();//See Kevin
1602 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1605 //Find out if this is a packet from someone we were expecting a packet.
1606 rcvaddr = (SOCKADDR_IN *)&rcv_addr;
1607 for(i=1; i<MAXRELIABLESOCKETS; i++){
1608 rsockaddr = (SOCKADDR_IN *)&Reliable_sockets[i].addr;
1609 if(memcmp(&d3_rcv_addr,&Reliable_sockets[i].net_addr,sizeof(net_addr_t)) == 0){
1610 rsocket=&Reliable_sockets[i];
1615 if(rsocket == NULL){
1616 ml_printf("Received reliable data from unconnected client.\n");
1617 ml_printf("Received from %s:%d\n",inet_ntoa(rcvaddr->sin_addr),rcvaddr->sin_port);
1620 rsocket->last_packet_received = psnet_get_time();
1622 if(rsocket->status != RNF_CONNECTED){
1624 if(rsocket->status == RNF_LIMBO){
1625 //this is our connection to the server
1626 if(Serverconn != 0xffffffff){
1627 if(rcv_buff.type == RNT_ACK){
1628 ushort *acknum = (ushort *)&rcv_buff.data;
1629 if(*acknum == (~CONNECTSEQ & 0xffff)){
1630 rsocket->status = RNF_CONNECTED;
1631 ml_printf("Got ACK for IAMHERE!\n");
1635 } else if(rcv_buff.type == RNT_I_AM_HERE){
1636 rsocket->status = RNF_CONNECTING;
1637 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1638 ml_printf("Got IAMHERE!\n");
1642 if((rcv_buff.type == RNT_DATA) && (Serverconn != 0xffffffff)){
1643 rsocket->status = RNF_CONNECTED;
1645 rsocket->last_packet_received = psnet_get_time();
1649 //Update the last recv variable so we don't need a heartbeat
1650 rsocket->last_packet_received = psnet_get_time();
1652 if(rcv_buff.type == RNT_HEARTBEAT){
1655 if(rcv_buff.type == RNT_ACK){
1657 rsocket->num_ping_samples++;
1659 rsocket->pings[rsocket->ping_pos] = rsocket->last_packet_received - rcv_buff.send_time;
1660 if(rsocket->num_ping_samples >= MAX_PING_HISTORY){
1661 float sort_ping[MAX_PING_HISTORY];
1662 for(int a=0;a<MAX_PING_HISTORY;a++){
1663 sort_ping[a] = rsocket->pings[a];
1666 qsort(sort_ping ,MAX_PING_HISTORY, sizeof(float), psnet_rel_ping_compare);
1667 rsocket->mean_ping = ((sort_ping[MAX_PING_HISTORY/2]+sort_ping[(MAX_PING_HISTORY/2)+1]))/2;
1669 rsocket->ping_pos++;
1670 if(rsocket->ping_pos >= MAX_PING_HISTORY){
1671 rsocket->ping_pos=0;
1674 // if this is an ack for a send buffer on the socket, kill the send buffer. its done
1675 for(i=0; i<MAXNETBUFFERS; i++){
1676 unsigned int *acksig = (unsigned int *)&rcv_buff.data;
1678 if(rsocket->sbuffers[i]){
1679 if(rsocket->ssequence[i] == INTEL_INT(*acksig) ){
1680 Assert(rsocket->sbuffers[i] != NULL);
1681 free(rsocket->sbuffers[i]);
1682 rsocket->sbuffers[i] = NULL;
1683 rsocket->ssequence[i] = 0;
1688 //remove that packet from the send buffer
1689 rsocket->last_packet_received = psnet_get_time();
1693 if(rcv_buff.type == RNT_DATA_COMP){
1695 //Decompress it. Put it back in the buffer. Process it as RNT_DATA
1696 rcv_buff.type = RNT_DATA;
1698 if(rcv_buff.type == RNT_DATA){
1699 //If the data is out of order by >= MAXNETBUFFERS-1 ignore that packet for now
1701 seqdelta = rcv_buff.seq - rsocket->oursequence;
1702 if(seqdelta<0) seqdelta = seqdelta*-1;
1703 if(seqdelta>=MAXNETBUFFERS - 1){
1704 ml_printf("Received reliable packet out of order!\n");
1705 //It's out of order, so we won't ack it, which will mean we will get it again soon.
1708 //else move data into the proper buffer position
1711 if(rsocket->oursequence < (0xffff - (MAXNETBUFFERS-1))){
1712 if (rsocket->oursequence > rcv_buff.seq){
1716 //Sequence is high, so prepare for wrap around
1717 if( ((unsigned short)(rcv_buff.seq + rsocket->oursequence)) > (MAXNETBUFFERS-1)){
1722 for(i=0; i<MAXNETBUFFERS; i++){
1723 if( (NULL != rsocket->rbuffers[i]) && (rsocket->rsequence[i] == rcv_buff.seq)){
1724 //Received duplicate packet!
1729 for(i=0; i<MAXNETBUFFERS; i++){
1730 if(NULL == rsocket->rbuffers[i]){
1731 if(rcv_buff.data_len>max_len){
1732 rsocket->recv_len[i] = rcv_buff.data_len;
1734 rsocket->recv_len[i] = rcv_buff.data_len;
1736 rsocket->rbuffers[i] = (reliable_net_rcvbuffer *)malloc(sizeof(reliable_net_rcvbuffer));
1737 memcpy(rsocket->rbuffers[i]->buffer,rcv_buff.data,rsocket->recv_len[i]);
1738 rsocket->rsequence[i] = rcv_buff.seq;
1743 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1747 } while((ipx_has_data>0) || (udp_has_data>0));
1749 // Go through each reliable socket that is connected and do any needed work.
1750 for(j=0; j<MAXRELIABLESOCKETS; j++){
1751 rsocket=&Reliable_sockets[j];
1753 if(Serverconn == 0xffffffff){
1754 if(rsocket->status==RNF_LIMBO){
1755 if(fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout){
1756 ml_printf("Reliable (but in limbo) socket (%d) timed out in nw_WorkReliable().\n",j);
1757 memset(rsocket,0,sizeof(reliable_socket));
1758 rsocket->status = RNF_UNUSED;//Won't work if this is an outgoing connection.
1762 if((rsocket->status == RNF_LIMBO) && (fl_abs((psnet_get_time() - First_sent_iamhere)) > Nettimeout)){
1763 rsocket->status = RNF_BROKEN;
1764 ml_printf("Reliable socket (%d) timed out in nw_WorkReliable().\n",j);
1768 if(rsocket->status == RNF_CONNECTED){
1769 float retry_packet_time;
1770 if((rsocket->mean_ping==0) || (rsocket->mean_ping > (NETRETRYTIME*4))){
1771 retry_packet_time = NETRETRYTIME;
1773 if(rsocket->mean_ping<MIN_NET_RETRYTIME) {
1774 retry_packet_time = (float)MIN_NET_RETRYTIME;
1776 retry_packet_time = ((float)(float)rsocket->mean_ping * (float)1.25);
1779 //Iterate through send buffers.
1780 for(i=0;i<MAXNETBUFFERS;i++){
1782 if((rsocket->sbuffers[i]) && (fl_abs((psnet_get_time() - rsocket->timesent[i])) >= retry_packet_time)) {
1783 reliable_header send_header;
1784 send_header.send_time = psnet_get_time();
1785 send_header.send_time = INTEL_FLOAT( &send_header.send_time );
1786 send_header.seq = INTEL_SHORT( rsocket->ssequence[i] );
1787 memcpy(send_header.data,rsocket->sbuffers[i]->buffer,rsocket->send_len[i]);
1788 send_header.data_len = INTEL_SHORT( (ushort)rsocket->send_len[i] );
1789 send_header.type = RNT_DATA;
1790 if(rsocket->connection_type == NET_TCP){
1791 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1792 } else if(rsocket->connection_type == NET_IPX){
1793 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1795 if((rcode == SOCKET_ERROR) && (WSAEWOULDBLOCK == WSAGetLastError())){
1796 //The packet didn't get sent, flag it to try again next frame
1797 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1799 rsocket->last_packet_sent = psnet_get_time();
1800 rsocket->timesent[i] = psnet_get_time();
1806 if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_sent)) > NETHEARTBEATTIME)) {
1807 reliable_header send_header;
1808 send_header.send_time = psnet_get_time();
1809 send_header.send_time = INTEL_FLOAT( &send_header.send_time );
1810 send_header.seq = 0;
1811 send_header.data_len = 0;
1812 send_header.type = RNT_HEARTBEAT;
1815 if(rsocket->connection_type == NET_TCP){
1816 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1817 } else if(rsocket->connection_type == NET_IPX){
1818 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1820 if((rcode != SOCKET_ERROR) && (WSAEWOULDBLOCK != WSAGetLastError())){
1821 //It must have been sent
1822 rsocket->last_packet_sent = psnet_get_time();
1826 if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout)){
1827 //This socket is hosed.....inform someone?
1828 ml_printf("Reliable Socket (%d) timed out in nw_WorkReliable().\n",j);
1829 rsocket->status = RNF_BROKEN;
1835 // get the status of a reliable socket, see RNF_* defines above
1836 int psnet_rel_get_status(PSNET_SOCKET_RELIABLE socketid)
1838 if(socketid >= MAXRELIABLESOCKETS){
1842 return Reliable_sockets[socketid].status;
1845 // function which checks the Listen_socket for possibly incoming requests to be connected.
1846 // returns 0 on error or nothing waiting. 1 if we should try to accept
1847 int psnet_rel_check_for_listen(net_addr_t *from_addr)
1849 SOCKADDR_IN *ip_addr; // UDP/TCP socket structure
1851 SOCKADDR_IPX *ipx_addr; // IPX socket structure
1856 for(i=1; i<MAXRELIABLESOCKETS; i++){
1857 if(Reliable_sockets[i].status == RNF_CONNECTING){
1858 Reliable_sockets[i].status = RNF_CONNECTED;
1859 //memcpy(from_addr,&reliable_sockets[i].addr,sizeof(SOCKADDR));
1860 ml_printf("New reliable connection in nw_CheckListenSocket().\n");
1862 switch ( Reliable_sockets[i].connection_type ){
1865 ipx_addr = (SOCKADDR_IPX *)&Reliable_sockets[i].addr;
1866 memset(from_addr, 0x00, sizeof(net_addr_t));
1867 from_addr->port = ntohs( ipx_addr->sa_socket );
1868 from_addr->type = NET_IPX;
1869 memcpy(from_addr->addr, ipx_addr->sa_nodenum, 6 );
1870 memcpy(from_addr->net_id, ipx_addr->sa_netnum, 4 );
1875 ip_addr = (SOCKADDR_IN *)&Reliable_sockets[i].addr;
1876 memset(from_addr, 0x00, sizeof(net_addr_t));
1877 from_addr->port = ntohs( ip_addr->sin_port );
1878 from_addr->type = NET_TCP;
1880 memcpy(from_addr->addr, &ip_addr->sin_addr.S_un.S_addr, 4);
1882 memcpy(from_addr->addr, &ip_addr->sin_addr.s_addr, 4);
1891 char dbg_output[50];
1892 nw_GetNumbersFromHostAddress(from_addr,dbg_output);
1893 mprintf((0,"Got address from: %s\n",dbg_output));
1898 return INVALID_SOCKET;
1901 // attacmpt to connect() to the server's tcp socket. socket parameter is simply assigned to the
1902 // Reliable_socket socket created in psnet_init
1903 void psnet_rel_connect_to_server(PSNET_SOCKET *socket, net_addr_t *server_addr)
1905 //Send out a RNT_REQ_CONN packet, and wait for it to be acked.
1906 SOCKADDR_IN sockaddr; // UDP/TCP socket structure
1908 SOCKADDR_IPX ipx_addr; // IPX socket structure
1910 SOCKADDR *addr = NULL; // pointer to SOCKADDR to make coding easier
1916 float time_sent_req = 0;
1917 float first_sent_req = 0;
1918 static reliable_header conn_header;
1919 static reliable_header ack_header;
1921 struct timeval timeout;
1924 *socket = INVALID_SOCKET;
1926 memset(iaddr, 0x00, 6);
1927 memcpy(iaddr, &server_addr->addr, 6);
1928 port = (ushort)(server_addr->port); // Talk to the server listen port
1930 conn_header.type = RNT_REQ_CONN;
1931 conn_header.seq = CONNECTSEQ;
1932 conn_header.data_len = 0;
1937 if((server_addr->type == NET_IPX) && (!Ipx_active)){
1940 if((server_addr->type == NET_TCP) && (!Tcp_active)){
1943 //Flush out any left overs
1944 if(Tcp_active && (Socket_type == NET_TCP)){
1946 FD_SET(Unreliable_socket, &read_fds);
1948 while(SELECT(0, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE)){
1950 while(SELECT(Unreliable_socket+1, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE)){
1952 addrlen = sizeof(SOCKADDR);
1953 bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1955 //Int3();//See Kevin
1956 ml_printf("UDP recvfrom returned an error! -- %d\n",WSAGetLastError());
1961 FD_SET(Unreliable_socket, &read_fds);
1964 if(Ipx_active && (Socket_type == NET_IPX)){
1966 FD_SET(Unreliable_socket, &read_fds);
1968 while(SELECT(0, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE))
1970 while(SELECT(Unreliable_socket+1, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE))
1973 addrlen = sizeof(SOCKADDR);
1974 bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1977 //Int3();//See Kevin
1978 ml_printf("IPX recvfrom returned an error! -- %d\n",WSAGetLastError());
1982 FD_SET(Unreliable_socket, &read_fds);
1985 memset(&ack_header,0,sizeof(reliable_header));
1987 SOCKET typeless_sock = 0;
1988 net_addr_t d3_rcv_addr;
1989 memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1991 switch ( server_addr->type ){
1994 ipx_addr.sa_family = AF_IPX;
1995 memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1996 memcpy(ipx_addr.sa_netnum, server_addr->net_id, 4);
1997 ipx_addr.sa_socket = htons(port);
1998 addr = (SOCKADDR *)&ipx_addr;
1999 name_length = sizeof(ipx_addr);
2000 if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE) ){
2001 ml_printf("Unable to send IPX packet in nw_ConnectToServer()! -- %d\n",WSAGetLastError());
2004 typeless_sock = Unreliable_socket;
2005 memcpy(d3_rcv_addr.addr,ipx_addr.sa_nodenum, 6);
2006 memcpy(d3_rcv_addr.net_id,ipx_addr.sa_netnum, 4);
2007 d3_rcv_addr.type = NET_IPX;
2011 sockaddr.sin_family = AF_INET;
2012 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
2013 sockaddr.sin_port = htons(port);
2014 addr = (SOCKADDR *)&sockaddr;
2015 name_length = sizeof(sockaddr);
2016 if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE) ){
2017 ml_printf("Unable to send UDP packet in nw_ConnectToServer()! -- %d\n",WSAGetLastError());
2020 memcpy(d3_rcv_addr.addr, &sockaddr.sin_addr.s_addr, 4);
2021 d3_rcv_addr.port = sockaddr.sin_port;
2022 d3_rcv_addr.type = NET_TCP;
2023 typeless_sock = Unreliable_socket;
2027 ml_printf("Network","Unknown protocol type in nw_ConnectToServer()!\n");
2033 first_sent_req = psnet_get_time();
2034 time_sent_req = psnet_get_time();
2036 //Wait until we get a response from the server or we timeout
2039 PSNET_TOP_LAYER_PROCESS();
2042 FD_SET(typeless_sock, &read_fds);
2044 if(SELECT(0, &read_fds, NULL,NULL,&timeout, PSNET_TYPE_RELIABLE)){
2046 if(SELECT(typeless_sock+1, &read_fds, NULL,NULL,&timeout, PSNET_TYPE_RELIABLE)){
2048 ml_string("selected() in psnet_rel_connect_to_server()");
2050 addrlen = sizeof(SOCKADDR);
2051 bytesin = RECVFROM(typeless_sock,(char *)&ack_header,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
2053 ml_printf("recvfrom returned an error! -- %d\n",WSAGetLastError());
2058 ml_string("received data after select in psnet_rel_connect_to_server()");
2060 ml_string("about to check ack_header.type");
2061 if(ack_header.type == RNT_ACK){
2062 short *acknum = (short *)&ack_header.data;
2063 if(*acknum == CONNECTSEQ){
2064 for(i=1; i<MAXRELIABLESOCKETS; i++){
2065 if(Reliable_sockets[i].status==RNF_UNUSED){
2066 //Add the new connection here.
2067 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
2068 Reliable_sockets[i].connection_type = (ubyte)server_addr->type;
2069 memcpy(&Reliable_sockets[i].net_addr,&d3_rcv_addr,sizeof(net_addr_t));
2070 Reliable_sockets[i].last_packet_received = psnet_get_time();
2071 memcpy(&Reliable_sockets[i].addr,&rcv_addr,sizeof(SOCKADDR));
2072 Reliable_sockets[i].status = RNF_LIMBO;
2074 ml_printf("Succesfully connected to server in nw_ConnectToServer().\n");
2075 //Now send I_AM_HERE packet
2076 conn_header.type = RNT_I_AM_HERE;
2077 conn_header.seq = (ushort)(~CONNECTSEQ);
2078 conn_header.data_len = 0;
2080 First_sent_iamhere = psnet_get_time();
2081 Last_sent_iamhere = psnet_get_time();
2082 int rcode = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
2083 if(rcode == SOCKET_ERROR){
2084 *socket = INVALID_SOCKET;
2085 Reliable_sockets[i].status = RNF_UNUSED;
2086 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
2087 ml_printf("Unable to send packet in nw_ConnectToServer()\n");
2090 Reliable_sockets[i].last_packet_sent = psnet_get_time();
2092 f = psnet_get_time();
2093 while((fl_abs((psnet_get_time() - f))<2) && (Reliable_sockets[i].status != RNF_CONNECTING)){
2100 ml_printf("Out of reliable socket space in nw_ConnectToServer().\n");
2102 } else ml_printf("Received out of sequence ACK in nw_ConnectToServer().\n");
2103 } else ml_printf("Received something that isn't an ACK in nw_ConnectToServer().\n");
2104 } else ml_printf("Received 0 bytes from recvfrom() in nw_ConnectToServer().\n");
2107 if((psnet_get_time()-time_sent_req)>2)
2109 ml_printf("Resending connect request.\n");
2110 int ret = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
2111 if(ret != SOCKET_ERROR){
2112 time_sent_req = psnet_get_time();
2114 ml_printf("Error sending connection request! -- %d\n",WSAGetLastError() );
2119 } while(fl_abs((psnet_get_time() - first_sent_req)) < RELIABLE_CONNECT_TIME);
2122 // returns the ip address of this computer
2124 int psnet_rel_get_ip()
2128 SOCKADDR_IN local_address;
2131 // Get the local host name
2132 memset(&local_address, 0, sizeof(local_address));
2133 ret = gethostname(local, 255 );
2134 if (ret != SOCKET_ERROR ){
2135 // Resolve host name for local address
2136 hostent = gethostbyname((LPSTR)local);
2138 local_address.sin_addr.s_addr = *((u_long FAR *)(hostent->h_addr));
2141 ml_string("SOCKET_ERROR in psnet_rel_get_ip()!");
2143 ml_printf(%s:%d\n", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port)
2144 return local_address.sin_addr.s_addr;
2148 // returns the ip address of this computer
2151 SOCKADDR_IN local_address;
2153 if(Psnet_connection == NETWORK_CONNECTION_DIALUP){
2154 local_address.sin_addr.s_addr = psnet_ras_status();
2155 if(local_address.sin_addr.s_addr == INADDR_NONE){
2156 local_address.sin_addr.s_addr = INADDR_ANY;
2159 // Init local address to zero
2160 local_address.sin_addr.s_addr = INADDR_ANY;
2163 // NOTE: for memeory checkers, do NOT try to free this
2164 ml_printf("psnet_get_ip() reports IP : %s\n", inet_ntoa(local_address.sin_addr));
2166 return local_address.sin_addr.s_addr;
2169 // initialize reliable sockets
2170 int psnet_init_rel_tcp(int port, int should_listen)
2173 SOCKADDR_IN sockaddr;
2175 sockaddr.sin_port = htons((ushort)port);
2176 sockaddr.sin_family = AF_INET;
2178 ml_printf("Setting up reliable sockets.\n");
2180 my_ip = psnet_get_ip();
2182 memcpy(&sockaddr.sin_addr.s_addr, &my_ip, sizeof(uint));
2184 Reliable_UDP_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP );
2185 if(INVALID_SOCKET == Reliable_UDP_socket){
2186 ml_printf("Unable to create reliable UDP socket -- %d\n", WSAGetLastError() );
2189 } else if(bind(Reliable_UDP_socket,(SOCKADDR *)&sockaddr,sizeof(SOCKADDR))!=0){
2190 ml_printf("Unable to bind reliable socket -- %d\n", WSAGetLastError() );
2195 // make any reliable sockets which we create that aren't listening non-blocking sockets
2200 error = ioctlsocket( Reliable_UDP_socket, FIONBIO, &arg );
2201 if ( error == SOCKET_ERROR ) {
2202 ml_printf("Unable to make reliable UDP socket non-blocking -- %d\n", WSAGetLastError() );
2212 // initialize reliable sockets
2213 int psnet_init_rel_ipx(int port, int should_listen)
2219 SOCKADDR_IPX ipx_addr;
2221 memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
2222 ipx_addr.sa_family = AF_IPX;
2223 ipx_addr.sa_socket = htons((ushort)port);
2225 Reliable_IPX_socket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
2226 if(INVALID_SOCKET == Reliable_IPX_socket){
2227 ml_printf("Unable to create reliable IPX socket -- %d\n", WSAGetLastError() );
2230 } else if(bind(Reliable_IPX_socket,(SOCKADDR *)&ipx_addr,sizeof(SOCKADDR))!=0){
2231 ml_printf("Unable to bind reliable IPX socket -- %d\n", WSAGetLastError() );
2236 // make any reliable sockets which we create that aren't listening non-blocking sockets
2241 error = ioctlsocket( Reliable_IPX_socket, FIONBIO, &arg );
2242 if ( error == SOCKET_ERROR ) {
2243 ml_printf("Unable to make reliable IPX socket non-blocking -- %d\n", WSAGetLastError() );
2254 void psnet_rel_close()
2257 PSNET_SOCKET_RELIABLE sock;
2260 for(idx=0; idx<MAXRELIABLESOCKETS; idx++){
2261 if(Reliable_sockets[idx].status != RNF_UNUSED){
2263 psnet_rel_close_socket(&sock);
2268 // ------------------------------------------------------------------------------------------------------
2269 // PACKET BUFFERING FUNCTIONS
2272 // initialize the buffering system
2273 void psnet_buffer_init(network_packet_buffer_list *l)
2277 // blast the buffer clean
2278 memset(l->psnet_buffers, 0, sizeof(network_packet_buffer) * MAX_PACKET_BUFFERS);
2280 // set all buffer sequence #'s to -1
2281 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2282 l->psnet_buffers[idx].sequence_number = -1;
2285 // initialize the sequence #
2286 l->psnet_seq_number = 0;
2287 l->psnet_lowest_id = -1;
2288 l->psnet_highest_id = -1;
2291 // buffer a packet (maintain order!)
2292 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr_t *from)
2297 // find the first empty packet
2298 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2299 if(l->psnet_buffers[idx].sequence_number == -1){
2305 // if we didn't find the buffer, report an overrun
2307 ml_printf("WARNING - Buffer overrun in psnet\n");
2310 memcpy(l->psnet_buffers[idx].data, data, length);
2311 l->psnet_buffers[idx].len = length;
2312 memcpy(&l->psnet_buffers[idx].from_addr, from, sizeof(net_addr_t));
2313 l->psnet_buffers[idx].sequence_number = l->psnet_seq_number;
2315 // keep track of the highest id#
2316 l->psnet_highest_id = l->psnet_seq_number++;
2318 // set the lowest id# for the first time
2319 if(l->psnet_lowest_id == -1){
2320 l->psnet_lowest_id = l->psnet_highest_id;
2325 // get the index of the next packet in order!
2326 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr_t *from)
2331 // if there are no buffers, do nothing
2332 if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
2336 // search until we find the lowest packet index id#
2337 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2338 // if we found the buffer
2339 if(l->psnet_buffers[idx].sequence_number == l->psnet_lowest_id){
2345 // at this point, we should _always_ have found the buffer
2348 // copy out the buffer data
2349 memcpy(data, l->psnet_buffers[idx].data, l->psnet_buffers[idx].len);
2350 *length = l->psnet_buffers[idx].len;
2351 memcpy(from, &l->psnet_buffers[idx].from_addr, sizeof(net_addr_t));
2353 // now we need to cleanup the packet list
2355 // mark the buffer as free
2356 l->psnet_buffers[idx].sequence_number = -1;
2357 l->psnet_lowest_id++;
2362 // -------------------------------------------------------------------------------------------------------
2363 // PSNET 2 FORWARD DEFINITIONS
2366 // if the string is a legally formatted ip string
2367 int psnet_is_valid_numeric_ip(char *ip)
2371 int val1,val2,val3,val4;
2373 // get the first ip value
2375 token = strtok(copy,".");
2379 // get the value of the token
2381 if((val1 < 0) || (val1 > 255)){
2387 token = strtok(NULL,".");
2391 // get the value of the token
2393 if((val2 < 0) || (val2 > 255)){
2399 token = strtok(NULL,".");
2403 // get the value of the token
2405 if((val3 < 0) || (val3 > 255)){
2411 token = strtok(NULL,"");
2415 // get the value of the token
2417 if((val4 < 0) || (val4 > 255)){
2422 // make sure he hasn't entered all 0's
2423 if((val1 == 0) && (val2 == 0) && (val3 == 0) && (val4 == 0)){
2431 // function called from high level FreeSpace code to determine the status of the networking
2432 // code returns one of a handful of macros
2434 DWORD (__stdcall *pRasEnumConnections)(LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections) = NULL;
2435 DWORD (__stdcall *pRasGetConnectStatus)(HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) = NULL;
2436 DWORD (__stdcall *pRasGetProjectionInfo)(HRASCONN hrasconn, RASPROJECTION rasprojection, LPVOID lpprojection, LPDWORD lpcb ) = NULL;
2438 // functions to get the status of a RAS connection
2439 unsigned int psnet_ras_status()
2442 unsigned long size, num_connections, i;
2443 RASCONN rasbuffer[25];
2444 HINSTANCE ras_handle;
2445 unsigned long rasip=0;
2446 RASPPPIP projection;
2447 // int Ras_connected;
2451 // first, call a LoadLibrary to load the RAS api
2452 ras_handle = LoadLibrary( "rasapi32.dll" );
2453 if ( ras_handle == NULL ) {
2457 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, "RasEnumConnectionsA");
2458 if (!pRasEnumConnections) {
2459 FreeLibrary( ras_handle );
2462 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, "RasGetConnectStatusA");
2463 if (!pRasGetConnectStatus) {
2464 FreeLibrary( ras_handle );
2467 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, "RasGetProjectionInfoA");
2468 if (!pRasGetProjectionInfo) {
2469 FreeLibrary( ras_handle );
2473 size = sizeof(rasbuffer);
2474 rasbuffer[0].dwSize = sizeof(RASCONN);
2476 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2478 FreeLibrary( ras_handle );
2482 // JAS: My computer gets to this point, but I have no RAS connections,
2484 if ( num_connections < 1 ) {
2485 ml_string("Found no RAS connections");
2486 FreeLibrary( ras_handle );
2490 ml_printf("Found %d connections", num_connections);
2492 for (i = 0; i < num_connections; i++ ) {
2493 RASCONNSTATUS status;
2496 ml_printf("Connection %d:", i);
2497 ml_printf("Entry Name: %s", rasbuffer[i].szEntryName);
2498 ml_printf("Device Type: %s", rasbuffer[i].szDeviceType);
2499 ml_printf("Device Name: %s", rasbuffer[i].szDeviceName);
2501 // get the connection status
2502 status.dwSize = sizeof(RASCONNSTATUS);
2503 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2505 FreeLibrary( ras_handle );
2509 // get the projection informatiom
2510 size = sizeof(projection);
2511 projection.dwSize = size;
2512 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2514 FreeLibrary( ras_handle );
2518 ml_printf("IP Address: %s", projection.szIpAddress);
2523 FreeLibrary( ras_handle );
2524 rasip = inet_addr(projection.szIpAddress);
2525 if(rasip==INADDR_NONE){
2529 //The ip of the RAS connection
2533 unsigned int psnet_ras_status()
2541 // functions to get the status of a RAS connection
2543 void psnet_ras_status()
2546 unsigned long size, num_connections, i;
2547 RASCONN rasbuffer[25];
2548 HINSTANCE ras_handle;
2552 // first, call a LoadLibrary to load the RAS api
2553 ras_handle = LoadLibrary( NOX("rasapi32.dll") );
2554 if ( ras_handle == NULL ) {
2558 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, NOX("RasEnumConnectionsA"));
2559 if (!pRasEnumConnections) {
2560 FreeLibrary( ras_handle );
2563 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, NOX("RasGetConnectStatusA"));
2564 if (!pRasGetConnectStatus) {
2565 FreeLibrary( ras_handle );
2568 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, NOX("RasGetProjectionInfoA"));
2569 if (!pRasGetProjectionInfo) {
2570 FreeLibrary( ras_handle );
2574 size = sizeof(rasbuffer);
2575 rasbuffer[0].dwSize = sizeof(RASCONN);
2577 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2579 FreeLibrary( ras_handle );
2583 // JAS: My computer gets to this point, but I have no RAS connections,
2585 if ( num_connections < 1 ) {
2586 ml_printf("Found no connections\n" );
2587 FreeLibrary( ras_handle );
2591 ml_printf("Found %d connections\n", num_connections);
2593 for (i = 0; i < num_connections; i++ ) {
2594 RASCONNSTATUS status;
2595 RASPPPIP projection;
2598 ml_printf("Connection %d:\n", i);
2599 ml_printf("Entry Name: %s\n", rasbuffer[i].szEntryName);
2600 ml_printf("Device Type: %s\n", rasbuffer[i].szDeviceType);
2601 ml_printf("Device Name: %s\n", rasbuffer[i].szDeviceName);
2603 // get the connection status
2604 status.dwSize = sizeof(RASCONNSTATUS);
2605 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2607 FreeLibrary( ras_handle );
2611 ml_printf("\tStatus: %s\n", (status.rasconnstate==RASCS_Connected)?"Connected":"Not Connected");
2613 // get the projection informatiom
2614 size = sizeof(projection);
2615 projection.dwSize = size;
2616 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2618 FreeLibrary( ras_handle );
2622 ml_printf("IP Address: %s", projection.szIpAddress));
2627 FreeLibrary( ras_handle );
2631 // set some options on a socket
2632 void psnet_socket_options( SOCKET sock )
2636 int cursize, cursizesize, bufsize;
2638 socklen_t cursize, cursizesize, bufsize;
2641 // Set the mode of the socket to allow broadcasting. We need to be able to broadcast
2642 // when a game is searched for in IPX mode.
2644 if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (LPSTR)&broadcast, sizeof(broadcast) )){
2651 // setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (LPSTR)&broadcast, sizeof(broadcast) );
2653 // try and increase the size of my receive buffer
2654 bufsize = MAX_RECEIVE_BUFSIZE;
2656 // set the current size of the receive buffer
2657 cursizesize = sizeof(int);
2658 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&cursize, &cursizesize);
2659 // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2660 ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&bufsize, sizeof(bufsize));
2661 if ( ret == SOCKET_ERROR ) {
2664 wserr = WSAGetLastError();
2665 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
2669 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&cursize, &cursizesize);
2670 ml_printf("Receive buffer set to %d\n", cursize);
2672 // set the current size of the send buffer
2673 cursizesize = sizeof(int);
2674 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&cursize, &cursizesize);
2675 // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2676 ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&bufsize, sizeof(bufsize));
2677 if ( ret == SOCKET_ERROR ) {
2680 wserr = WSAGetLastError();
2681 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) ){
2685 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&cursize, &cursizesize);
2686 ml_printf("Send buffer set to %d\n", cursize);
2689 // initialize ipx socket
2690 int psnet_init_ipx()
2695 SOCKADDR_IPX sockaddr;
2697 IPX_socket = INVALID_SOCKET;
2699 IPX_socket = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );
2700 if ( IPX_socket == INVALID_SOCKET ) {
2701 Ipx_failure_code = WSAGetLastError();
2702 ml_printf("Error on IPX startup %d\n", Ipx_failure_code);
2707 memset(&sockaddr,0,sizeof(SOCKADDR_IPX));
2708 sockaddr.sa_family = AF_IPX;
2709 sockaddr.sa_socket = htons( Psnet_default_port );
2710 if ( bind(IPX_socket, (SOCKADDR*)&sockaddr, sizeof (SOCKADDR_IPX)) == SOCKET_ERROR) {
2711 Ipx_failure_code = WSAGetLastError();
2712 ml_printf("Couldn't bind IPX socket (%d)! Invalidating IPX\n", Ipx_failure_code );
2716 // set socket options
2717 psnet_socket_options( IPX_socket );
2718 Ipx_can_broadcast = Can_broadcast;
2725 // initialize tcp socket
2726 int psnet_init_tcp()
2728 SOCKADDR_IN sockaddr;
2730 TCP_socket = INVALID_SOCKET;
2732 TCP_socket = socket( AF_INET, SOCK_DGRAM, 0 );
2733 if ( TCP_socket == (int)INVALID_SOCKET ) {
2734 Tcp_failure_code = WSAGetLastError();
2735 ml_printf("Error on TCP startup %d\n", Tcp_failure_code);
2740 memset(&sockaddr,0,sizeof(SOCKADDR_IN));
2741 sockaddr.sin_family = AF_INET;
2742 sockaddr.sin_addr.s_addr = psnet_get_ip();
2743 sockaddr.sin_port = htons( Psnet_default_port );
2744 if ( bind(TCP_socket, (SOCKADDR*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
2745 Tcp_failure_code = WSAGetLastError();
2746 ml_printf("Couldn't bind TCP socket (%d)! Invalidating TCP\n", Tcp_failure_code );
2750 // set socket options
2751 psnet_socket_options( TCP_socket );
2752 Tcp_can_broadcast = Can_broadcast;
2758 // get time in seconds
2759 float psnet_get_time()
2761 return (float)timer_get_milliseconds() / 1000.0f;
2764 // mark a socket as having received data
2765 void psnet_mark_received(PSNET_SOCKET_RELIABLE socket)
2768 if((socket == 0xffffffff) || (socket >= MAXRELIABLESOCKETS)){
2773 Reliable_sockets[socket].last_packet_received = psnet_get_time();