2 * $Logfile: /Freespace2/code/Network/Psnet2.cpp $
7 * C file containing application level network-interface.
10 * Revision 1.1 2002/05/03 03:28:10 root
14 * 25 9/14/99 2:21p Dave
15 * Fixed observer mode joining and ingame stuff.
17 * 24 9/10/99 9:44p Dave
18 * Bumped version # up. Make server reliable connects not have such a huge
21 * 23 9/07/99 4:01p Dave
22 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
23 * does everything properly (setting up address when binding). Remove
24 * black rectangle background from UI_INPUTBOX.
26 * 22 8/26/99 8:51p Dave
27 * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
29 * 21 8/16/99 4:06p Dave
30 * Big honking checkin.
32 * 20 7/26/99 5:50p Dave
33 * Revised ingame join. Better? We'll see....
35 * 19 7/20/99 1:49p Dave
36 * Peter Drake build. Fixed some release build warnings.
38 * 18 7/15/99 9:20a Andsager
39 * FS2_DEMO initial checkin
41 * 17 7/03/99 4:08p Dave
42 * Fixed wss_slots size issues. Fixed potentially nasty bug in low level
45 * 16 6/25/99 5:02p Jasenw
46 * Removed old debug code.
48 * 15 6/07/99 9:51p Dave
49 * Consolidated all multiplayer ports into one.
51 * 14 4/30/99 12:18p Dave
52 * Several minor bug fixes.
54 * 13 4/27/99 5:55p Dave
55 * Fixed Ras_connected bug with VSDK code.
57 * 12 4/27/99 2:59p Dave
58 * Potential fix for reliable socket connection problem.
60 * 11 4/23/99 11:07a Dave
61 * Added lots of debug multi.log output to psnet2
63 * 10 4/12/99 10:07p Dave
64 * Made network startup more forgiving. Added checkmarks to dogfight
65 * screen for players who hit commit.
67 * 9 3/10/99 6:50p Dave
68 * Changed the way we buffer packets for all clients. Optimized turret
69 * fired packets. Did some weapon firing optimizations.
71 * 8 3/09/99 6:24p Dave
72 * More work on object update revamping. Identified several sources of
73 * unnecessary bandwidth.
75 * 7 3/08/99 7:03p Dave
76 * First run of new object update system. Looks very promising.
78 * 6 1/24/99 11:37p Dave
79 * First full rev of beam weapons. Very customizable. Removed some bogus
80 * Int3()'s in low level net code.
82 * 5 1/06/99 2:24p Dave
83 * Stubs and release build fixes.
85 * 4 11/20/98 11:16a Dave
86 * Fixed up IPX support a bit. Making sure that switching modes and
87 * loading/saving pilot files maintains proper state.
89 * 3 11/19/98 4:19p Dave
90 * Put IPX sockets back in psnet. Consolidated all multiplayer config
93 * 2 11/19/98 8:04a Dave
94 * Full support for D3-style reliable sockets. Revamped packet lag/loss
95 * system, made it receiver side and at the lowest possible level.
101 #include <windowsx.h>
107 #include <raserror.h>
113 #include "multiutil.h"
114 #include "multilag.h"
115 #include "osregistry.h"
117 #include "multi_log.h"
118 #include "multi_rate.h"
123 // -------------------------------------------------------------------------------------------------------
124 // PSNET 2 DEFINES/VARS
127 BOOL Psnet_my_addr_valid;
128 net_addr Psnet_my_addr;
130 ubyte Null_address[6];
133 int Can_broadcast; // can we do broadcasting on our socket?
134 int Ipx_can_broadcast = 0;
135 int Tcp_can_broadcast = 0;
141 int Tcp_failure_code = 0;
142 int Ipx_failure_code = 0;
144 int Psnet_connection;
146 ushort Psnet_default_port;
148 // specified their internet connnection type
149 #define NETWORK_CONNECTION_NONE 1
150 #define NETWORK_CONNECTION_DIALUP 2
151 #define NETWORK_CONNECTION_LAN 3
153 // defines and variables to indicate network connection status
154 #define NETWORK_STATUS_NOT_INITIALIZED 1
155 #define NETWORK_STATUS_NO_WINSOCK 2 // winsock failed to initialize
156 #define NETWORK_STATUS_NO_PROTOCOL 3 // TCP/IP doesn't appear to be loaded
157 #define NETWORK_STATUS_NO_RELIABLE 4
158 #define NETWORK_STATUS_RUNNING 5 // everything should be running
160 // defintion of structures that actually leave this machine. psnet_send give us only
161 // the data that we want to send. We will add a header onto this data (packet sequence
162 // number, possibly a checksum). We must include a 2 byte flags variable into both structure
163 // since the receiving end of this packet must know whether or not to checksum the packet.
165 #define MAX_TOP_LAYER_PACKET_SIZE 680
167 // use the pack pragma to pack these structures to 2 byte aligment. Really only needed for
169 #define MAX_PACKET_BUFFERS 75
171 #pragma pack(push, 2)
173 // definition for a non-checksum packet
174 typedef struct network_packet
178 ubyte data[MAX_TOP_LAYER_PACKET_SIZE];
179 } network_naked_packet;
181 // structure definition for our packet buffers
182 typedef struct network_packet_buffer
187 ubyte data[MAX_TOP_LAYER_PACKET_SIZE];
188 } network_packet_buffer;
190 // struct for a bunch of network packet buffers
191 typedef struct network_packet_buffer_list {
192 network_packet_buffer psnet_buffers[MAX_PACKET_BUFFERS];
193 int psnet_seq_number;
195 int psnet_highest_id;
196 } network_packet_buffer_list;
201 #define MAXHOSTNAME 128
203 #define MAX_RECEIVE_BUFSIZE 4096 // 32 K, eh?
204 #define MAX_SEND_RETRIES 20 // number of retries when sending would block
205 #define MAX_LINGER_TIME 0 // in seconds -- when lingering to close a socket
208 //*******************************
209 #define MAXNETBUFFERS 150 // Maximum network buffers (For between network and upper level functions, which is
210 // required in case of out of order packets
211 #define NETRETRYTIME 0.75f // Time after sending before we resend
212 #define MIN_NET_RETRYTIME 0.2f
213 #define NETTIMEOUT 30 // Time after receiving the last packet before we drop that user
214 #define NETHEARTBEATTIME 3 // How often to send a heartbeat
215 #define MAXRELIABLESOCKETS 40 // Max reliable sockets to open at once...
216 #define NETBUFFERSIZE 600 // Max size of a network packet
218 #define RELIABLE_CONNECT_TIME 7 // how long we'll wait for a response when doing a reliable connect
220 int Nettimeout = NETTIMEOUT;
222 // Reliable packet stuff
223 #define RNT_ACK 1 // ACK Packet
224 #define RNT_DATA 2 // Data Packet
225 #define RNT_DATA_COMP 3 // Compressed Data Packet
226 #define RNT_REQ_CONN 4 // Requesting a connection
227 #define RNT_DISCONNECT 5 // Disconnecting a connection
228 #define RNT_HEARTBEAT 6 // Heartbeat -- send every NETHEARTBEATTIME
229 #define RNT_I_AM_HERE 7
231 #pragma pack(push,r_udp)
234 ubyte type; // packet type
236 ushort seq; // sequence packet 0-65535 used for ACKing also
237 ushort data_len; // length of data
238 float send_time; // Time the packet was sent, if an ACK the time the packet being ACK'd was sent.
239 ubyte data[NETBUFFERSIZE]; // Packet data
242 #define RELIABLE_PACKET_HEADER_ONLY_SIZE (sizeof(reliable_header)-NETBUFFERSIZE)
243 #define MAX_PING_HISTORY 10
246 ubyte buffer[NETBUFFERSIZE];
248 } reliable_net_sendbuffer;
251 ubyte buffer[NETBUFFERSIZE];
252 } reliable_net_rcvbuffer;
255 reliable_net_sendbuffer *sbuffers[MAXNETBUFFERS]; // This is an array of pointers for quick sorting
256 unsigned short ssequence[MAXNETBUFFERS]; // This is the sequence number of the given packet
257 float timesent[MAXNETBUFFERS];
258 int send_len[MAXNETBUFFERS];
259 reliable_net_rcvbuffer *rbuffers[MAXNETBUFFERS];
260 int recv_len[MAXNETBUFFERS];
261 unsigned short rsequence[MAXNETBUFFERS]; // This is the sequence number of the given packet
262 float last_packet_received; // For a given connection, this is the last packet we received
263 float last_packet_sent;
264 SOCKADDR addr; // SOCKADDR of our peer
265 ushort status; // Status of this connection
266 unsigned short oursequence; // This is the next sequence number the application is expecting
267 unsigned short theirsequence; // This is the next sequence number the peer is expecting
268 net_addr net_addr; // A FS2 network address structure
269 ubyte connection_type; // IPX, IP, modem, etc.
270 float pings[MAX_PING_HISTORY];
272 unsigned int num_ping_samples;
276 reliable_socket Reliable_sockets[MAXRELIABLESOCKETS];
278 // sockets for IPX and TCP (unreliable)
282 // the sockets that the game will use when selecting network type
283 SOCKET Unreliable_socket = INVALID_SOCKET;
286 // SOCKET Reliable_UDP_socket = INVALID_SOCKET;
287 // SOCKET Reliable_IPX_socket = INVALID_SOCKET;
289 float First_sent_iamhere = 0;
290 float Last_sent_iamhere = 0;
292 #define CONNECTSEQ 0x142 // Magic number for starting a connection, just so it isn't 0
294 unsigned int Serverconn = 0xffffffff;
296 #pragma pack(pop,r_udp)
297 //*******************************
300 network_packet_buffer_list Psnet_top_buffers[PSNET_NUM_TYPES];
302 // -------------------------------------------------------------------------------------------------------
303 // PSNET 2 FORWARD DECLARATIONS
306 // if the string is a legally formatted ip string
307 int psnet_is_valid_numeric_ip(char *ip);
309 // functions to get the status of a RAS connection
310 unsigned int psnet_ras_status();
312 // set some options on a socket
313 void psnet_socket_options( SOCKET sock );
315 // initialize ipx socket
316 int psnet_init_ipx();
318 // initialize tcp socket
319 int psnet_init_tcp();
321 // get time in seconds
322 float psnet_get_time();
324 // returns the ip address of this machine. use for calling bind() with to associate with the proper
325 // IP address and network device.
328 // initialize reliable sockets
329 int psnet_init_rel_tcp(int port, int should_listen);
330 int psnet_init_rel_ipx(int port, int should_listen);
332 // shutdown reliable sockets
333 void psnet_rel_close();
335 // initialize the buffering system
336 void psnet_buffer_init(network_packet_buffer_list *l);
338 // buffer a packet (maintain order!)
339 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr *from);
341 // get the index of the next packet in order!
342 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr *from);
345 // -------------------------------------------------------------------------------------------------------
346 // PSNET 2 TOP LAYER FUNCTIONS - these functions simply buffer and store packets based upon type (see PSNET_TYPE_* defines)
349 // wrappers around select() and recvfrom() for lagging/losing data
350 int RECVFROM(SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen, int psnet_type)
352 network_packet_buffer_list *l;
358 Assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
359 if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
362 l = &Psnet_top_buffers[psnet_type];
364 // if we have no buffer! The user should have made sure this wasn't the case by calling SELECT()
365 ret = psnet_buffer_get_next(l, (ubyte*)buf, &ret_len, &addr);
371 // otherwise, stuff the outgoing data
372 switch ( Socket_type ) {
374 ((SOCKADDR_IPX*)from)->sa_socket = htons(addr.port);
375 memcpy(((SOCKADDR_IPX*)from)->sa_nodenum, addr.addr, 6);
376 memcpy(((SOCKADDR_IPX*)from)->sa_netnum, addr.net_id, 4);
377 ((SOCKADDR_IPX*)from)->sa_family = AF_IPX;
378 *fromlen = sizeof(SOCKADDR_IPX);
382 ((SOCKADDR_IN*)from)->sin_port = htons(addr.port);
383 memcpy(&((SOCKADDR_IN*)from)->sin_addr.S_un.S_addr, addr.addr, 4);
384 ((SOCKADDR_IN*)from)->sin_family = AF_INET;
385 *fromlen = sizeof(SOCKADDR_IN);
397 // wrappers around select() and recvfrom() for lagging/losing data
398 int SELECT(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout, int psnet_type)
400 network_packet_buffer_list *l;
402 // if this is a check for writability, just return the select
403 if(writefds != NULL){
404 return select(nfds, readfds, writefds, exceptfds, timeout);
408 Assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
409 if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
412 l = &Psnet_top_buffers[psnet_type];
414 // do we have any buffers in here?
415 if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
423 // wrappers around sendto to sorting through different packet types
424 int SENDTO(SOCKET s, char * buf, int len, int flags, sockaddr *to, int tolen, int psnet_type)
426 char outbuf[MAX_TOP_LAYER_PACKET_SIZE + 150];
429 outbuf[0] = (char)psnet_type;
430 memcpy(&outbuf[1], buf, len);
432 // is the socket writeable?
435 return sendto(s, outbuf, len + 1, flags, (SOCKADDR*)to, tolen);
438 // call this once per frame to read everything off of our socket
439 void PSNET_TOP_LAYER_PROCESS()
442 SOCKADDR_IN ip_addr; // UDP/TCP socket structure
443 SOCKADDR_IPX ipx_addr; // IPX socket structure
446 int read_len, from_len;
448 network_naked_packet packet_read;
450 // clear the addresses to remove compiler warnings
451 memset(&ip_addr, 0, sizeof(SOCKADDR_IN));
452 memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
454 if ( Network_status != NETWORK_STATUS_RUNNING ) {
455 ml_printf("Network ==> socket not inited in PSNET_TOP_LAYER_PROCESS\n");
460 // check if there is any data on the socket to be read. The amount of data that can be
461 // atomically read is stored in len.
464 FD_SET( Unreliable_socket, &rfds );
468 if ( select( -1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
469 ml_printf("Error %d doing a socket select on read\n", WSAGetLastError());
473 // if the read file descriptor is not set, then bail!
474 if ( !FD_ISSET(Unreliable_socket, &rfds) ){
478 // get data off the socket and process
479 read_len = SOCKET_ERROR;
480 switch ( Socket_type ) {
482 from_len = sizeof(SOCKADDR_IPX);
483 read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0, (SOCKADDR*)&ipx_addr, &from_len);
487 from_len = sizeof(SOCKADDR_IN);
488 read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0, (SOCKADDR*)&ip_addr, &from_len);
496 // set the from_addr for storage into the packet buffer structure
497 from_addr.type = Socket_type;
499 switch ( Socket_type ) {
501 from_addr.port = ntohs( ipx_addr.sa_socket );
502 memcpy(from_addr.addr, ipx_addr.sa_nodenum, 6 );
503 memcpy(from_addr.net_id, ipx_addr.sa_netnum, 4 );
507 from_addr.port = ntohs( ip_addr.sin_port );
508 memset(from_addr.addr, 0x00, 6);
509 memcpy(from_addr.addr, &ip_addr.sin_addr.S_un.S_addr, 4);
518 if ( read_len == SOCKET_ERROR ) {
519 // int x = WSAGetLastError();
520 ml_printf("Socket error on socket_get_data()");
524 // determine the packet type
525 int packet_type = packet_read.data[0];
526 // mprintf(("TOP LAYER PACKET %d!\n", packet_type));
527 if((packet_type < 0) || (packet_type >= PSNET_NUM_TYPES)){
531 psnet_buffer_packet(&Psnet_top_buffers[packet_type], packet_read.data + 1, read_len - 1, &from_addr);
537 // -------------------------------------------------------------------------------------------------------
541 // initialize psnet to use the specified port
542 void psnet_init( int protocol, int port_num )
544 char *internet_connection;
550 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
554 // GAME PORT INITIALIZATION STUFF
555 if ( Network_status == NETWORK_STATUS_RUNNING ){
556 ml_string("Skipping psnet_init() because network already running");
560 internet_connection = os_config_read_string(NULL, "NetworkConnection", "none");
561 if ( !stricmp(internet_connection, NOX("dialup")) ) {
562 ml_string("psnet_init() detected dialup connection");
564 Psnet_connection = NETWORK_CONNECTION_DIALUP;
565 } else if ( !stricmp(internet_connection, NOX("lan")) ) {
566 ml_string("psnet_init() detected lan connection");
568 Psnet_connection = NETWORK_CONNECTION_LAN;
570 ml_string("psnet_init() detected no connection");
572 Psnet_connection = NETWORK_CONNECTION_NONE;
575 Network_status = NETWORK_STATUS_NO_WINSOCK;
576 if (WSAStartup(0x101, &wsa_data )){
580 // get the port for running this game on. Be careful that it cannot be out of bounds
581 Psnet_default_port = DEFAULT_GAME_PORT;
582 if ( (port_num > 1023) && (port_num < USHRT_MAX) ) {
583 Psnet_default_port = (ushort)port_num;
586 // initialize TCP now
588 if(!psnet_init_tcp()){
589 ml_printf("Error on TCP startup %d\n", Tcp_failure_code);
593 if(!psnet_init_rel_tcp(Psnet_default_port + 1, 0)){
594 ml_printf("Network", "Error on TCP startup %d\n", Tcp_failure_code);
600 // clear reliable sockets
601 reliable_socket *rsocket;
603 for(j=0; j<MAXRELIABLESOCKETS; j++){
604 rsocket=&Reliable_sockets[j];
605 memset(rsocket,0,sizeof(reliable_socket));
608 // initialize IPX not
610 if(!psnet_init_ipx()){
611 ml_printf("Network", "Error on IPX startup %d\n", Ipx_failure_code);
615 if(!psnet_init_rel_ipx(Psnet_default_port + 1, 0)){
616 ml_printf("Network", "Error on IPX startup %d\n", Ipx_failure_code);
622 // determine if we've successfully initialized the protocol we want
623 if(!Tcp_active && !Ipx_active){
624 Network_status = NETWORK_STATUS_NO_PROTOCOL;
626 ml_string("No protocol in psnet_init()!");
629 // specified network timeout
630 Nettimeout = NETTIMEOUT;
631 if(Cmdline_timeout > 0){
632 Nettimeout = Cmdline_timeout;
638 if(Network_status != NETWORK_STATUS_NO_PROTOCOL){
639 // set network to be running
640 Network_status = NETWORK_STATUS_RUNNING;
642 // determine if our socket can broadcast
643 Can_broadcast = Tcp_can_broadcast || Ipx_can_broadcast;
645 // initialize all packet type buffers
646 for(idx=0; idx<PSNET_NUM_TYPES; idx++){
647 psnet_buffer_init(&Psnet_top_buffers[idx]);
655 if ( Network_status != NETWORK_STATUS_RUNNING ){
659 WSACancelBlockingCall();
661 if ( TCP_socket != INVALID_SOCKET ) {
662 shutdown( TCP_socket, 1 );
663 closesocket( TCP_socket );
666 if ( IPX_socket != INVALID_SOCKET ) {
667 shutdown( IPX_socket, 1 );
668 closesocket( IPX_socket );
672 //Warning( LOCATION, "Error closing wsock!\n" );
675 // close down all reliable sockets - this forces them to
676 // send a disconnect to any remote machines
679 Network_status = NETWORK_STATUS_NOT_INITIALIZED;
682 // set the protocol to use
683 int psnet_use_protocol( int protocol )
686 SOCKADDR_IPX ipx_addr;
689 // zero out my address
690 Psnet_my_addr_valid = 0;
691 memset( &Psnet_my_addr, 0, sizeof(Psnet_my_addr) );
693 // wait until we choose a protocol to determine if we can broadcast
696 ml_string("In psnet_use_protocol()");
698 switch ( protocol ) {
700 ml_string("psnet_use_protocol() selecting IPX");
702 // assign the IPX_* sockets to the socket values used elsewhere
703 Unreliable_socket = IPX_socket;
705 Can_broadcast = Ipx_can_broadcast;
707 ml_printf("Psnet : IPX broadcast\n");
710 // get the socket name for the IPX_socket, and put it into My_addr
711 len = sizeof(SOCKADDR_IPX);
712 if ( getsockname(IPX_socket, (SOCKADDR *)&ipx_addr, &len) == SOCKET_ERROR ) {
713 ml_printf("Unable to get sock name for IPX unreliable socket (%d)\n", WSAGetLastError() );
717 memcpy(Psnet_my_addr.net_id, ipx_addr.sa_netnum, 4);
718 memcpy(Psnet_my_addr.addr, ipx_addr.sa_nodenum, 6);
719 Psnet_my_addr.port = Psnet_default_port;
721 ml_printf("Psnet using - NET_IPX\n");
725 if ( Network_status != NETWORK_STATUS_RUNNING ){
726 ml_string("Network_status != NETWORK_STATUS_RUNNING in NET_TCP in psnet_use_protocol()");
730 // assign the TCP_* sockets to the socket values used elsewhere
731 Unreliable_socket = TCP_socket;
733 Can_broadcast = Tcp_can_broadcast;
735 ml_printf("Psnet : TCP broadcast\n");
738 // get the socket name for the IPX_socket, and put it into My_addr
739 len = sizeof(SOCKADDR_IN);
740 if ( getsockname(TCP_socket, (SOCKADDR *)&ip_addr, &len) == SOCKET_ERROR ) {
741 ml_printf("Unable to get sock name for TCP unreliable socket (%d)\n", WSAGetLastError() );
746 memset(Psnet_my_addr.net_id, 0, 4);
747 memcpy(Psnet_my_addr.addr, &ip_addr.sin_addr, 6);
748 Psnet_my_addr.port = Psnet_default_port;
750 ml_printf("Psnet using - NET_TCP\n");
758 Psnet_my_addr.type = protocol;
759 Socket_type = protocol;
764 // get the status of the network
765 int psnet_get_network_status()
767 // first case is when "none" is selected
768 if ( Psnet_connection == NETWORK_CONNECTION_NONE ) {
769 return NETWORK_ERROR_NO_TYPE;
772 // first, check the connection status of the network
773 if ( Network_status == NETWORK_STATUS_NO_WINSOCK )
774 return NETWORK_ERROR_NO_WINSOCK;
776 if ( Network_status == NETWORK_STATUS_NO_PROTOCOL ){
777 return NETWORK_ERROR_NO_PROTOCOL;
780 // network is running -- be sure that the RAS people know to connect if they currently cannot.
782 if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
783 // if on a dialup connection, be sure that RAS is active.
784 if ( !Ras_connected ) {
785 return NETWORK_ERROR_CONNECT_TO_ISP;
787 } else if ( Psnet_connection == NETWORK_CONNECTION_LAN ) {
788 // if on a LAN, and they have a dialup connection active, return error to indicate that they need
789 // to pick the right connection type
790 if ( Ras_connected ) {
791 return NETWORK_ERROR_LAN_AND_RAS;
794 return NETWORK_ERROR_NONE;
797 // convert a net_addr to a string
798 char* psnet_addr_to_string( char * text, net_addr * address )
801 if ( Network_status != NETWORK_STATUS_RUNNING ) {
802 strcpy( text, XSTR("[no networking]",910) );
808 switch ( address->type ) {
810 sprintf(text, "%x %x %x %x: %x %x %x %x %x %x", address->net_id[0],
823 memcpy(&temp_addr.s_addr, address->addr, 4);
824 strcpy( text, inet_ntoa(temp_addr) );
836 // convert a string to a net addr
837 void psnet_string_to_addr( net_addr * address, char * text )
840 char str[255], *c, *port;
843 if ( Network_status != NETWORK_STATUS_RUNNING ) {
844 strcpy( text, XSTR("[no networking]",910) );
848 // copy the text string to local storage to look for ports
849 Assert( strlen(text) < 255 );
851 c = strrchr(str, ':');
858 switch ( address->type ) {
860 Int3(); // no support for this yet
864 addr.s_addr = inet_addr(str);
865 // if we get INADDR_NONE returns, then we need to try and resolve the host
867 if ( addr.s_addr == INADDR_NONE ) {
868 he = gethostbyname( str );
869 // returns a non-null pointer if successful, so get the address
871 addr.s_addr = ((in_addr *)(he->h_addr))->s_addr; // this is the address in network byte order
873 addr.s_addr = INADDR_NONE;
877 memset(address->addr, 0x00, 6);
878 memcpy(address->addr, &addr.s_addr, 4);
880 address->port = (ushort)(atoi(port));
891 // compare 2 addresses
892 int psnet_same( net_addr * a1, net_addr * a2 )
894 return !memcmp(a1->addr, a2->addr, 6);
897 // send data unreliably
898 int psnet_send( net_addr * who_to, void * data, int len, int np_index )
900 // send data unreliably
902 SOCKADDR_IN sockaddr; // UDP/TCP socket structure
903 SOCKADDR_IPX ipx_addr; // IPX socket structure
905 ubyte iaddr[6], *send_data;
908 struct timeval timeout;
910 // always use the reliable socket
911 send_sock = Unreliable_socket;
913 if ( Network_status != NETWORK_STATUS_RUNNING ) {
914 ml_printf("Network ==> Socket not inited in psnet_send\n");
918 if ( psnet_same( who_to, &Psnet_my_addr) ){
922 memset(iaddr, 0x00, 6);
923 memcpy(iaddr, who_to->addr, 6);
925 if ( memcmp(iaddr, Null_address, 6) == 0) {
926 ml_printf("Network ==> send to address is 0 in psnet_send\n");
933 ml_printf("Network ==> destination port %d invalid in psnet_send\n", port);
937 // stuff the data with the type
938 send_data = (ubyte*)data;
942 FD_SET( send_sock, &wfds );
946 if ( SELECT( -1, NULL, &wfds, NULL, &timeout, PSNET_TYPE_UNRELIABLE) == SOCKET_ERROR ) {
947 ml_printf("Error on blocking select for write %d\n", WSAGetLastError() );
951 // if the write file descriptor is not set, then bail!
952 if ( !FD_ISSET(send_sock, &wfds ) ){
957 switch ( who_to->type ) {
959 ipx_addr.sa_socket = htons(port);
960 ipx_addr.sa_family = AF_IPX;
961 memcpy(ipx_addr.sa_nodenum, iaddr, 6);
962 memcpy(ipx_addr.sa_netnum, who_to->net_id, 4);
964 ret = SENDTO(send_sock, (char *)send_data, send_len, 0, (SOCKADDR*)&ipx_addr, sizeof(ipx_addr), PSNET_TYPE_UNRELIABLE);
966 multi_rate_add(np_index, "ipx", send_len);
967 if ( (ret != SOCKET_ERROR) && (ret != send_len) ){
968 // ml_printf("requested to send %d bytes -- sent %d instead!!!\n", send_len, ret);
973 sockaddr.sin_family = AF_INET;
974 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
975 sockaddr.sin_port = htons(port);
977 multi_rate_add(np_index, "udp(h)", send_len + UDP_HEADER_SIZE);
978 multi_rate_add(np_index, "udp", send_len);
979 ret = SENDTO( send_sock, (char *)send_data, send_len, 0, (SOCKADDR*)&sockaddr, sizeof(sockaddr), PSNET_TYPE_UNRELIABLE );
983 Assert(0); // unknown protocol
988 if ( ret != SOCKET_ERROR ) {
991 //Warning( LOCATION, "Couldn't send data (0x%x)!\n", WSAGetLastError() );
995 // get data from the unreliable socket
996 int psnet_get( void * data, net_addr * from_addr )
1000 // try and get a free buffer and return its size
1001 if(psnet_buffer_get_next(&Psnet_top_buffers[PSNET_TYPE_UNRELIABLE], (ubyte*)data, &buffer_size, from_addr)){
1009 // broadcast data on unreliable socket
1010 int psnet_broadcast( net_addr * who_to, void * data, int len )
1012 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1013 ml_printf("Network ==> Socket not inited in psnet_broadcast\n");
1017 if ( !Can_broadcast ) {
1018 ml_printf("Cannot broadcast -- returning without doing anything\n");
1022 ubyte broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1024 // broadcasting works on a local subnet which is all we really want to do for now anyway.
1025 // we might keep this in as an option for freespace later.
1026 switch ( who_to->type ) {
1029 memcpy(who_to->addr, broadcast, 6);
1030 psnet_send(who_to, data, len);
1038 // flush all sockets
1041 ubyte data[MAX_TOP_LAYER_PACKET_SIZE + 250];
1044 while ( psnet_get( data, &from_addr ) > 0 ) ;
1047 // if the passed string is a valid IP string
1048 int psnet_is_valid_ip_string( char *ip_string, int allow_port )
1051 struct hostent *host_ent;
1054 // our addresses may have ports, so make local copy and remove port number
1055 Assert( strlen(ip_string) < 255 );
1056 strcpy(str, ip_string);
1057 c = strrchr(str, ':');
1062 addr.s_addr = inet_addr(ip_string);
1063 if ( addr.s_addr != INADDR_NONE ){
1064 // make sure the ip string is a valid format string
1065 if(psnet_is_valid_numeric_ip(ip_string)){
1070 // try name resolution
1071 host_ent = gethostbyname( ip_string );
1076 // valid host entry so return 1;
1081 // -------------------------------------------------------------------------------------------------------
1082 // PSNET 2 RELIABLE SOCKET FUNCTIONS
1086 int psnet_rel_ping_compare( const void *arg1, const void *arg2 )
1088 float *ping1 = (float *)arg1;
1089 float *ping2 = (float *)arg2;
1091 if(*ping1==*ping2) return 0;
1092 else if(*ping1>*ping2) return 1;
1093 else if(*ping1<*ping2) return -1;
1098 void psnet_rel_send_ack(SOCKADDR *raddr, unsigned int sig, ubyte link_type, float time_sent)
1101 reliable_header ack_header;
1102 ack_header.type = RNT_ACK;
1103 ack_header.data_len = sizeof(unsigned int);
1104 ack_header.send_time = time_sent;
1105 memcpy(&ack_header.data,&sig,sizeof(unsigned int));
1106 switch (link_type) {
1109 ml_string("No IPX in rel_send_ack()");
1112 ret = SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1116 ml_string("No TCP in rel_send_ack()");
1119 ret = SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1122 ml_string("Unknown protocol type in nw_SendReliable()");
1128 // function to shutdown and close the given socket. It takes a couple of things into consideration
1129 // when closing, such as possibly reiniting reliable sockets if they are closed here.
1130 void psnet_rel_close_socket( PSNET_SOCKET_RELIABLE *sockp )
1132 reliable_header diss_conn_header;
1134 // if the socket is out of range
1135 if(*sockp>=MAXRELIABLESOCKETS)
1137 ml_printf("Invalid socket id passed to nw_NewCloseSocket() -- %d\n",*sockp);
1140 ml_printf("Closing socket %d\n",*sockp);
1142 // go through every buffer and "free it up(tm)"
1144 for(i=0;i<MAXNETBUFFERS;i++){
1145 if(Reliable_sockets[*sockp].rbuffers[i]){
1146 if(Reliable_sockets[*sockp].rbuffers[i] != NULL){
1147 free(Reliable_sockets[*sockp].rbuffers[i]);
1149 Reliable_sockets[*sockp].rbuffers[i] = NULL;
1150 Reliable_sockets[*sockp].rsequence[i] = 0;
1152 if(Reliable_sockets[*sockp].sbuffers[i]){
1153 if(Reliable_sockets[*sockp].sbuffers[i] != NULL){
1154 free(Reliable_sockets[*sockp].sbuffers[i]);
1156 Reliable_sockets[*sockp].sbuffers[i] = NULL;
1157 Reliable_sockets[*sockp].rsequence[i] = 0;
1161 // send a disconnect packet to the socket on the other end
1162 diss_conn_header.type = RNT_DISCONNECT;
1163 diss_conn_header.seq = CONNECTSEQ;
1164 diss_conn_header.data_len = 0;
1165 if(*sockp==Serverconn){
1166 Serverconn = 0xffffffff;
1168 switch ( Reliable_sockets[*sockp].connection_type ) {
1173 SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1179 SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1182 ml_printf("Unknown protocol type in nw_CloseSocket()!\n");
1186 memset(&Reliable_sockets[*sockp],0,sizeof(reliable_socket));
1187 Reliable_sockets[*sockp].status = RNF_UNUSED;
1190 // function to check the status of the reliable socket and try to re-initialize it if necessary.
1191 // win95 seems to have trouble doing a reinit of the socket immediately after close, so this
1192 // function exists to check the status, and reinitialize if we need to
1193 int psnet_rel_check()
1198 // send data reliably
1199 int psnet_rel_send(PSNET_SOCKET_RELIABLE socketid, ubyte *data, int length, int np_index)
1203 reliable_socket *rsocket;
1205 if(socketid >= MAXRELIABLESOCKETS){
1206 ml_printf("Invalid socket id passed to psnet_rel_send() -- %d\n",socketid);
1210 Assert(length<sizeof(reliable_header));
1213 rsocket=&Reliable_sockets[socketid];
1214 if(rsocket->status!=RNF_CONNECTED) {
1215 //We can't send because this isn't a connected reliable socket.
1216 ml_printf("Can't send packet because of status %d in nw_SendReliable(). socket = %d\n",rsocket->status,socketid);
1220 // Add the new packet to the sending list and send it.
1221 for(i=0;i<MAXNETBUFFERS;i++){
1222 if(NULL==rsocket->sbuffers[i]){
1223 reliable_header send_header;
1224 int send_this_packet=1;
1226 rsocket->send_len[i] = length;
1227 rsocket->sbuffers[i] = (reliable_net_sendbuffer *)malloc(sizeof(reliable_net_sendbuffer));
1229 memcpy(rsocket->sbuffers[i]->buffer,data,length);
1231 send_header.seq = rsocket->theirsequence;
1232 rsocket->ssequence[i] = rsocket->theirsequence;
1234 memcpy(send_header.data,data,length);
1235 send_header.data_len = (ushort)length;
1236 send_header.type = RNT_DATA;
1237 send_header.send_time = psnet_get_time();
1238 // SOCKADDR_IN * rsockaddr = (SOCKADDR_IN *)&rsocket->addr;
1240 if (send_this_packet){
1241 switch ( rsocket->connection_type ){
1246 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1252 multi_rate_add(np_index, "tcp(h)", RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i]);
1253 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1256 ml_printf("Unknown protocol type in nw_SendReliable()!\n");
1261 if((bytesout==SOCKET_ERROR)&&(WSAEWOULDBLOCK==WSAGetLastError())){
1262 //This will cause it to try to send again next frame. (or sooner)
1263 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1265 rsocket->timesent[i] = psnet_get_time();
1269 rsocket->theirsequence++;
1273 ml_printf("PSNET RELIABLE SEND BUFFER OVERRUN. socket = %d\n",socketid);
1279 // -1 socket not connected
1280 // 0 No packet ready to receive
1281 // >0 Buffer filled with the number of bytes recieved
1282 int psnet_rel_get(PSNET_SOCKET socketid, ubyte *buffer, int max_len)
1286 reliable_socket *rsocket = NULL;
1288 if(socketid >= MAXRELIABLESOCKETS){
1289 ml_printf("Invalid socket id passed to nw_NewReceiveReliable() -- %d\n",socketid);
1292 rsocket = &Reliable_sockets[socketid];
1293 if( (RNF_CONNECTED!=rsocket->status) && (RNF_LIMBO!=rsocket->status) ){
1294 ml_printf("Can't receive packet because it isn't connected in nw_ReceiveReliable(). socket = %d\n",socketid);
1297 //If the buffer position is the position we are waiting for, fill in
1298 //the buffer we received in the call to this function and return true
1300 for(i=0; i<MAXNETBUFFERS; i++){
1301 if((rsocket->rsequence[i] == rsocket->oursequence) && rsocket->rbuffers[i]){
1302 memcpy(buffer,rsocket->rbuffers[i]->buffer, rsocket->recv_len[i]);
1303 free(rsocket->rbuffers[i]);
1304 rsocket->rbuffers[i] = NULL;
1305 rsocket->rsequence[i] = 0;
1306 rsocket->oursequence++;
1307 return rsocket->recv_len[i];
1314 // process all active reliable sockets
1315 void psnet_rel_work()
1319 int max_len = NETBUFFERSIZE;
1322 static reliable_header rcv_buff;
1323 static SOCKADDR rcv_addr;
1325 int addrlen = sizeof(SOCKADDR);
1326 unsigned int rcvid;//The id of who we actually received a packet from, as opposed to socketid parm
1330 PSNET_TOP_LAYER_PROCESS();
1332 // negotitate initial connection with the server
1333 reliable_socket *rsocket = NULL;
1334 if(Serverconn != 0xffffffff){
1335 //Check to see if we need to send a packet out.
1336 if((Reliable_sockets[Serverconn].status==RNF_LIMBO) && ((Serverconn != 0xffffffff) && fl_abs((psnet_get_time() - Last_sent_iamhere))>NETRETRYTIME) ){
1337 reliable_header conn_header;
1338 //Now send I_AM_HERE packet
1339 conn_header.type = RNT_I_AM_HERE;
1340 conn_header.seq = (ushort)(~CONNECTSEQ);
1341 conn_header.data_len = 0;
1342 Last_sent_iamhere = psnet_get_time();
1343 int ret = SOCKET_ERROR;
1344 switch ( Reliable_sockets[Serverconn].connection_type ) {
1347 ml_printf("Unable to use this network connection type in nw_WorkReliable()\n");
1351 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1355 ml_printf("Unable to use this network connection type in nw_WorkReliable()\n");
1359 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1362 ml_printf("Unknown protocol type in nw_WorkReliable()!\n");
1367 if((ret == SOCKET_ERROR) && (WSAEWOULDBLOCK == WSAGetLastError())){
1368 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time()-NETRETRYTIME;
1370 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time();
1376 net_addr d3_rcv_addr;
1377 SOCKADDR_IN *rcvaddr,*rsockaddr;
1378 int ipx_has_data = 0;
1379 int udp_has_data = 0;
1383 if(Ipx_active && (Socket_type == NET_IPX)){
1385 FD_SET(Unreliable_socket, &read_fds);
1386 ipx_has_data = SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1388 if(Tcp_active && (Socket_type == NET_TCP)){
1390 FD_SET(Unreliable_socket, &read_fds);
1391 udp_has_data = SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1394 addrlen = sizeof(SOCKADDR);
1396 SOCKADDR_IPX *ipx_addr = (SOCKADDR_IPX *)&rcv_addr;
1397 memset(&d3_rcv_addr,0,sizeof(net_addr));
1398 memset(&rcv_addr,0,sizeof(SOCKADDR));
1399 bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1400 memcpy(d3_rcv_addr.addr, ipx_addr->sa_nodenum, 6);
1401 memcpy(d3_rcv_addr.net_id, ipx_addr->sa_netnum, 4);
1402 d3_rcv_addr.type = NET_IPX;
1403 link_type = NET_IPX;
1404 } else if(udp_has_data){
1405 SOCKADDR_IN *tcp_addr = (SOCKADDR_IN *)&rcv_addr;
1406 memset(&d3_rcv_addr,0,sizeof(net_addr));
1407 memset(&rcv_addr,0,sizeof(SOCKADDR));
1408 bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header), 0, (SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1409 memcpy(d3_rcv_addr.addr, &tcp_addr->sin_addr.s_addr, 4);
1410 d3_rcv_addr.port = tcp_addr->sin_port;
1411 d3_rcv_addr.type = NET_TCP;
1412 link_type = NET_TCP;
1414 //Neither socket had data waiting
1419 ml_printf("recvfrom returned an error! -- %d\n",WSAGetLastError());
1420 //Int3();//See Kevin
1424 //Someone wants to connect, so find a slot
1425 if(rcv_buff.type == RNT_REQ_CONN){
1426 for(i=1; i<MAXRELIABLESOCKETS; i++){
1427 if( (Reliable_sockets[i].status == RNF_CONNECTED) || (Reliable_sockets[i].status == RNF_LIMBO) ){
1428 //if(memcmp(&rcv_addr,&reliable_sockets[i].addr,sizeof(SOCKADDR))==0)
1429 if(memcmp(&d3_rcv_addr, &Reliable_sockets[i].net_addr, sizeof(net_addr)) == 0){
1430 //We already have a reliable link to this user, so we will ignore it...
1431 ml_printf("Received duplicate connection request. %d\n",i);
1432 //reliable_sockets[i].last_packet_received = timer_GetTime();
1433 psnet_rel_send_ack(&Reliable_sockets[i].addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1434 //We will change this as a hack to prevent later code from hooking us up
1435 rcv_buff.type = 0xff;
1440 for(i=1; i<MAXRELIABLESOCKETS; i++){
1441 if(Reliable_sockets[i].status == RNF_UNUSED){
1442 //Add the new connection here.
1443 Reliable_sockets[i].connection_type=link_type;
1444 memcpy(&Reliable_sockets[i].net_addr, &d3_rcv_addr, sizeof(net_addr));
1445 memcpy(&Reliable_sockets[i].addr ,&rcv_addr, sizeof(SOCKADDR));
1446 Reliable_sockets[i].ping_pos = 0;
1447 Reliable_sockets[i].num_ping_samples = 0;
1448 Reliable_sockets[i].status = RNF_LIMBO;
1449 Reliable_sockets[i].last_packet_received = psnet_get_time();
1450 rsocket = &Reliable_sockets[i];
1451 rcvaddr = (SOCKADDR_IN *)&rcv_addr;
1452 ml_printf("Connect from %s:%d\n", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port));
1456 if(i==MAXRELIABLESOCKETS){
1457 //No more connections!
1458 ml_printf("Out of incoming reliable connection sockets\n");
1459 //Int3();//See Kevin
1462 psnet_rel_send_ack(&rsocket->addr,rcv_buff.seq,link_type,rcv_buff.send_time);
1465 //Find out if this is a packet from someone we were expecting a packet.
1466 rcvaddr = (SOCKADDR_IN *)&rcv_addr;
1467 for(i=1; i<MAXRELIABLESOCKETS; i++){
1468 rsockaddr = (SOCKADDR_IN *)&Reliable_sockets[i].addr;
1469 if(memcmp(&d3_rcv_addr,&Reliable_sockets[i].net_addr,sizeof(net_addr)) == 0){
1470 rsocket=&Reliable_sockets[i];
1475 if(NULL == rsocket){
1476 ml_printf("Received reliable data from unconnected client.\n");
1477 ml_printf("Received from %s:%d\n",inet_ntoa(rcvaddr->sin_addr),rcvaddr->sin_port);
1480 rsocket->last_packet_received = psnet_get_time();
1482 if(rsocket->status != RNF_CONNECTED){
1484 if(rsocket->status == RNF_LIMBO){
1485 //this is our connection to the server
1486 if(Serverconn != 0xffffffff){
1487 if(rcv_buff.type == RNT_ACK){
1488 int *acknum = (int *)&rcv_buff.data;
1489 if(*acknum == (~CONNECTSEQ & 0xffff)){
1490 rsocket->status = RNF_CONNECTED;
1491 ml_printf("Got ACK for IAMHERE!\n");
1495 } else if(rcv_buff.type == RNT_I_AM_HERE){
1496 rsocket->status = RNF_CONNECTING;
1497 psnet_rel_send_ack(&rsocket->addr,rcv_buff.seq,link_type,rcv_buff.send_time);
1498 ml_printf("Got IAMHERE!\n");
1502 if((rcv_buff.type == RNT_DATA) && (Serverconn != 0xffffffff)){
1503 rsocket->status = RNF_CONNECTED;
1505 rsocket->last_packet_received = psnet_get_time();
1509 //Update the last recv variable so we don't need a heartbeat
1510 rsocket->last_packet_received = psnet_get_time();
1512 if(rcv_buff.type == RNT_HEARTBEAT){
1515 if(rcv_buff.type == RNT_ACK){
1517 rsocket->num_ping_samples++;
1519 rsocket->pings[rsocket->ping_pos] = rsocket->last_packet_received - rcv_buff.send_time;
1520 if(rsocket->num_ping_samples >= MAX_PING_HISTORY){
1521 float sort_ping[MAX_PING_HISTORY];
1522 for(int a=0;a<MAX_PING_HISTORY;a++){
1523 sort_ping[a] = rsocket->pings[a];
1526 qsort(sort_ping ,MAX_PING_HISTORY, sizeof(float), psnet_rel_ping_compare);
1527 rsocket->mean_ping = ((sort_ping[MAX_PING_HISTORY/2]+sort_ping[(MAX_PING_HISTORY/2)+1]))/2;
1529 rsocket->ping_pos++;
1530 if(rsocket->ping_pos >= MAX_PING_HISTORY){
1531 rsocket->ping_pos=0;
1534 // if this is an ack for a send buffer on the socket, kill the send buffer. its done
1535 for(i=0; i<MAXNETBUFFERS; i++){
1536 unsigned int *acksig = (unsigned int *)&rcv_buff.data;
1538 if(rsocket->sbuffers[i]){
1539 if(rsocket->ssequence[i] == *acksig){
1540 Assert(rsocket->sbuffers[i] != NULL);
1541 free(rsocket->sbuffers[i]);
1542 rsocket->sbuffers[i] = NULL;
1543 rsocket->ssequence[i] = 0;
1548 //remove that packet from the send buffer
1549 rsocket->last_packet_received = psnet_get_time();
1553 if(rcv_buff.type == RNT_DATA_COMP){
1555 //Decompress it. Put it back in the buffer. Process it as RNT_DATA
1556 rcv_buff.type = RNT_DATA;
1558 if(rcv_buff.type == RNT_DATA){
1559 //If the data is out of order by >= MAXNETBUFFERS-1 ignore that packet for now
1561 seqdelta = rcv_buff.seq - rsocket->oursequence;
1562 if(seqdelta<0) seqdelta = seqdelta*-1;
1563 if(seqdelta>=MAXNETBUFFERS - 1){
1564 ml_printf("Received reliable packet out of order!\n");
1565 //It's out of order, so we won't ack it, which will mean we will get it again soon.
1568 //else move data into the proper buffer position
1571 if(rsocket->oursequence < (0xffff - (MAXNETBUFFERS-1))){
1572 if (rsocket->oursequence > rcv_buff.seq){
1576 //Sequence is high, so prepare for wrap around
1577 if( ((unsigned short)(rcv_buff.seq + rsocket->oursequence)) > (MAXNETBUFFERS-1)){
1582 for(i=0; i<MAXNETBUFFERS; i++){
1583 if( (NULL != rsocket->rbuffers[i]) && (rsocket->rsequence[i] == rcv_buff.seq)){
1584 //Received duplicate packet!
1589 for(i=0; i<MAXNETBUFFERS; i++){
1590 if(NULL == rsocket->rbuffers[i]){
1591 if(rcv_buff.data_len>max_len){
1592 rsocket->recv_len[i] = rcv_buff.data_len;
1594 rsocket->recv_len[i] = rcv_buff.data_len;
1596 rsocket->rbuffers[i] = (reliable_net_rcvbuffer *)malloc(sizeof(reliable_net_rcvbuffer));
1597 memcpy(rsocket->rbuffers[i]->buffer,rcv_buff.data,rsocket->recv_len[i]);
1598 rsocket->rsequence[i] = rcv_buff.seq;
1603 psnet_rel_send_ack(&rsocket->addr,rcv_buff.seq,link_type,rcv_buff.send_time);
1607 } while((ipx_has_data>0) || (udp_has_data>0));
1609 // Go through each reliable socket that is connected and do any needed work.
1610 for(j=0; j<MAXRELIABLESOCKETS; j++){
1611 rsocket=&Reliable_sockets[j];
1613 if(Serverconn == 0xffffffff){
1614 if(rsocket->status==RNF_LIMBO){
1615 if(fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout){
1616 ml_printf("Reliable (but in limbo) socket (%d) timed out in nw_WorkReliable().\n",j);
1617 memset(rsocket,0,sizeof(reliable_socket));
1618 rsocket->status = RNF_UNUSED;//Won't work if this is an outgoing connection.
1622 if((rsocket->status == RNF_LIMBO) && (fl_abs((psnet_get_time() - First_sent_iamhere)) > Nettimeout)){
1623 rsocket->status = RNF_BROKEN;
1624 ml_printf("Reliable socket (%d) timed out in nw_WorkReliable().\n",j);
1628 if(rsocket->status == RNF_CONNECTED){
1629 float retry_packet_time;
1630 if((rsocket->mean_ping==0) || (rsocket->mean_ping > (NETRETRYTIME*4))){
1631 retry_packet_time = NETRETRYTIME;
1633 if(rsocket->mean_ping<MIN_NET_RETRYTIME) {
1634 retry_packet_time = (float)MIN_NET_RETRYTIME;
1636 retry_packet_time = ((float)(float)rsocket->mean_ping * (float)1.25);
1639 //Iterate through send buffers.
1640 for(i=0;i<MAXNETBUFFERS;i++){
1642 if((rsocket->sbuffers[i]) && (fl_abs((psnet_get_time() - rsocket->timesent[i])) >= retry_packet_time)) {
1643 reliable_header send_header;
1644 send_header.send_time = psnet_get_time();
1645 send_header.seq = rsocket->ssequence[i];
1646 memcpy(send_header.data,rsocket->sbuffers[i]->buffer,rsocket->send_len[i]);
1647 send_header.data_len = (ushort)rsocket->send_len[i];
1648 send_header.type = RNT_DATA;
1649 if(rsocket->connection_type == NET_TCP){
1650 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1651 } else if(rsocket->connection_type == NET_IPX){
1652 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1654 if((rcode == SOCKET_ERROR) && (WSAEWOULDBLOCK == WSAGetLastError())){
1655 //The packet didn't get sent, flag it to try again next frame
1656 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1658 rsocket->last_packet_sent = psnet_get_time();
1659 rsocket->timesent[i] = psnet_get_time();
1665 if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_sent)) > NETHEARTBEATTIME)) {
1666 reliable_header send_header;
1667 send_header.send_time = psnet_get_time();
1668 send_header.seq = 0;
1669 send_header.data_len = 0;
1670 send_header.type = RNT_HEARTBEAT;
1673 if(rsocket->connection_type == NET_TCP){
1674 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1675 } else if(rsocket->connection_type == NET_IPX){
1676 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1678 if((rcode != SOCKET_ERROR) && (WSAEWOULDBLOCK != WSAGetLastError())){
1679 //It must have been sent
1680 rsocket->last_packet_sent = psnet_get_time();
1684 if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout)){
1685 //This socket is hosed.....inform someone?
1686 ml_printf("Reliable Socket (%d) timed out in nw_WorkReliable().\n",j);
1687 rsocket->status = RNF_BROKEN;
1693 // get the status of a reliable socket, see RNF_* defines above
1694 int psnet_rel_get_status(PSNET_SOCKET_RELIABLE socketid)
1696 if(socketid >= MAXRELIABLESOCKETS){
1700 return Reliable_sockets[socketid].status;
1703 // function which checks the Listen_socket for possibly incoming requests to be connected.
1704 // returns 0 on error or nothing waiting. 1 if we should try to accept
1705 int psnet_rel_check_for_listen(net_addr *from_addr)
1707 SOCKADDR_IN *ip_addr; // UDP/TCP socket structure
1708 SOCKADDR_IPX *ipx_addr; // IPX socket structure
1712 for(i=1; i<MAXRELIABLESOCKETS; i++){
1713 if(Reliable_sockets[i].status == RNF_CONNECTING){
1714 Reliable_sockets[i].status = RNF_CONNECTED;
1715 //memcpy(from_addr,&reliable_sockets[i].addr,sizeof(SOCKADDR));
1716 ml_printf("New reliable connection in nw_CheckListenSocket().\n");
1718 switch ( Reliable_sockets[i].connection_type ){
1720 ipx_addr = (SOCKADDR_IPX *)&Reliable_sockets[i].addr;
1721 memset(from_addr, 0x00, sizeof(net_addr));
1722 from_addr->port = ntohs( ipx_addr->sa_socket );
1723 from_addr->type = NET_IPX;
1724 memcpy(from_addr->addr, ipx_addr->sa_nodenum, 6 );
1725 memcpy(from_addr->net_id, ipx_addr->sa_netnum, 4 );
1729 ip_addr = (SOCKADDR_IN *)&Reliable_sockets[i].addr;
1730 memset(from_addr, 0x00, sizeof(net_addr));
1731 from_addr->port = ntohs( ip_addr->sin_port );
1732 from_addr->type = NET_TCP;
1733 memcpy(from_addr->addr, &ip_addr->sin_addr.S_un.S_addr, 4);
1741 char dbg_output[50];
1742 nw_GetNumbersFromHostAddress(from_addr,dbg_output);
1743 mprintf((0,"Got address from: %s\n",dbg_output));
1748 return INVALID_SOCKET;
1751 // attacmpt to connect() to the server's tcp socket. socket parameter is simply assigned to the
1752 // Reliable_socket socket created in psnet_init
1753 void psnet_rel_connect_to_server(PSNET_SOCKET *socket, net_addr *server_addr)
1755 //Send out a RNT_REQ_CONN packet, and wait for it to be acked.
1756 SOCKADDR_IN sockaddr; // UDP/TCP socket structure
1757 SOCKADDR_IPX ipx_addr; // IPX socket structure
1758 SOCKADDR *addr; // pointer to SOCKADDR to make coding easier
1764 float time_sent_req = 0;
1765 float first_sent_req = 0;
1766 static reliable_header conn_header;
1767 static reliable_header ack_header;
1769 struct timeval timeout;
1772 *socket = INVALID_SOCKET;
1774 memset(iaddr, 0x00, 6);
1775 memcpy(iaddr, &server_addr->addr, 6);
1776 port = (ushort)(server_addr->port); // Talk to the server listen port
1778 conn_header.type = RNT_REQ_CONN;
1779 conn_header.seq = CONNECTSEQ;
1780 conn_header.data_len = 0;
1785 if((server_addr->type == NET_IPX) && (!Ipx_active)){
1788 if((server_addr->type == NET_TCP) && (!Tcp_active)){
1791 //Flush out any left overs
1792 if(Tcp_active && (Socket_type == NET_TCP)){
1794 FD_SET(Unreliable_socket, &read_fds);
1795 while(SELECT(0, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE)){
1796 addrlen = sizeof(SOCKADDR);
1797 bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1799 //Int3();//See Kevin
1800 ml_printf("UDP recvfrom returned an error! -- %d\n",WSAGetLastError());
1805 FD_SET(Unreliable_socket, &read_fds);
1808 if(Ipx_active && (Socket_type == NET_IPX)){
1810 FD_SET(Unreliable_socket, &read_fds);
1811 while(SELECT(0, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE))
1813 addrlen = sizeof(SOCKADDR);
1814 bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1817 //Int3();//See Kevin
1818 ml_printf("IPX recvfrom returned an error! -- %d\n",WSAGetLastError());
1822 FD_SET(Unreliable_socket, &read_fds);
1825 memset(&ack_header,0,sizeof(reliable_header));
1827 SOCKET typeless_sock;
1828 net_addr d3_rcv_addr;
1829 memset(&d3_rcv_addr,0,sizeof(net_addr));
1831 switch ( server_addr->type ){
1833 ipx_addr.sa_family = AF_IPX;
1834 memcpy(ipx_addr.sa_nodenum, iaddr, 6);
1835 memcpy(ipx_addr.sa_netnum, server_addr->net_id, 4);
1836 ipx_addr.sa_socket = htons(port);
1837 addr = (SOCKADDR *)&ipx_addr;
1838 name_length = sizeof(ipx_addr);
1839 if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE) ){
1840 ml_printf("Unable to send IPX packet in nw_ConnectToServer()! -- %d\n",WSAGetLastError());
1843 typeless_sock = Unreliable_socket;
1844 memcpy(d3_rcv_addr.addr,ipx_addr.sa_nodenum, 6);
1845 memcpy(d3_rcv_addr.net_id,ipx_addr.sa_netnum, 4);
1846 d3_rcv_addr.type = NET_IPX;
1849 sockaddr.sin_family = AF_INET;
1850 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1851 sockaddr.sin_port = htons(port);
1852 addr = (SOCKADDR *)&sockaddr;
1853 name_length = sizeof(sockaddr);
1854 if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE) ){
1855 ml_printf("Unable to send UDP packet in nw_ConnectToServer()! -- %d\n",WSAGetLastError());
1858 memcpy(d3_rcv_addr.addr, &sockaddr.sin_addr.s_addr, 4);
1859 d3_rcv_addr.port = sockaddr.sin_port;
1860 d3_rcv_addr.type = NET_TCP;
1861 typeless_sock = Unreliable_socket;
1865 ml_printf("Network","Unknown protocol type in nw_ConnectToServer()!\n");
1871 first_sent_req = psnet_get_time();
1872 time_sent_req = psnet_get_time();
1874 //Wait until we get a response from the server or we timeout
1877 PSNET_TOP_LAYER_PROCESS();
1880 FD_SET(typeless_sock, &read_fds);
1881 if(SELECT(0, &read_fds, NULL,NULL,&timeout, PSNET_TYPE_RELIABLE)){
1882 ml_string("selected() in psnet_rel_connect_to_server()");
1884 addrlen = sizeof(SOCKADDR);
1885 bytesin = RECVFROM(typeless_sock,(char *)&ack_header,sizeof(reliable_header),0,(SOCKADDR *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1887 ml_printf("recvfrom returned an error! -- %d\n",WSAGetLastError());
1892 ml_string("received data after select in psnet_rel_connect_to_server()");
1894 ml_string("about to check ack_header.type");
1895 if(ack_header.type == RNT_ACK){
1896 int *acknum = (int *)&ack_header.data;
1897 if(*acknum == CONNECTSEQ){
1898 for(i=1; i<MAXRELIABLESOCKETS; i++){
1899 if(Reliable_sockets[i].status==RNF_UNUSED){
1900 //Add the new connection here.
1901 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
1902 Reliable_sockets[i].connection_type = (ubyte)server_addr->type;
1903 memcpy(&Reliable_sockets[i].net_addr,&d3_rcv_addr,sizeof(net_addr));
1904 Reliable_sockets[i].last_packet_received = psnet_get_time();
1905 memcpy(&Reliable_sockets[i].addr,&rcv_addr,sizeof(SOCKADDR));
1906 Reliable_sockets[i].status = RNF_LIMBO;
1908 ml_printf("Succesfully connected to server in nw_ConnectToServer().\n");
1909 //Now send I_AM_HERE packet
1910 conn_header.type = RNT_I_AM_HERE;
1911 conn_header.seq = (ushort)(~CONNECTSEQ);
1912 conn_header.data_len = 0;
1914 First_sent_iamhere = psnet_get_time();
1915 Last_sent_iamhere = psnet_get_time();
1916 int rcode = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1917 if(rcode == SOCKET_ERROR){
1918 *socket = INVALID_SOCKET;
1919 Reliable_sockets[i].status = RNF_UNUSED;
1920 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
1921 ml_printf("Unable to send packet in nw_ConnectToServer()\n");
1924 Reliable_sockets[i].last_packet_sent = psnet_get_time();
1926 f = psnet_get_time();
1927 while((fl_abs((psnet_get_time() - f))<2) && (Reliable_sockets[i].status != RNF_CONNECTING)){
1934 ml_printf("Out of reliable socket space in nw_ConnectToServer().\n");
1936 } else ml_printf("Received out of sequence ACK in nw_ConnectToServer().\n");
1937 } else ml_printf("Received something that isn't an ACK in nw_ConnectToServer().\n");
1938 } else ml_printf("Received 0 bytes from recvfrom() in nw_ConnectToServer().\n");
1941 if((psnet_get_time()-time_sent_req)>2)
1943 ml_printf("Resending connect request.\n");
1944 int ret = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(SOCKADDR), PSNET_TYPE_RELIABLE);
1945 if(ret != SOCKET_ERROR){
1946 time_sent_req = psnet_get_time();
1948 ml_printf("Error sending connection request! -- %d\n",WSAGetLastError() );
1953 } while(fl_abs((psnet_get_time() - first_sent_req)) < RELIABLE_CONNECT_TIME);
1956 // returns the ip address of this computer
1958 int psnet_rel_get_ip()
1962 SOCKADDR_IN local_address;
1965 // Get the local host name
1966 memset(&local_address, 0, sizeof(local_address));
1967 ret = gethostname(local, 255 );
1968 if (ret != SOCKET_ERROR ){
1969 // Resolve host name for local address
1970 hostent = gethostbyname((LPSTR)local);
1972 local_address.sin_addr.s_addr = *((u_long FAR *)(hostent->h_addr));
1975 ml_string("SOCKET_ERROR in psnet_rel_get_ip()!");
1977 ml_printf(%s:%d\n", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port)
1978 return local_address.sin_addr.s_addr;
1982 // returns the ip address of this computer
1985 SOCKADDR_IN local_address;
1987 if(Psnet_connection == NETWORK_CONNECTION_DIALUP){
1988 local_address.sin_addr.s_addr = psnet_ras_status();
1989 if(local_address.sin_addr.s_addr == INADDR_NONE){
1990 local_address.sin_addr.s_addr = INADDR_ANY;
1993 // Init local address to zero
1994 local_address.sin_addr.s_addr = INADDR_ANY;
1997 ml_printf("psnet_get_ip() reports IP : %s\n", inet_ntoa(local_address.sin_addr));
1999 return local_address.sin_addr.s_addr;
2002 // initialize reliable sockets
2003 int psnet_init_rel_tcp(int port, int should_listen)
2006 SOCKADDR_IN sockaddr;
2008 sockaddr.sin_port = htons((ushort)port);
2009 sockaddr.sin_family = AF_INET;
2011 ml_printf("Setting up reliable sockets.\n");
2013 my_ip = psnet_get_ip();
2015 memcpy(&sockaddr.sin_addr.s_addr, &my_ip, sizeof(uint));
2017 Reliable_UDP_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP );
2018 if(INVALID_SOCKET == Reliable_UDP_socket){
2019 ml_printf("Unable to create reliable UDP socket -- %d\n", WSAGetLastError() );
2022 } else if(bind(Reliable_UDP_socket,(SOCKADDR *)&sockaddr,sizeof(SOCKADDR))!=0){
2023 ml_printf("Unable to bind reliable socket -- %d\n", WSAGetLastError() );
2028 // make any reliable sockets which we create that aren't listening non-blocking sockets
2033 error = ioctlsocket( Reliable_UDP_socket, FIONBIO, &arg );
2034 if ( error == SOCKET_ERROR ) {
2035 ml_printf("Unable to make reliable UDP socket non-blocking -- %d\n", WSAGetLastError() );
2045 // initialize reliable sockets
2046 int psnet_init_rel_ipx(int port, int should_listen)
2049 SOCKADDR_IPX ipx_addr;
2051 memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
2052 ipx_addr.sa_family = AF_IPX;
2053 ipx_addr.sa_socket = htons((ushort)port);
2055 Reliable_IPX_socket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
2056 if(INVALID_SOCKET == Reliable_IPX_socket){
2057 ml_printf("Unable to create reliable IPX socket -- %d\n", WSAGetLastError() );
2060 } else if(bind(Reliable_IPX_socket,(SOCKADDR *)&ipx_addr,sizeof(SOCKADDR))!=0){
2061 ml_printf("Unable to bind reliable IPX socket -- %d\n", WSAGetLastError() );
2066 // make any reliable sockets which we create that aren't listening non-blocking sockets
2071 error = ioctlsocket( Reliable_IPX_socket, FIONBIO, &arg );
2072 if ( error == SOCKET_ERROR ) {
2073 ml_printf("Unable to make reliable IPX socket non-blocking -- %d\n", WSAGetLastError() );
2083 void psnet_rel_close()
2086 PSNET_SOCKET_RELIABLE sock;
2089 for(idx=0; idx<MAXRELIABLESOCKETS; idx++){
2090 if(Reliable_sockets[idx].status != RNF_UNUSED){
2092 psnet_rel_close_socket(&sock);
2097 // ------------------------------------------------------------------------------------------------------
2098 // PACKET BUFFERING FUNCTIONS
2101 // initialize the buffering system
2102 void psnet_buffer_init(network_packet_buffer_list *l)
2106 // blast the buffer clean
2107 memset(l->psnet_buffers, 0, sizeof(network_packet_buffer) * MAX_PACKET_BUFFERS);
2109 // set all buffer sequence #'s to -1
2110 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2111 l->psnet_buffers[idx].sequence_number = -1;
2114 // initialize the sequence #
2115 l->psnet_seq_number = 0;
2116 l->psnet_lowest_id = -1;
2117 l->psnet_highest_id = -1;
2120 // buffer a packet (maintain order!)
2121 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr *from)
2126 // find the first empty packet
2127 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2128 if(l->psnet_buffers[idx].sequence_number == -1){
2134 // if we didn't find the buffer, report an overrun
2136 ml_printf("WARNING - Buffer overrun in psnet\n");
2139 memcpy(l->psnet_buffers[idx].data, data, length);
2140 l->psnet_buffers[idx].len = length;
2141 memcpy(&l->psnet_buffers[idx].from_addr, from, sizeof(net_addr));
2142 l->psnet_buffers[idx].sequence_number = l->psnet_seq_number;
2144 // keep track of the highest id#
2145 l->psnet_highest_id = l->psnet_seq_number++;
2147 // set the lowest id# for the first time
2148 if(l->psnet_lowest_id == -1){
2149 l->psnet_lowest_id = l->psnet_highest_id;
2154 // get the index of the next packet in order!
2155 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr *from)
2160 // if there are no buffers, do nothing
2161 if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
2165 // search until we find the lowest packet index id#
2166 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2167 // if we found the buffer
2168 if(l->psnet_buffers[idx].sequence_number == l->psnet_lowest_id){
2174 // at this point, we should _always_ have found the buffer
2177 // copy out the buffer data
2178 memcpy(data, l->psnet_buffers[idx].data, l->psnet_buffers[idx].len);
2179 *length = l->psnet_buffers[idx].len;
2180 memcpy(from, &l->psnet_buffers[idx].from_addr, sizeof(net_addr));
2182 // now we need to cleanup the packet list
2184 // mark the buffer as free
2185 l->psnet_buffers[idx].sequence_number = -1;
2186 l->psnet_lowest_id++;
2191 // -------------------------------------------------------------------------------------------------------
2192 // PSNET 2 FORWARD DEFINITIONS
2195 // if the string is a legally formatted ip string
2196 int psnet_is_valid_numeric_ip(char *ip)
2200 int val1,val2,val3,val4;
2202 // get the first ip value
2204 token = strtok(copy,".");
2208 // get the value of the token
2210 if((val1 < 0) || (val1 > 255)){
2216 token = strtok(NULL,".");
2220 // get the value of the token
2222 if((val2 < 0) || (val2 > 255)){
2228 token = strtok(NULL,".");
2232 // get the value of the token
2234 if((val3 < 0) || (val3 > 255)){
2240 token = strtok(NULL,"");
2244 // get the value of the token
2246 if((val4 < 0) || (val4 > 255)){
2251 // make sure he hasn't entered all 0's
2252 if((val1 == 0) && (val2 == 0) && (val3 == 0) && (val4 == 0)){
2260 // function called from high level FreeSpace code to determine the status of the networking
2261 // code returns one of a handful of macros
2263 DWORD (__stdcall *pRasEnumConnections)(LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections) = NULL;
2264 DWORD (__stdcall *pRasGetConnectStatus)(HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) = NULL;
2265 DWORD (__stdcall *pRasGetProjectionInfo)(HRASCONN hrasconn, RASPROJECTION rasprojection, LPVOID lpprojection, LPDWORD lpcb ) = NULL;
2267 // functions to get the status of a RAS connection
2268 unsigned int psnet_ras_status()
2271 unsigned long size, num_connections, i;
2272 RASCONN rasbuffer[25];
2273 HINSTANCE ras_handle;
2274 unsigned long rasip=0;
2275 RASPPPIP projection;
2276 // int Ras_connected;
2280 // first, call a LoadLibrary to load the RAS api
2281 ras_handle = LoadLibrary( "rasapi32.dll" );
2282 if ( ras_handle == NULL ) {
2286 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, "RasEnumConnectionsA");
2287 if (!pRasEnumConnections) {
2288 FreeLibrary( ras_handle );
2291 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, "RasGetConnectStatusA");
2292 if (!pRasGetConnectStatus) {
2293 FreeLibrary( ras_handle );
2296 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, "RasGetProjectionInfoA");
2297 if (!pRasGetProjectionInfo) {
2298 FreeLibrary( ras_handle );
2302 size = sizeof(rasbuffer);
2303 rasbuffer[0].dwSize = sizeof(RASCONN);
2305 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2307 FreeLibrary( ras_handle );
2311 // JAS: My computer gets to this point, but I have no RAS connections,
2313 if ( num_connections < 1 ) {
2314 ml_string("Found no RAS connections");
2315 FreeLibrary( ras_handle );
2319 ml_printf("Found %d connections", num_connections);
2321 for (i = 0; i < num_connections; i++ ) {
2322 RASCONNSTATUS status;
2325 ml_printf("Connection %d:", i);
2326 ml_printf("Entry Name: %s", rasbuffer[i].szEntryName);
2327 ml_printf("Device Type: %s", rasbuffer[i].szDeviceType);
2328 ml_printf("Device Name: %s", rasbuffer[i].szDeviceName);
2330 // get the connection status
2331 status.dwSize = sizeof(RASCONNSTATUS);
2332 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2334 FreeLibrary( ras_handle );
2338 // get the projection informatiom
2339 size = sizeof(projection);
2340 projection.dwSize = size;
2341 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2343 FreeLibrary( ras_handle );
2347 ml_printf("IP Address: %s", projection.szIpAddress);
2352 FreeLibrary( ras_handle );
2353 rasip = inet_addr(projection.szIpAddress);
2354 if(rasip==INADDR_NONE){
2358 //The ip of the RAS connection
2362 // functions to get the status of a RAS connection
2364 void psnet_ras_status()
2367 unsigned long size, num_connections, i;
2368 RASCONN rasbuffer[25];
2369 HINSTANCE ras_handle;
2373 // first, call a LoadLibrary to load the RAS api
2374 ras_handle = LoadLibrary( NOX("rasapi32.dll") );
2375 if ( ras_handle == NULL ) {
2379 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, NOX("RasEnumConnectionsA"));
2380 if (!pRasEnumConnections) {
2381 FreeLibrary( ras_handle );
2384 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, NOX("RasGetConnectStatusA"));
2385 if (!pRasGetConnectStatus) {
2386 FreeLibrary( ras_handle );
2389 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, NOX("RasGetProjectionInfoA"));
2390 if (!pRasGetProjectionInfo) {
2391 FreeLibrary( ras_handle );
2395 size = sizeof(rasbuffer);
2396 rasbuffer[0].dwSize = sizeof(RASCONN);
2398 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2400 FreeLibrary( ras_handle );
2404 // JAS: My computer gets to this point, but I have no RAS connections,
2406 if ( num_connections < 1 ) {
2407 ml_printf("Found no connections\n" );
2408 FreeLibrary( ras_handle );
2412 ml_printf("Found %d connections\n", num_connections);
2414 for (i = 0; i < num_connections; i++ ) {
2415 RASCONNSTATUS status;
2416 RASPPPIP projection;
2419 ml_printf("Connection %d:\n", i);
2420 ml_printf("Entry Name: %s\n", rasbuffer[i].szEntryName);
2421 ml_printf("Device Type: %s\n", rasbuffer[i].szDeviceType);
2422 ml_printf("Device Name: %s\n", rasbuffer[i].szDeviceName);
2424 // get the connection status
2425 status.dwSize = sizeof(RASCONNSTATUS);
2426 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2428 FreeLibrary( ras_handle );
2432 ml_printf("\tStatus: %s\n", (status.rasconnstate==RASCS_Connected)?"Connected":"Not Connected");
2434 // get the projection informatiom
2435 size = sizeof(projection);
2436 projection.dwSize = size;
2437 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2439 FreeLibrary( ras_handle );
2443 ml_printf("IP Address: %s", projection.szIpAddress));
2448 FreeLibrary( ras_handle );
2452 // set some options on a socket
2453 void psnet_socket_options( SOCKET sock )
2456 int ret, cursize, cursizesize, bufsize;
2458 // Set the mode of the socket to allow broadcasting. We need to be able to broadcast
2459 // when a game is searched for in IPX mode.
2461 if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (LPSTR)&broadcast, sizeof(broadcast) )){
2468 // setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (LPSTR)&broadcast, sizeof(broadcast) );
2470 // try and increase the size of my receive buffer
2471 bufsize = MAX_RECEIVE_BUFSIZE;
2473 // set the current size of the receive buffer
2474 cursizesize = sizeof(int);
2475 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&cursize, &cursizesize);
2476 // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2477 ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&bufsize, sizeof(bufsize));
2478 if ( ret == SOCKET_ERROR ) {
2481 wserr = WSAGetLastError();
2482 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
2486 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (LPSTR)&cursize, &cursizesize);
2487 ml_printf("Receive buffer set to %d\n", cursize);
2489 // set the current size of the send buffer
2490 cursizesize = sizeof(int);
2491 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&cursize, &cursizesize);
2492 // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2493 ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&bufsize, sizeof(bufsize));
2494 if ( ret == SOCKET_ERROR ) {
2497 wserr = WSAGetLastError();
2498 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) ){
2502 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (LPSTR)&cursize, &cursizesize);
2503 ml_printf("Send buffer set to %d\n", cursize);
2506 // initialize ipx socket
2507 int psnet_init_ipx()
2509 SOCKADDR_IPX sockaddr;
2511 IPX_socket = INVALID_SOCKET;
2513 IPX_socket = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );
2514 if ( IPX_socket == INVALID_SOCKET ) {
2515 Ipx_failure_code = WSAGetLastError();
2516 ml_printf("Error on IPX startup %d\n", Ipx_failure_code);
2521 memset(&sockaddr,0,sizeof(SOCKADDR_IPX));
2522 sockaddr.sa_family = AF_IPX;
2523 sockaddr.sa_socket = htons( Psnet_default_port );
2524 if ( bind(IPX_socket, (SOCKADDR*)&sockaddr, sizeof (SOCKADDR_IPX)) == SOCKET_ERROR) {
2525 Ipx_failure_code = WSAGetLastError();
2526 ml_printf("Couldn't bind IPX socket (%d)! Invalidating IPX\n", Ipx_failure_code );
2530 // set socket options
2531 psnet_socket_options( IPX_socket );
2532 Ipx_can_broadcast = Can_broadcast;
2538 // initialize tcp socket
2539 int psnet_init_tcp()
2541 SOCKADDR_IN sockaddr;
2543 TCP_socket = INVALID_SOCKET;
2545 TCP_socket = socket( AF_INET, SOCK_DGRAM, 0 );
2546 if ( TCP_socket == INVALID_SOCKET ) {
2547 Tcp_failure_code = WSAGetLastError();
2548 ml_printf("Error on TCP startup %d\n", Tcp_failure_code);
2553 memset(&sockaddr,0,sizeof(SOCKADDR_IN));
2554 sockaddr.sin_family = AF_INET;
2555 sockaddr.sin_addr.s_addr = psnet_get_ip();
2556 sockaddr.sin_port = htons( Psnet_default_port );
2557 if ( bind(TCP_socket, (SOCKADDR*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
2558 Tcp_failure_code = WSAGetLastError();
2559 ml_printf("Couldn't bind TCP socket (%d)! Invalidating TCP\n", Tcp_failure_code );
2563 // set socket options
2564 psnet_socket_options( TCP_socket );
2565 Tcp_can_broadcast = Can_broadcast;
2571 // get time in seconds
2572 float psnet_get_time()
2574 return (float)timer_get_milliseconds() / 1000.0f;
2577 // mark a socket as having received data
2578 void psnet_mark_received(PSNET_SOCKET_RELIABLE socket)
2581 if((socket == 0xffffffff) || (socket >= MAXRELIABLESOCKETS)){
2586 Reliable_sockets[socket].last_packet_received = psnet_get_time();
2589 #endif // #ifdef PSNET2