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.14 2005/10/02 09:30:10 taylor
19 * sync up rest of big-endian network changes. it should at least be as good as what's in FS2_Open now, only better :)
21 * Revision 1.13 2005/10/01 22:01:28 taylor
22 * some cleanup of earlier big-endian changes
24 * Revision 1.12 2004/07/04 11:39:06 taylor
25 * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
27 * Revision 1.11 2004/06/11 01:52:15 tigital
28 * byte-swapping changes for bigendian systems
30 * Revision 1.10 2003/08/03 16:10:30 taylor
31 * cleanup; compile warning fixes
33 * Revision 1.9 2002/07/27 19:52:54 relnev
34 * add missing structure packing
36 * Revision 1.8 2002/06/09 04:41:24 relnev
37 * added copyright header
39 * Revision 1.7 2002/06/02 05:31:17 relnev
42 * Revision 1.6 2002/06/02 02:29:39 relnev
45 * Revision 1.5 2002/05/27 04:04:43 relnev
46 * 155 undefined references left
48 * Revision 1.4 2002/05/26 21:27:53 theoddone33
49 * More progress (I hate psnet2)
51 * Revision 1.3 2002/05/26 20:49:54 theoddone33
54 * Revision 1.2 2002/05/07 03:16:48 theoddone33
55 * The Great Newline Fix
57 * Revision 1.1.1.1 2002/05/03 03:28:10 root
61 * 25 9/14/99 2:21p Dave
62 * Fixed observer mode joining and ingame stuff.
64 * 24 9/10/99 9:44p Dave
65 * Bumped version # up. Make server reliable connects not have such a huge
68 * 23 9/07/99 4:01p Dave
69 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
70 * does everything properly (setting up address when binding). Remove
71 * black rectangle background from UI_INPUTBOX.
73 * 22 8/26/99 8:51p Dave
74 * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
76 * 21 8/16/99 4:06p Dave
77 * Big honking checkin.
79 * 20 7/26/99 5:50p Dave
80 * Revised ingame join. Better? We'll see....
82 * 19 7/20/99 1:49p Dave
83 * Peter Drake build. Fixed some release build warnings.
85 * 18 7/15/99 9:20a Andsager
86 * FS2_DEMO initial checkin
88 * 17 7/03/99 4:08p Dave
89 * Fixed wss_slots size issues. Fixed potentially nasty bug in low level
92 * 16 6/25/99 5:02p Jasenw
93 * Removed old debug code.
95 * 15 6/07/99 9:51p Dave
96 * Consolidated all multiplayer ports into one.
98 * 14 4/30/99 12:18p Dave
99 * Several minor bug fixes.
101 * 13 4/27/99 5:55p Dave
102 * Fixed Ras_connected bug with VSDK code.
104 * 12 4/27/99 2:59p Dave
105 * Potential fix for reliable socket connection problem.
107 * 11 4/23/99 11:07a Dave
108 * Added lots of debug multi.log output to psnet2
110 * 10 4/12/99 10:07p Dave
111 * Made network startup more forgiving. Added checkmarks to dogfight
112 * screen for players who hit commit.
114 * 9 3/10/99 6:50p Dave
115 * Changed the way we buffer packets for all clients. Optimized turret
116 * fired packets. Did some weapon firing optimizations.
118 * 8 3/09/99 6:24p Dave
119 * More work on object update revamping. Identified several sources of
120 * unnecessary bandwidth.
122 * 7 3/08/99 7:03p Dave
123 * First run of new object update system. Looks very promising.
125 * 6 1/24/99 11:37p Dave
126 * First full rev of beam weapons. Very customizable. Removed some bogus
127 * Int3()'s in low level net code.
129 * 5 1/06/99 2:24p Dave
130 * Stubs and release build fixes.
132 * 4 11/20/98 11:16a Dave
133 * Fixed up IPX support a bit. Making sure that switching modes and
134 * loading/saving pilot files maintains proper state.
136 * 3 11/19/98 4:19p Dave
137 * Put IPX sockets back in psnet. Consolidated all multiplayer config
140 * 2 11/19/98 8:04a Dave
141 * Full support for D3-style reliable sockets. Revamped packet lag/loss
142 * system, made it receiver side and at the lowest possible level.
148 #include <winsock2.h>
150 #include <raserror.h>
152 #include <sys/types.h>
153 #include <sys/socket.h>
154 #include <netinet/in.h>
155 #include <arpa/inet.h>
165 #include "multiutil.h"
166 #include "multilag.h"
167 #include "osregistry.h"
169 #include "multi_log.h"
170 #include "multi_rate.h"
175 // -------------------------------------------------------------------------------------------------------
176 // PSNET 2 DEFINES/VARS
179 int Psnet_my_addr_valid;
180 net_addr_t Psnet_my_addr;
182 const ubyte Null_address[4] = { 0x00, 0x00, 0x00, 0x00 };
185 int Can_broadcast; // can we do broadcasting on our socket?
186 int Tcp_can_broadcast = 0;
191 int Tcp_failure_code = 0;
193 int Psnet_connection;
195 ushort Psnet_default_port;
197 // specified their internet connnection type
198 #define NETWORK_CONNECTION_NONE 1
199 #define NETWORK_CONNECTION_DIALUP 2
200 #define NETWORK_CONNECTION_LAN 3
202 // defines and variables to indicate network connection status
203 #define NETWORK_STATUS_NOT_INITIALIZED 1
204 #define NETWORK_STATUS_NO_WINSOCK 2 // winsock failed to initialize
205 #define NETWORK_STATUS_NO_PROTOCOL 3 // TCP/IP doesn't appear to be loaded
206 #define NETWORK_STATUS_NO_RELIABLE 4
207 #define NETWORK_STATUS_RUNNING 5 // everything should be running
209 // defintion of structures that actually leave this machine. psnet_send give us only
210 // the data that we want to send. We will add a header onto this data (packet sequence
211 // number, possibly a checksum). We must include a 2 byte flags variable into both structure
212 // since the receiving end of this packet must know whether or not to checksum the packet.
214 #define MAX_TOP_LAYER_PACKET_SIZE 680
216 // use the pack pragma to pack these structures to 2 byte aligment. Really only needed for
218 #define MAX_PACKET_BUFFERS 75
221 #pragma pack(push, 2)
224 // definition for a non-checksum packet
225 typedef struct network_packet
229 ubyte data[MAX_TOP_LAYER_PACKET_SIZE];
230 } network_naked_packet;
232 // structure definition for our packet buffers
233 typedef struct network_packet_buffer
237 net_addr_t from_addr;
238 ubyte data[MAX_TOP_LAYER_PACKET_SIZE];
239 } network_packet_buffer;
241 // struct for a bunch of network packet buffers
242 typedef struct network_packet_buffer_list {
243 network_packet_buffer psnet_buffers[MAX_PACKET_BUFFERS];
244 int psnet_seq_number;
246 int psnet_highest_id;
247 } network_packet_buffer_list;
254 #define MAXHOSTNAME 128
256 #define MAX_RECEIVE_BUFSIZE 4096 // 32 K, eh?
257 #define MAX_SEND_RETRIES 20 // number of retries when sending would block
258 #define MAX_LINGER_TIME 0 // in seconds -- when lingering to close a socket
261 //*******************************
262 #define MAXNETBUFFERS 150 // Maximum network buffers (For between network and upper level functions, which is
263 // required in case of out of order packets
264 #define NETRETRYTIME 0.75f // Time after sending before we resend
265 #define MIN_NET_RETRYTIME 0.2f
266 #define NETTIMEOUT 30 // Time after receiving the last packet before we drop that user
267 #define NETHEARTBEATTIME 3 // How often to send a heartbeat
268 #define MAXRELIABLESOCKETS 40 // Max reliable sockets to open at once...
269 #define NETBUFFERSIZE 600 // Max size of a network packet
271 #define RELIABLE_CONNECT_TIME 7 // how long we'll wait for a response when doing a reliable connect
273 int Nettimeout = NETTIMEOUT;
275 // Reliable packet stuff
276 #define RNT_ACK 1 // ACK Packet
277 #define RNT_DATA 2 // Data Packet
278 #define RNT_DATA_COMP 3 // Compressed Data Packet
279 #define RNT_REQ_CONN 4 // Requesting a connection
280 #define RNT_DISCONNECT 5 // Disconnecting a connection
281 #define RNT_HEARTBEAT 6 // Heartbeat -- send every NETHEARTBEATTIME
282 #define RNT_I_AM_HERE 7
285 #pragma pack(push,r_udp)
289 #define PACKED __attribute__((packed))
293 ubyte type; // packet type
295 ushort seq; // sequence packet 0-65535 used for ACKing also
296 ushort data_len; // length of data
297 float send_time; // Time the packet was sent, if an ACK the time the packet being ACK'd was sent.
298 ubyte data[NETBUFFERSIZE]; // Packet data
299 } PACKED reliable_header;
301 #define RELIABLE_PACKET_HEADER_ONLY_SIZE (sizeof(reliable_header)-NETBUFFERSIZE)
302 #define MAX_PING_HISTORY 10
305 ubyte buffer[NETBUFFERSIZE];
307 } PACKED reliable_net_sendbuffer;
310 ubyte buffer[NETBUFFERSIZE];
311 } PACKED reliable_net_rcvbuffer;
314 reliable_net_sendbuffer *sbuffers[MAXNETBUFFERS]; // This is an array of pointers for quick sorting
315 unsigned short ssequence[MAXNETBUFFERS]; // This is the sequence number of the given packet
316 float timesent[MAXNETBUFFERS];
317 int send_len[MAXNETBUFFERS];
318 reliable_net_rcvbuffer *rbuffers[MAXNETBUFFERS];
319 int recv_len[MAXNETBUFFERS];
320 unsigned short rsequence[MAXNETBUFFERS]; // This is the sequence number of the given packet
321 float last_packet_received; // For a given connection, this is the last packet we received
322 float last_packet_sent;
323 struct sockaddr addr; // struct sockaddr of our peer
324 ushort status; // Status of this connection
325 unsigned short oursequence; // This is the next sequence number the application is expecting
326 unsigned short theirsequence; // This is the next sequence number the peer is expecting
327 net_addr_t net_addr; // A FS2 network address structure
328 ubyte connection_type; // IP, modem, etc.
329 float pings[MAX_PING_HISTORY];
331 unsigned int num_ping_samples;
335 reliable_socket Reliable_sockets[MAXRELIABLESOCKETS];
337 // socket TCP (unreliable)
340 // the sockets that the game will use when selecting network type
341 SOCKET Unreliable_socket = INVALID_SOCKET;
344 // SOCKET Reliable_UDP_socket = INVALID_SOCKET;
346 float First_sent_iamhere = 0;
347 float Last_sent_iamhere = 0;
349 #define CONNECTSEQ 0x142 // Magic number for starting a connection, just so it isn't 0
351 unsigned int Serverconn = 0xffffffff;
354 #pragma pack(pop,r_udp)
358 //*******************************
361 network_packet_buffer_list Psnet_top_buffers[PSNET_NUM_TYPES];
363 // -------------------------------------------------------------------------------------------------------
364 // PSNET 2 FORWARD DECLARATIONS
367 // if the string is a legally formatted ip string
368 int psnet_is_valid_numeric_ip(char *ip);
370 // functions to get the status of a RAS connection
371 unsigned int psnet_ras_status();
373 // set some options on a socket
374 void psnet_socket_options( SOCKET sock );
376 // initialize tcp socket
377 int psnet_init_tcp();
379 // get time in seconds
380 float psnet_get_time();
382 // returns the ip address of this machine. use for calling bind() with to associate with the proper
383 // IP address and network device.
386 // initialize reliable sockets
387 int psnet_init_rel_tcp(int port, int should_listen);
389 // shutdown reliable sockets
390 void psnet_rel_close();
392 // initialize the buffering system
393 void psnet_buffer_init(network_packet_buffer_list *l);
395 // buffer a packet (maintain order!)
396 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr_t *from);
398 // get the index of the next packet in order!
399 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr_t *from);
402 // -------------------------------------------------------------------------------------------------------
403 // PSNET 2 TOP LAYER FUNCTIONS - these functions simply buffer and store packets based upon type (see PSNET_TYPE_* defines)
406 // wrappers around select() and recvfrom() for lagging/losing data
407 int RECVFROM(SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen, int psnet_type)
409 network_packet_buffer_list *l;
415 SDL_assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
416 if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
419 l = &Psnet_top_buffers[psnet_type];
421 // if we have no buffer! The user should have made sure this wasn't the case by calling SELECT()
422 ret = psnet_buffer_get_next(l, (ubyte*)buf, &ret_len, &addr);
428 // otherwise, stuff the outgoing data
429 ((struct sockaddr_in*)from)->sin_port = htons(addr.port);
430 memcpy(&((struct sockaddr_in*)from)->sin_addr.s_addr, addr.addr, 4);
431 ((struct sockaddr_in*)from)->sin_family = AF_INET;
432 *fromlen = sizeof(struct sockaddr_in);
438 // wrappers around select() and recvfrom() for lagging/losing data
439 int SELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, int psnet_type)
441 network_packet_buffer_list *l;
443 // if this is a check for writability, just return the select
444 if(writefds != NULL){
445 return select(nfds, readfds, writefds, exceptfds, timeout);
449 SDL_assert((psnet_type >= 0) && (psnet_type < PSNET_NUM_TYPES));
450 if((psnet_type < 0) || (psnet_type >= PSNET_NUM_TYPES)){
453 l = &Psnet_top_buffers[psnet_type];
455 // do we have any buffers in here?
456 if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
464 // wrappers around sendto to sorting through different packet types
465 int SENDTO(SOCKET s, char * buf, int len, int flags, sockaddr *to, int tolen, int psnet_type)
467 char outbuf[MAX_TOP_LAYER_PACKET_SIZE + 150];
470 outbuf[0] = (char)psnet_type;
471 memcpy(&outbuf[1], buf, len);
473 // is the socket writeable?
476 return sendto(s, outbuf, len + 1, flags, (struct sockaddr*)to, tolen);
479 // call this once per frame to read everything off of our socket
480 void PSNET_TOP_LAYER_PROCESS()
483 struct sockaddr_in ip_addr; // UDP/TCP socket structure
488 net_addr_t from_addr;
489 network_naked_packet packet_read;
491 // clear the addresses to remove compiler warnings
492 memset(&ip_addr, 0, sizeof(struct sockaddr_in));
494 if ( Network_status != NETWORK_STATUS_RUNNING ) {
495 ml_printf("Network ==> socket not inited in PSNET_TOP_LAYER_PROCESS");
500 // check if there is any data on the socket to be read. The amount of data that can be
501 // atomically read is stored in len.
504 FD_SET( Unreliable_socket, &rfds );
508 if ( select( Unreliable_socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
509 ml_printf("Error %d doing a socket select on read", WSAGetLastError());
513 // if the read file descriptor is not set, then bail!
514 if ( !FD_ISSET(Unreliable_socket, &rfds) ){
518 // get data off the socket and process
519 from_len = sizeof(struct sockaddr_in);
520 read_len = recvfrom( Unreliable_socket, (char*)packet_read.data, MAX_TOP_LAYER_PACKET_SIZE, 0, (struct sockaddr*)&ip_addr, &from_len);
522 // set the from_addr for storage into the packet buffer structure
523 from_addr.type = Socket_type;
524 from_addr.port = ntohs( ip_addr.sin_port );
525 memcpy(from_addr.addr, &ip_addr.sin_addr.s_addr, 4);
527 if ( read_len == SOCKET_ERROR ) {
528 // int x = WSAGetLastError();
529 ml_printf("Socket error on socket_get_data()");
533 // determine the packet type
534 int packet_type = packet_read.data[0];
535 // mprintf(("TOP LAYER PACKET %d!\n", packet_type));
536 if((packet_type < 0) || (packet_type >= PSNET_NUM_TYPES)){
540 psnet_buffer_packet(&Psnet_top_buffers[packet_type], packet_read.data + 1, read_len - 1, &from_addr);
546 // -------------------------------------------------------------------------------------------------------
550 // initialize psnet to use the specified port
551 void psnet_init( int protocol, int port_num )
553 const char *internet_connection;
560 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
564 // GAME PORT INITIALIZATION STUFF
565 if ( Network_status == NETWORK_STATUS_RUNNING ){
566 ml_string("Skipping psnet_init() because network already running");
570 // 'lan' should be a safe default in 2015
571 internet_connection = os_config_read_string("Network", "NetworkConnection", "LAN");
573 if ( !SDL_strcasecmp(internet_connection, NOX("dialup")) ) {
574 ml_string("psnet_init() detected dialup connection");
576 Psnet_connection = NETWORK_CONNECTION_DIALUP;
577 } else if ( !SDL_strcasecmp(internet_connection, NOX("lan")) ) {
578 ml_string("psnet_init() detected lan connection");
580 Psnet_connection = NETWORK_CONNECTION_LAN;
582 ml_string("psnet_init() detected no connection");
584 Psnet_connection = NETWORK_CONNECTION_NONE;
587 Network_status = NETWORK_STATUS_NO_WINSOCK;
589 if (WSAStartup(0x101, &wsa_data )){
594 // get the port for running this game on. Be careful that it cannot be out of bounds
595 Psnet_default_port = DEFAULT_GAME_PORT;
596 if ( (port_num > 1023) && (port_num < USHRT_MAX) ) {
597 Psnet_default_port = (ushort)port_num;
600 // initialize TCP now
602 if(!psnet_init_tcp()){
603 ml_printf("Error on TCP startup %d", Tcp_failure_code);
607 if(!psnet_init_rel_tcp(Psnet_default_port + 1, 0)){
608 ml_printf("Network", "Error on TCP startup %d", Tcp_failure_code);
614 // clear reliable sockets
615 reliable_socket *rsocket;
617 for(j=0; j<MAXRELIABLESOCKETS; j++){
618 rsocket=&Reliable_sockets[j];
619 memset(rsocket,0,sizeof(reliable_socket));
622 // determine if we've successfully initialized the protocol we want
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;
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 ){
660 WSACancelBlockingCall();
663 if ( TCP_socket != (int)INVALID_SOCKET ) {
664 shutdown( TCP_socket, 1 );
665 closesocket( TCP_socket );
670 //Warning( LOCATION, "Error closing wsock!\n" );
674 // close down all reliable sockets - this forces them to
675 // send a disconnect to any remote machines
678 Network_status = NETWORK_STATUS_NOT_INITIALIZED;
681 // set the protocol to use
682 int psnet_use_protocol( int protocol )
685 struct sockaddr_in ip_addr;
687 // zero out my address
688 Psnet_my_addr_valid = 0;
689 memset( &Psnet_my_addr, 0, sizeof(Psnet_my_addr) );
691 // wait until we choose a protocol to determine if we can broadcast
694 ml_string("In psnet_use_protocol()");
696 if (protocol != NET_TCP) {
702 if ( Network_status != NETWORK_STATUS_RUNNING ){
703 ml_string("Network_status != NETWORK_STATUS_RUNNING in NET_TCP in psnet_use_protocol()");
707 // assign the TCP_* sockets to the socket values used elsewhere
708 Unreliable_socket = TCP_socket;
710 Can_broadcast = Tcp_can_broadcast;
712 ml_printf("Psnet : TCP broadcast");
715 // get the socket name, and put it into My_addr
716 len = sizeof(struct sockaddr_in);
717 if ( getsockname(TCP_socket, (struct sockaddr *)&ip_addr, &len) == SOCKET_ERROR ) {
718 ml_printf("Unable to get sock name for TCP unreliable socket (%d)", WSAGetLastError() );
723 memcpy(Psnet_my_addr.addr, &ip_addr.sin_addr, 4);
724 Psnet_my_addr.port = Psnet_default_port;
726 ml_printf("Psnet using - NET_TCP");
729 Psnet_my_addr.type = protocol;
730 Socket_type = protocol;
735 // get the status of the network
736 int psnet_get_network_status()
738 // first case is when "none" is selected
739 if ( Psnet_connection == NETWORK_CONNECTION_NONE ) {
740 return NETWORK_ERROR_NO_TYPE;
743 // first, check the connection status of the network
744 if ( Network_status == NETWORK_STATUS_NO_WINSOCK )
745 return NETWORK_ERROR_NO_WINSOCK;
747 if ( Network_status == NETWORK_STATUS_NO_PROTOCOL ){
748 return NETWORK_ERROR_NO_PROTOCOL;
751 // network is running -- be sure that the RAS people know to connect if they currently cannot.
753 if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
754 // if on a dialup connection, be sure that RAS is active.
755 if ( !Ras_connected ) {
756 return NETWORK_ERROR_CONNECT_TO_ISP;
758 } else if ( Psnet_connection == NETWORK_CONNECTION_LAN ) {
759 // if on a LAN, and they have a dialup connection active, return error to indicate that they need
760 // to pick the right connection type
761 if ( Ras_connected ) {
762 return NETWORK_ERROR_LAN_AND_RAS;
765 return NETWORK_ERROR_NONE;
768 // convert a net_addr to a string
769 char* psnet_addr_to_string( char * text, const int max_textlen, net_addr_t * address )
772 if ( Network_status != NETWORK_STATUS_RUNNING ) {
773 SDL_strlcpy( text, XSTR("[no networking]",910), max_textlen );
779 SDL_assert(address->type == NET_TCP);
781 memcpy(&temp_addr.s_addr, address->addr, 4);
782 SDL_strlcpy( text, inet_ntoa(temp_addr), max_textlen );
787 // convert a string to a net addr
788 void psnet_string_to_addr( net_addr_t * address, char * text, const int max_textlen )
791 char str[255], *c, *port;
794 if ( Network_status != NETWORK_STATUS_RUNNING ) {
795 SDL_strlcpy( text, XSTR("[no networking]",910), max_textlen );
799 // copy the text string to local storage to look for ports
800 SDL_assert( strlen(text) < 255 );
801 SDL_strlcpy(str, text, SDL_arraysize(str));
802 c = strrchr(str, ':');
809 SDL_assert(address->type == NET_TCP);
812 addr.s_addr = inet_addr(str);
813 // if we get INADDR_NONE returns, then we need to try and resolve the host
815 if ( addr.s_addr == INADDR_NONE ) {
816 he = gethostbyname( str );
817 // returns a non-null pointer if successful, so get the address
819 addr.s_addr = ((in_addr *)(he->h_addr))->s_addr; // this is the address in network byte order
821 addr.s_addr = INADDR_NONE;
825 memcpy(address->addr, &addr.s_addr, 4);
828 address->port = (ushort)(atoi(port));
832 // compare 2 addresses
833 int psnet_same( net_addr_t * a1, net_addr_t * a2 )
835 return ((a1->port == a2->port) && !memcmp(a1->addr, a2->addr, 4));
838 // send data unreliably
839 int psnet_send( net_addr_t * who_to, void * data, int len, int np_index )
841 // send data unreliably
843 struct sockaddr_in sockaddr; // UDP/TCP socket structure
845 ubyte iaddr[4], *send_data;
848 struct timeval timeout;
850 // always use the reliable socket
851 send_sock = Unreliable_socket;
853 if ( Network_status != NETWORK_STATUS_RUNNING ) {
854 ml_printf("Network ==> Socket not inited in psnet_send");
858 if ( psnet_same( who_to, &Psnet_my_addr) ){
862 if (who_to->type != NET_TCP) {
867 memcpy(iaddr, who_to->addr, 4);
869 if ( memcmp(iaddr, Null_address, 4) == 0) {
870 ml_printf("Network ==> send to address is 0 in psnet_send");
877 ml_printf("Network ==> destination port %d invalid in psnet_send", port);
881 // stuff the data with the type
882 send_data = (ubyte*)data;
886 FD_SET( send_sock, &wfds );
890 if ( SELECT( send_sock+1, NULL, &wfds, NULL, &timeout, PSNET_TYPE_UNRELIABLE) == SOCKET_ERROR ) {
891 ml_printf("Error on blocking select for write %d", WSAGetLastError() );
895 // if the write file descriptor is not set, then bail!
896 if ( !FD_ISSET(send_sock, &wfds ) ){
900 sockaddr.sin_family = AF_INET;
901 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
902 sockaddr.sin_port = htons(port);
904 multi_rate_add(np_index, "udp(h)", send_len + UDP_HEADER_SIZE);
905 multi_rate_add(np_index, "udp", send_len);
906 ret = SENDTO( send_sock, (char *)send_data, send_len, 0, (struct sockaddr*)&sockaddr, sizeof(sockaddr), PSNET_TYPE_UNRELIABLE );
908 if ( ret != SOCKET_ERROR ) {
911 //Warning( LOCATION, "Couldn't send data (0x%x)!\n", WSAGetLastError() );
915 // get data from the unreliable socket
916 int psnet_get( void * data, net_addr_t * from_addr )
920 // try and get a free buffer and return its size
921 if(psnet_buffer_get_next(&Psnet_top_buffers[PSNET_TYPE_UNRELIABLE], (ubyte*)data, &buffer_size, from_addr)){
929 // broadcast data on unreliable socket
930 int psnet_broadcast( net_addr_t * who_to, void * data, int len )
932 if ( Network_status != NETWORK_STATUS_RUNNING ) {
933 ml_printf("Network ==> Socket not inited in psnet_broadcast");
937 if ( !Can_broadcast ) {
938 ml_printf("Cannot broadcast -- returning without doing anything");
942 ubyte broadcast[4] = { 0xff, 0xff, 0xff, 0xff };
944 // broadcasting works on a local subnet which is all we really want to do for now anyway.
945 // we might keep this in as an option for freespace later.
946 memcpy(who_to->addr, broadcast, 4);
947 psnet_send(who_to, data, len);
955 ubyte data[MAX_TOP_LAYER_PACKET_SIZE + 250];
956 net_addr_t from_addr;
958 while ( psnet_get( data, &from_addr ) > 0 ) ;
961 // if the passed string is a valid IP string
962 int psnet_is_valid_ip_string( char *ip_string, int allow_port )
965 struct hostent *host_ent;
968 // our addresses may have ports, so make local copy and remove port number
969 SDL_assert( strlen(ip_string) < 255 );
970 SDL_strlcpy(str, ip_string, SDL_arraysize(str));
971 c = strrchr(str, ':');
976 addr.s_addr = inet_addr(ip_string);
977 if ( addr.s_addr != INADDR_NONE ){
978 // make sure the ip string is a valid format string
979 if(psnet_is_valid_numeric_ip(ip_string)){
984 // try name resolution
985 host_ent = gethostbyname( ip_string );
990 // valid host entry so return 1;
995 // -------------------------------------------------------------------------------------------------------
996 // PSNET 2 RELIABLE SOCKET FUNCTIONS
1000 int psnet_rel_ping_compare( const void *arg1, const void *arg2 )
1002 float *ping1 = (float *)arg1;
1003 float *ping2 = (float *)arg2;
1005 if(*ping1==*ping2) return 0;
1006 else if(*ping1>*ping2) return 1;
1007 else if(*ping1<*ping2) return -1;
1012 void psnet_rel_send_ack(struct sockaddr *raddr, unsigned int sig, ubyte link_type, float time_sent)
1015 reliable_header ack_header;
1017 if (link_type != NET_TCP) {
1022 ack_header.type = RNT_ACK;
1023 ack_header.data_len = sizeof(unsigned int);
1024 ack_header.send_time = INTEL_FLOAT( time_sent );
1025 sig_tmp = INTEL_INT( sig );
1026 memcpy(&ack_header.data,&sig_tmp,sizeof(unsigned int));
1028 if ( !Tcp_active ) {
1029 ml_string("No TCP in rel_send_ack()");
1033 SENDTO(Unreliable_socket, (char *)&ack_header, RELIABLE_PACKET_HEADER_ONLY_SIZE+sizeof(unsigned int), 0, raddr, sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1036 // function to shutdown and close the given socket. It takes a couple of things into consideration
1037 // when closing, such as possibly reiniting reliable sockets if they are closed here.
1038 void psnet_rel_close_socket( PSNET_SOCKET_RELIABLE *sockp )
1040 reliable_header diss_conn_header;
1042 if (*sockp == INVALID_SOCKET) {
1046 // if the socket is out of range
1047 if(*sockp>=MAXRELIABLESOCKETS)
1049 ml_printf("Invalid socket id passed to nw_NewCloseSocket() -- %d",*sockp);
1052 ml_printf("Closing socket %d",*sockp);
1054 // go through every buffer and "free it up(tm)"
1056 for(i=0;i<MAXNETBUFFERS;i++){
1057 if(Reliable_sockets[*sockp].rbuffers[i]){
1058 if(Reliable_sockets[*sockp].rbuffers[i] != NULL){
1059 free(Reliable_sockets[*sockp].rbuffers[i]);
1061 Reliable_sockets[*sockp].rbuffers[i] = NULL;
1062 Reliable_sockets[*sockp].rsequence[i] = 0;
1064 if(Reliable_sockets[*sockp].sbuffers[i]){
1065 if(Reliable_sockets[*sockp].sbuffers[i] != NULL){
1066 free(Reliable_sockets[*sockp].sbuffers[i]);
1068 Reliable_sockets[*sockp].sbuffers[i] = NULL;
1069 Reliable_sockets[*sockp].rsequence[i] = 0;
1073 // send a disconnect packet to the socket on the other end
1074 diss_conn_header.type = RNT_DISCONNECT;
1075 diss_conn_header.seq = CONNECTSEQ;
1076 diss_conn_header.data_len = 0;
1077 if(*sockp==Serverconn){
1078 Serverconn = 0xffffffff;
1081 if (Reliable_sockets[*sockp].connection_type == NET_TCP) {
1082 SDL_assert(Tcp_active);
1083 SENDTO(Unreliable_socket, (char *)&diss_conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[*sockp].addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1085 ml_printf("Unknown protocol type in nw_CloseSocket()!");
1089 memset(&Reliable_sockets[*sockp],0,sizeof(reliable_socket));
1090 Reliable_sockets[*sockp].status = RNF_UNUSED;
1093 // function to check the status of the reliable socket and try to re-initialize it if necessary.
1094 // win95 seems to have trouble doing a reinit of the socket immediately after close, so this
1095 // function exists to check the status, and reinitialize if we need to
1096 int psnet_rel_check()
1101 // send data reliably
1102 int psnet_rel_send(PSNET_SOCKET_RELIABLE socketid, ubyte *data, int length, int np_index)
1106 reliable_socket *rsocket;
1108 if(socketid >= MAXRELIABLESOCKETS){
1109 ml_printf("Invalid socket id passed to psnet_rel_send() -- %d",socketid);
1113 SDL_assert( length < (int)(sizeof(reliable_header)) );
1116 rsocket=&Reliable_sockets[socketid];
1117 if(rsocket->status!=RNF_CONNECTED) {
1118 //We can't send because this isn't a connected reliable socket.
1119 ml_printf("Can't send packet because of status %d in nw_SendReliable(). socket = %d",rsocket->status,socketid);
1123 // Add the new packet to the sending list and send it.
1124 for(i=0;i<MAXNETBUFFERS;i++){
1125 if(NULL==rsocket->sbuffers[i]){
1126 reliable_header send_header;
1127 int send_this_packet=1;
1129 rsocket->send_len[i] = length;
1130 rsocket->sbuffers[i] = (reliable_net_sendbuffer *)malloc(sizeof(reliable_net_sendbuffer));
1132 memcpy(rsocket->sbuffers[i]->buffer,data,length);
1134 send_header.seq = INTEL_SHORT( rsocket->theirsequence );
1135 rsocket->ssequence[i] = rsocket->theirsequence;
1137 memcpy(send_header.data,data,length);
1138 send_header.data_len = INTEL_SHORT( (ushort)length );
1139 send_header.type = RNT_DATA;
1140 send_header.send_time = psnet_get_time();
1141 send_header.send_time = INTEL_FLOAT( send_header.send_time );
1142 // struct sockaddr_in * rsockaddr = (struct sockaddr_in *)&rsocket->addr;
1144 if (send_this_packet){
1145 if (rsocket->connection_type == NET_TCP) {
1146 SDL_assert(Tcp_active);
1147 multi_rate_add(np_index, "tcp(h)", RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i]);
1148 bytesout = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1150 ml_printf("Unknown protocol type in nw_SendReliable()!");
1154 int error = WSAGetLastError();
1155 if((bytesout==SOCKET_ERROR)&&NETCALL_WOULDBLOCK(error)){
1156 //This will cause it to try to send again next frame. (or sooner)
1157 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1159 rsocket->timesent[i] = psnet_get_time();
1163 rsocket->theirsequence++;
1167 ml_printf("PSNET RELIABLE SEND BUFFER OVERRUN. socket = %d",socketid);
1173 // -1 socket not connected
1174 // 0 No packet ready to receive
1175 // >0 Buffer filled with the number of bytes recieved
1176 int psnet_rel_get(PSNET_SOCKET socketid, ubyte *buffer, int max_len)
1180 reliable_socket *rsocket = NULL;
1182 if(socketid >= MAXRELIABLESOCKETS){
1183 ml_printf("Invalid socket id passed to nw_NewReceiveReliable() -- %d",socketid);
1186 rsocket = &Reliable_sockets[socketid];
1187 if( (RNF_CONNECTED!=rsocket->status) && (RNF_LIMBO!=rsocket->status) ){
1188 ml_printf("Can't receive packet because it isn't connected in nw_ReceiveReliable(). socket = %d",socketid);
1191 //If the buffer position is the position we are waiting for, fill in
1192 //the buffer we received in the call to this function and return true
1194 for(i=0; i<MAXNETBUFFERS; i++){
1195 if((rsocket->rsequence[i] == rsocket->oursequence) && rsocket->rbuffers[i]){
1196 memcpy(buffer,rsocket->rbuffers[i]->buffer, rsocket->recv_len[i]);
1197 free(rsocket->rbuffers[i]);
1198 rsocket->rbuffers[i] = NULL;
1199 rsocket->rsequence[i] = 0;
1200 rsocket->oursequence++;
1201 return rsocket->recv_len[i];
1208 // process all active reliable sockets
1209 void psnet_rel_work()
1213 int max_len = NETBUFFERSIZE;
1215 struct timeval timeout;
1216 static reliable_header rcv_buff;
1217 static struct sockaddr rcv_addr;
1219 int addrlen = sizeof(struct sockaddr);
1223 PSNET_TOP_LAYER_PROCESS();
1225 // negotitate initial connection with the server
1226 reliable_socket *rsocket = NULL;
1227 if(Serverconn != 0xffffffff){
1228 //Check to see if we need to send a packet out.
1229 if((Reliable_sockets[Serverconn].status==RNF_LIMBO) && ((Serverconn != 0xffffffff) && fl_abs((psnet_get_time() - Last_sent_iamhere))>NETRETRYTIME) ){
1230 reliable_header conn_header;
1231 //Now send I_AM_HERE packet
1232 conn_header.type = RNT_I_AM_HERE;
1233 conn_header.seq = (ushort)(~CONNECTSEQ);
1234 conn_header.data_len = 0;
1235 Last_sent_iamhere = psnet_get_time();
1236 int ret = SOCKET_ERROR;
1238 if (Reliable_sockets[Serverconn].connection_type == NET_TCP) {
1239 SDL_assert(Tcp_active);
1240 ret = SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&Reliable_sockets[Serverconn].addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1243 int error = WSAGetLastError();
1244 if((ret == SOCKET_ERROR) && NETCALL_WOULDBLOCK(error)){
1245 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time()-NETRETRYTIME;
1247 Reliable_sockets[Serverconn].last_packet_sent = psnet_get_time();
1253 net_addr_t d3_rcv_addr;
1254 struct sockaddr_in *rcvaddr;
1255 int udp_has_data = 0;
1260 FD_SET(Unreliable_socket, &read_fds);
1262 udp_has_data = SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_RELIABLE);
1264 if (udp_has_data <= 0) {
1268 addrlen = sizeof(struct sockaddr);
1269 struct sockaddr_in *tcp_addr = (struct sockaddr_in *)&rcv_addr;
1270 memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1271 memset(&rcv_addr,0,sizeof(struct sockaddr));
1272 bytesin = RECVFROM(Unreliable_socket, (char *)&rcv_buff,sizeof(reliable_header), 0, (struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1273 rcv_buff.seq = INTEL_SHORT( rcv_buff.seq );
1274 rcv_buff.data_len = INTEL_SHORT( rcv_buff.data_len );
1275 rcv_buff.send_time = INTEL_FLOAT( rcv_buff.send_time );
1276 memcpy(d3_rcv_addr.addr, &tcp_addr->sin_addr.s_addr, 4);
1277 d3_rcv_addr.port = tcp_addr->sin_port;
1278 d3_rcv_addr.type = NET_TCP;
1279 link_type = NET_TCP;
1282 ml_printf("recvfrom returned an error! -- %d",WSAGetLastError());
1283 //Int3();//See Kevin
1287 //Someone wants to connect, so find a slot
1288 if(rcv_buff.type == RNT_REQ_CONN){
1289 for(i=1; i<MAXRELIABLESOCKETS; i++){
1290 if( (Reliable_sockets[i].status == RNF_CONNECTED) || (Reliable_sockets[i].status == RNF_LIMBO) ){
1291 //if(memcmp(&rcv_addr,&reliable_sockets[i].addr,sizeof(struct sockaddr))==0)
1292 if(memcmp(&d3_rcv_addr, &Reliable_sockets[i].net_addr, sizeof(net_addr_t)) == 0){
1293 //We already have a reliable link to this user, so we will ignore it...
1294 ml_printf("Received duplicate connection request. %d",i);
1295 //reliable_sockets[i].last_packet_received = timer_GetTime();
1296 psnet_rel_send_ack(&Reliable_sockets[i].addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1297 //We will change this as a hack to prevent later code from hooking us up
1298 rcv_buff.type = 0xff;
1303 for(i=1; i<MAXRELIABLESOCKETS; i++){
1304 if(Reliable_sockets[i].status == RNF_UNUSED){
1305 //Add the new connection here.
1306 Reliable_sockets[i].connection_type=link_type;
1307 memcpy(&Reliable_sockets[i].net_addr, &d3_rcv_addr, sizeof(net_addr_t));
1308 memcpy(&Reliable_sockets[i].addr ,&rcv_addr, sizeof(struct sockaddr));
1309 Reliable_sockets[i].ping_pos = 0;
1310 Reliable_sockets[i].num_ping_samples = 0;
1311 Reliable_sockets[i].status = RNF_LIMBO;
1312 Reliable_sockets[i].last_packet_received = psnet_get_time();
1313 rsocket = &Reliable_sockets[i];
1314 rcvaddr = (struct sockaddr_in *)&rcv_addr;
1315 ml_printf("Connect from %s:%d", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port));
1319 if(i==MAXRELIABLESOCKETS){
1320 //No more connections!
1321 ml_printf("Out of incoming reliable connection sockets");
1322 //Int3();//See Kevin
1325 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1328 //Find out if this is a packet from someone we were expecting a packet.
1329 rcvaddr = (struct sockaddr_in *)&rcv_addr;
1330 for(i=1; i<MAXRELIABLESOCKETS; i++){
1331 if(memcmp(&d3_rcv_addr,&Reliable_sockets[i].net_addr,sizeof(net_addr_t)) == 0){
1332 rsocket=&Reliable_sockets[i];
1336 if(rsocket == NULL){
1337 ml_printf("Received reliable data from unconnected client.");
1338 ml_printf("Received from %s:%d",inet_ntoa(rcvaddr->sin_addr),rcvaddr->sin_port);
1341 rsocket->last_packet_received = psnet_get_time();
1343 if(rsocket->status != RNF_CONNECTED){
1345 if(rsocket->status == RNF_LIMBO){
1346 //this is our connection to the server
1347 if(Serverconn != 0xffffffff){
1348 if(rcv_buff.type == RNT_ACK){
1349 ushort *acknum = (ushort *)&rcv_buff.data;
1350 if(*acknum == (~CONNECTSEQ & 0xffff)){
1351 rsocket->status = RNF_CONNECTED;
1352 ml_printf("Got ACK for IAMHERE!");
1356 } else if(rcv_buff.type == RNT_I_AM_HERE){
1357 rsocket->status = RNF_CONNECTING;
1358 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1359 ml_printf("Got IAMHERE!");
1363 if((rcv_buff.type == RNT_DATA) && (Serverconn != 0xffffffff)){
1364 rsocket->status = RNF_CONNECTED;
1366 rsocket->last_packet_received = psnet_get_time();
1370 //Update the last recv variable so we don't need a heartbeat
1371 rsocket->last_packet_received = psnet_get_time();
1373 if(rcv_buff.type == RNT_HEARTBEAT){
1376 if(rcv_buff.type == RNT_ACK){
1378 rsocket->num_ping_samples++;
1380 rsocket->pings[rsocket->ping_pos] = rsocket->last_packet_received - rcv_buff.send_time;
1381 if(rsocket->num_ping_samples >= MAX_PING_HISTORY){
1382 float sort_ping[MAX_PING_HISTORY];
1383 for(int a=0;a<MAX_PING_HISTORY;a++){
1384 sort_ping[a] = rsocket->pings[a];
1387 qsort(sort_ping ,MAX_PING_HISTORY, sizeof(float), psnet_rel_ping_compare);
1388 rsocket->mean_ping = ((sort_ping[MAX_PING_HISTORY/2]+sort_ping[(MAX_PING_HISTORY/2)+1]))/2;
1390 rsocket->ping_pos++;
1391 if(rsocket->ping_pos >= MAX_PING_HISTORY){
1392 rsocket->ping_pos=0;
1395 // if this is an ack for a send buffer on the socket, kill the send buffer. its done
1396 for(i=0; i<MAXNETBUFFERS; i++){
1397 unsigned int *acksig = (unsigned int *)&rcv_buff.data;
1399 if(rsocket->sbuffers[i]){
1400 if(rsocket->ssequence[i] == INTEL_INT(*acksig) ){
1401 SDL_assert(rsocket->sbuffers[i] != NULL);
1402 free(rsocket->sbuffers[i]);
1403 rsocket->sbuffers[i] = NULL;
1404 rsocket->ssequence[i] = 0;
1409 //remove that packet from the send buffer
1410 rsocket->last_packet_received = psnet_get_time();
1414 if(rcv_buff.type == RNT_DATA_COMP){
1416 //Decompress it. Put it back in the buffer. Process it as RNT_DATA
1417 rcv_buff.type = RNT_DATA;
1419 if(rcv_buff.type == RNT_DATA){
1420 //If the data is out of order by >= MAXNETBUFFERS-1 ignore that packet for now
1422 seqdelta = rcv_buff.seq - rsocket->oursequence;
1423 if(seqdelta<0) seqdelta = seqdelta*-1;
1424 if(seqdelta>=MAXNETBUFFERS - 1){
1425 ml_printf("Received reliable packet out of order!");
1426 //It's out of order, so we won't ack it, which will mean we will get it again soon.
1429 //else move data into the proper buffer position
1432 if(rsocket->oursequence < (0xffff - (MAXNETBUFFERS-1))){
1433 if (rsocket->oursequence > rcv_buff.seq){
1437 //Sequence is high, so prepare for wrap around
1438 if( ((unsigned short)(rcv_buff.seq + rsocket->oursequence)) > (MAXNETBUFFERS-1)){
1443 for(i=0; i<MAXNETBUFFERS; i++){
1444 if( (NULL != rsocket->rbuffers[i]) && (rsocket->rsequence[i] == rcv_buff.seq)){
1445 //Received duplicate packet!
1450 for(i=0; i<MAXNETBUFFERS; i++){
1451 if(NULL == rsocket->rbuffers[i]){
1452 if(rcv_buff.data_len>max_len){
1453 rsocket->recv_len[i] = rcv_buff.data_len;
1455 rsocket->recv_len[i] = rcv_buff.data_len;
1457 rsocket->rbuffers[i] = (reliable_net_rcvbuffer *)malloc(sizeof(reliable_net_rcvbuffer));
1458 memcpy(rsocket->rbuffers[i]->buffer,rcv_buff.data,rsocket->recv_len[i]);
1459 rsocket->rsequence[i] = rcv_buff.seq;
1464 psnet_rel_send_ack(&rsocket->addr, rcv_buff.seq, link_type, rcv_buff.send_time);
1468 } while (udp_has_data > 0);
1470 // Go through each reliable socket that is connected and do any needed work.
1471 for(j=0; j<MAXRELIABLESOCKETS; j++){
1472 rsocket=&Reliable_sockets[j];
1474 if(Serverconn == 0xffffffff){
1475 if(rsocket->status==RNF_LIMBO){
1476 if(fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout){
1477 ml_printf("Reliable (but in limbo) socket (%d) timed out in nw_WorkReliable().",j);
1478 memset(rsocket,0,sizeof(reliable_socket));
1479 rsocket->status = RNF_UNUSED;//Won't work if this is an outgoing connection.
1483 if((rsocket->status == RNF_LIMBO) && (fl_abs((psnet_get_time() - First_sent_iamhere)) > Nettimeout)){
1484 rsocket->status = RNF_BROKEN;
1485 ml_printf("Reliable socket (%d) timed out in nw_WorkReliable().",j);
1489 if(rsocket->status == RNF_CONNECTED){
1490 float retry_packet_time;
1491 if((rsocket->mean_ping==0) || (rsocket->mean_ping > (NETRETRYTIME*4))){
1492 retry_packet_time = NETRETRYTIME;
1494 if(rsocket->mean_ping<MIN_NET_RETRYTIME) {
1495 retry_packet_time = (float)MIN_NET_RETRYTIME;
1497 retry_packet_time = ((float)(float)rsocket->mean_ping * (float)1.25);
1500 //Iterate through send buffers.
1501 for(i=0;i<MAXNETBUFFERS;i++){
1503 if((rsocket->sbuffers[i]) && (fl_abs((psnet_get_time() - rsocket->timesent[i])) >= retry_packet_time)) {
1504 reliable_header send_header;
1505 send_header.send_time = psnet_get_time();
1506 send_header.send_time = INTEL_FLOAT( send_header.send_time );
1507 send_header.seq = INTEL_SHORT( rsocket->ssequence[i] );
1508 memcpy(send_header.data,rsocket->sbuffers[i]->buffer,rsocket->send_len[i]);
1509 send_header.data_len = INTEL_SHORT( (ushort)rsocket->send_len[i] );
1510 send_header.type = RNT_DATA;
1511 if(rsocket->connection_type == NET_TCP){
1512 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE+rsocket->send_len[i],0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1514 int error = WSAGetLastError();
1515 if((rcode == SOCKET_ERROR) && NETCALL_WOULDBLOCK(error)){
1516 //The packet didn't get sent, flag it to try again next frame
1517 rsocket->timesent[i] = psnet_get_time()-(NETRETRYTIME*4);
1519 rsocket->last_packet_sent = psnet_get_time();
1520 rsocket->timesent[i] = psnet_get_time();
1526 if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_sent)) > NETHEARTBEATTIME)) {
1527 reliable_header send_header;
1528 send_header.send_time = psnet_get_time();
1529 send_header.send_time = INTEL_FLOAT( send_header.send_time );
1530 send_header.seq = 0;
1531 send_header.data_len = 0;
1532 send_header.type = RNT_HEARTBEAT;
1535 if(rsocket->connection_type == NET_TCP){
1536 rcode = SENDTO(Unreliable_socket, (char *)&send_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,&rsocket->addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1538 int error = WSAGetLastError();
1539 if((rcode != SOCKET_ERROR) && NETCALL_WOULDBLOCK(error)){
1540 //It must have been sent
1541 rsocket->last_packet_sent = psnet_get_time();
1545 if((rsocket->status == RNF_CONNECTED) && (fl_abs((psnet_get_time() - rsocket->last_packet_received))>Nettimeout)){
1546 //This socket is hosed.....inform someone?
1547 ml_printf("Reliable Socket (%d) timed out in nw_WorkReliable().",j);
1548 rsocket->status = RNF_BROKEN;
1554 // get the status of a reliable socket, see RNF_* defines above
1555 int psnet_rel_get_status(PSNET_SOCKET_RELIABLE socketid)
1557 if(socketid >= MAXRELIABLESOCKETS){
1561 return Reliable_sockets[socketid].status;
1564 // function which checks the Listen_socket for possibly incoming requests to be connected.
1565 // returns 0 on error or nothing waiting. 1 if we should try to accept
1566 int psnet_rel_check_for_listen(net_addr_t *from_addr)
1568 struct sockaddr_in *ip_addr; // UDP/TCP socket structure
1572 for(i=1; i<MAXRELIABLESOCKETS; i++){
1573 if(Reliable_sockets[i].status == RNF_CONNECTING){
1574 Reliable_sockets[i].status = RNF_CONNECTED;
1575 //memcpy(from_addr,&reliable_sockets[i].addr,sizeof(struct sockaddr));
1576 ml_printf("New reliable connection in nw_CheckListenSocket().");
1578 if (Reliable_sockets[i].connection_type != NET_TCP) {
1582 ip_addr = (struct sockaddr_in *)&Reliable_sockets[i].addr;
1583 memset(from_addr, 0x00, sizeof(net_addr_t));
1584 from_addr->port = ntohs( ip_addr->sin_port );
1585 from_addr->type = NET_TCP;
1586 memcpy(from_addr->addr, &ip_addr->sin_addr.s_addr, 4);
1589 char dbg_output[50];
1590 nw_GetNumbersFromHostAddress(from_addr,dbg_output);
1591 mprintf((0,"Got address from: %s\n",dbg_output));
1596 return INVALID_SOCKET;
1599 // attacmpt to connect() to the server's tcp socket. socket parameter is simply assigned to the
1600 // Reliable_socket socket created in psnet_init
1601 void psnet_rel_connect_to_server(PSNET_SOCKET *socket, net_addr_t *server_addr)
1603 //Send out a RNT_REQ_CONN packet, and wait for it to be acked.
1604 struct sockaddr_in sockaddr; // UDP/TCP socket structure
1605 struct sockaddr *addr = NULL; // pointer to struct sockaddr to make coding easier
1606 struct sockaddr rcv_addr;
1610 // float time_sent_req = 0;
1611 float first_sent_req = 0;
1612 static reliable_header conn_header;
1613 static reliable_header ack_header;
1615 struct timeval timeout;
1618 *socket = INVALID_SOCKET;
1620 memcpy(iaddr, &server_addr->addr, 4);
1621 port = (ushort)(server_addr->port); // Talk to the server listen port
1623 conn_header.type = RNT_REQ_CONN;
1624 conn_header.seq = CONNECTSEQ;
1625 conn_header.data_len = 0;
1630 if (server_addr->type != NET_TCP) {
1634 SDL_assert(Tcp_active);
1636 //Flush out any left overs
1638 FD_SET(Unreliable_socket, &read_fds);
1639 while(SELECT(Unreliable_socket+1, &read_fds, NULL, NULL, &timeout, PSNET_TYPE_RELIABLE)){
1640 addrlen = sizeof(struct sockaddr);
1641 bytesin = RECVFROM(Unreliable_socket, (char *)&ack_header,sizeof(reliable_header),0,(struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1643 //Int3();//See Kevin
1644 ml_printf("UDP recvfrom returned an error! -- %d",WSAGetLastError());
1649 FD_SET(Unreliable_socket, &read_fds);
1652 memset(&ack_header,0,sizeof(reliable_header));
1653 SOCKET typeless_sock = 0;
1654 net_addr_t d3_rcv_addr;
1655 memset(&d3_rcv_addr,0,sizeof(net_addr_t));
1658 sockaddr.sin_family = AF_INET;
1659 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1660 sockaddr.sin_port = htons(port);
1661 addr = (struct sockaddr *)&sockaddr;
1662 if( SOCKET_ERROR == SENDTO(Unreliable_socket, (char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE) ){
1663 ml_printf("Unable to send UDP packet in nw_ConnectToServer()! -- %d",WSAGetLastError());
1666 memcpy(d3_rcv_addr.addr, &sockaddr.sin_addr.s_addr, 4);
1667 d3_rcv_addr.port = sockaddr.sin_port;
1668 d3_rcv_addr.type = NET_TCP;
1669 typeless_sock = Unreliable_socket;
1672 first_sent_req = psnet_get_time();
1673 // time_sent_req = psnet_get_time();
1675 //Wait until we get a response from the server or we timeout
1678 PSNET_TOP_LAYER_PROCESS();
1681 FD_SET(typeless_sock, &read_fds);
1682 if(SELECT(typeless_sock+1, &read_fds, NULL,NULL,&timeout, PSNET_TYPE_RELIABLE)){
1683 ml_string("selected() in psnet_rel_connect_to_server()");
1685 addrlen = sizeof(struct sockaddr);
1686 bytesin = RECVFROM(typeless_sock,(char *)&ack_header,sizeof(reliable_header),0,(struct sockaddr *)&rcv_addr,&addrlen, PSNET_TYPE_RELIABLE);
1688 ml_printf("recvfrom returned an error! -- %d",WSAGetLastError());
1693 ml_string("received data after select in psnet_rel_connect_to_server()");
1695 ml_string("about to check ack_header.type");
1696 if(ack_header.type == RNT_ACK){
1697 short *acknum = (short *)&ack_header.data;
1698 if(*acknum == CONNECTSEQ){
1699 for(i=1; i<MAXRELIABLESOCKETS; i++){
1700 if(Reliable_sockets[i].status==RNF_UNUSED){
1701 //Add the new connection here.
1702 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
1703 Reliable_sockets[i].connection_type = (ubyte)server_addr->type;
1704 memcpy(&Reliable_sockets[i].net_addr,&d3_rcv_addr,sizeof(net_addr_t));
1705 Reliable_sockets[i].last_packet_received = psnet_get_time();
1706 memcpy(&Reliable_sockets[i].addr,&rcv_addr,sizeof(struct sockaddr));
1707 Reliable_sockets[i].status = RNF_LIMBO;
1709 ml_printf("Succesfully connected to server in nw_ConnectToServer().");
1710 //Now send I_AM_HERE packet
1711 conn_header.type = RNT_I_AM_HERE;
1712 conn_header.seq = (ushort)(~CONNECTSEQ);
1713 conn_header.data_len = 0;
1715 First_sent_iamhere = psnet_get_time();
1716 Last_sent_iamhere = psnet_get_time();
1717 int rcode = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1718 if(rcode == SOCKET_ERROR){
1719 *socket = INVALID_SOCKET;
1720 Reliable_sockets[i].status = RNF_UNUSED;
1721 memset(&Reliable_sockets[i],0,sizeof(reliable_socket));
1722 ml_printf("Unable to send packet in nw_ConnectToServer()");
1725 Reliable_sockets[i].last_packet_sent = psnet_get_time();
1727 f = psnet_get_time();
1728 while((fl_abs((psnet_get_time() - f))<2) && (Reliable_sockets[i].status != RNF_CONNECTING)){
1735 ml_printf("Out of reliable socket space in nw_ConnectToServer().");
1737 } else ml_printf("Received out of sequence ACK in nw_ConnectToServer().");
1738 } else ml_printf("Received something that isn't an ACK in nw_ConnectToServer().");
1739 } else ml_printf("Received 0 bytes from recvfrom() in nw_ConnectToServer().");
1742 if((psnet_get_time()-time_sent_req)>2)
1744 ml_printf("Resending connect request.");
1745 int ret = SENDTO(typeless_sock,(char *)&conn_header,RELIABLE_PACKET_HEADER_ONLY_SIZE,0,addr,sizeof(struct sockaddr), PSNET_TYPE_RELIABLE);
1746 if(ret != SOCKET_ERROR){
1747 time_sent_req = psnet_get_time();
1749 ml_printf("Error sending connection request! -- %d",WSAGetLastError() );
1754 } while(fl_abs((psnet_get_time() - first_sent_req)) < RELIABLE_CONNECT_TIME);
1757 // returns the ip address of this computer
1759 int psnet_rel_get_ip()
1763 struct sockaddr_in local_address;
1766 // Get the local host name
1767 memset(&local_address, 0, sizeof(local_address));
1768 ret = gethostname(local, 255 );
1769 if (ret != SOCKET_ERROR ){
1770 // Resolve host name for local address
1771 hostent = gethostbyname((char *)local);
1773 local_address.sin_addr.s_addr = *((u_long FAR *)(hostent->h_addr));
1776 ml_string("SOCKET_ERROR in psnet_rel_get_ip()!");
1778 ml_printf(%s:%d", inet_ntoa(rcvaddr->sin_addr), htons(rcvaddr->sin_port)
1779 return local_address.sin_addr.s_addr;
1783 // returns the ip address of this computer
1786 struct sockaddr_in local_address;
1788 if(Psnet_connection == NETWORK_CONNECTION_DIALUP){
1789 local_address.sin_addr.s_addr = psnet_ras_status();
1790 if(local_address.sin_addr.s_addr == INADDR_NONE){
1791 local_address.sin_addr.s_addr = INADDR_ANY;
1794 // Init local address to zero
1795 local_address.sin_addr.s_addr = INADDR_ANY;
1798 // NOTE: for memeory checkers, do NOT try to free this
1799 ml_printf("psnet_get_ip() reports IP : %s", inet_ntoa(local_address.sin_addr));
1801 return local_address.sin_addr.s_addr;
1804 // initialize reliable sockets
1805 int psnet_init_rel_tcp(int port, int should_listen)
1808 struct sockaddr_in sockaddr;
1810 sockaddr.sin_port = htons((ushort)port);
1811 sockaddr.sin_family = AF_INET;
1813 ml_printf("Setting up reliable sockets.");
1815 my_ip = psnet_get_ip();
1817 memcpy(&sockaddr.sin_addr.s_addr, &my_ip, sizeof(uint));
1819 Reliable_UDP_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP );
1820 if(INVALID_SOCKET == Reliable_UDP_socket){
1821 ml_printf("Unable to create reliable UDP socket -- %d", WSAGetLastError() );
1824 } else if(bind(Reliable_UDP_socket,(struct sockaddr *)&sockaddr,sizeof(struct sockaddr))!=0){
1825 ml_printf("Unable to bind reliable socket -- %d", WSAGetLastError() );
1830 // make any reliable sockets which we create that aren't listening non-blocking sockets
1835 error = ioctlsocket( Reliable_UDP_socket, FIONBIO, &arg );
1836 if ( error == SOCKET_ERROR ) {
1837 ml_printf("Unable to make reliable UDP socket non-blocking -- %d", WSAGetLastError() );
1847 void psnet_rel_close()
1850 PSNET_SOCKET_RELIABLE sock;
1853 for(idx=0; idx<MAXRELIABLESOCKETS; idx++){
1854 if(Reliable_sockets[idx].status != RNF_UNUSED){
1856 psnet_rel_close_socket(&sock);
1861 // ------------------------------------------------------------------------------------------------------
1862 // PACKET BUFFERING FUNCTIONS
1865 // initialize the buffering system
1866 void psnet_buffer_init(network_packet_buffer_list *l)
1870 // blast the buffer clean
1871 memset(l->psnet_buffers, 0, sizeof(network_packet_buffer) * MAX_PACKET_BUFFERS);
1873 // set all buffer sequence #'s to -1
1874 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
1875 l->psnet_buffers[idx].sequence_number = -1;
1878 // initialize the sequence #
1879 l->psnet_seq_number = 0;
1880 l->psnet_lowest_id = -1;
1881 l->psnet_highest_id = -1;
1884 // buffer a packet (maintain order!)
1885 void psnet_buffer_packet(network_packet_buffer_list *l, ubyte *data, int length, net_addr_t *from)
1890 // find the first empty packet
1891 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
1892 if(l->psnet_buffers[idx].sequence_number == -1){
1898 // if we didn't find the buffer, report an overrun
1900 ml_printf("WARNING - Buffer overrun in psnet");
1903 memcpy(l->psnet_buffers[idx].data, data, length);
1904 l->psnet_buffers[idx].len = length;
1905 memcpy(&l->psnet_buffers[idx].from_addr, from, sizeof(net_addr_t));
1906 l->psnet_buffers[idx].sequence_number = l->psnet_seq_number;
1908 // keep track of the highest id#
1909 l->psnet_highest_id = l->psnet_seq_number++;
1911 // set the lowest id# for the first time
1912 if(l->psnet_lowest_id == -1){
1913 l->psnet_lowest_id = l->psnet_highest_id;
1918 // get the index of the next packet in order!
1919 int psnet_buffer_get_next(network_packet_buffer_list *l, ubyte *data, int *length, net_addr_t *from)
1923 // if there are no buffers, do nothing
1924 if((l->psnet_lowest_id == -1) || (l->psnet_lowest_id > l->psnet_highest_id)){
1928 // search until we find the lowest packet index id#
1929 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
1930 // if we found the buffer
1931 if(l->psnet_buffers[idx].sequence_number == l->psnet_lowest_id){
1936 // at this point, we should _always_ have found the buffer
1937 if (idx == MAX_PACKET_BUFFERS) {
1942 // copy out the buffer data
1943 memcpy(data, l->psnet_buffers[idx].data, l->psnet_buffers[idx].len);
1944 *length = l->psnet_buffers[idx].len;
1945 memcpy(from, &l->psnet_buffers[idx].from_addr, sizeof(net_addr_t));
1947 // now we need to cleanup the packet list
1949 // mark the buffer as free
1950 l->psnet_buffers[idx].sequence_number = -1;
1951 l->psnet_lowest_id++;
1956 // -------------------------------------------------------------------------------------------------------
1957 // PSNET 2 FORWARD DEFINITIONS
1960 // if the string is a legally formatted ip string
1961 int psnet_is_valid_numeric_ip(char *ip)
1965 int val1,val2,val3,val4;
1967 // get the first ip value
1968 SDL_strlcpy(copy, ip, SDL_arraysize(copy));
1969 token = strtok(copy,".");
1973 // get the value of the token
1975 if((val1 < 0) || (val1 > 255)){
1981 token = strtok(NULL,".");
1985 // get the value of the token
1987 if((val2 < 0) || (val2 > 255)){
1993 token = strtok(NULL,".");
1997 // get the value of the token
1999 if((val3 < 0) || (val3 > 255)){
2005 token = strtok(NULL,"");
2009 // get the value of the token
2011 if((val4 < 0) || (val4 > 255)){
2016 // make sure he hasn't entered all 0's
2017 if((val1 == 0) && (val2 == 0) && (val3 == 0) && (val4 == 0)){
2025 // function called from high level FreeSpace code to determine the status of the networking
2026 // code returns one of a handful of macros
2028 DWORD (__stdcall *pRasEnumConnections)(LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections) = NULL;
2029 DWORD (__stdcall *pRasGetConnectStatus)(HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) = NULL;
2030 DWORD (__stdcall *pRasGetProjectionInfo)(HRASCONN hrasconn, RASPROJECTION rasprojection, LPVOID lpprojection, LPDWORD lpcb ) = NULL;
2032 // functions to get the status of a RAS connection
2033 unsigned int psnet_ras_status()
2036 unsigned long size, num_connections, i;
2037 RASCONN rasbuffer[25];
2038 HINSTANCE ras_handle;
2039 unsigned long rasip=0;
2040 RASPPPIP projection;
2041 // int Ras_connected;
2045 // first, call a LoadLibrary to load the RAS api
2046 ras_handle = LoadLibrary( (LPCWSTR)"rasapi32.dll" );
2047 if ( ras_handle == NULL ) {
2051 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, "RasEnumConnectionsA");
2052 if (!pRasEnumConnections) {
2053 FreeLibrary( ras_handle );
2056 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, "RasGetConnectStatusA");
2057 if (!pRasGetConnectStatus) {
2058 FreeLibrary( ras_handle );
2061 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, "RasGetProjectionInfoA");
2062 if (!pRasGetProjectionInfo) {
2063 FreeLibrary( ras_handle );
2067 size = sizeof(rasbuffer);
2068 rasbuffer[0].dwSize = sizeof(RASCONN);
2070 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2072 FreeLibrary( ras_handle );
2076 // JAS: My computer gets to this point, but I have no RAS connections,
2078 if ( num_connections < 1 ) {
2079 ml_string("Found no RAS connections");
2080 FreeLibrary( ras_handle );
2084 ml_printf("Found %d connections", num_connections);
2086 for (i = 0; i < num_connections; i++ ) {
2087 RASCONNSTATUS status;
2089 ml_printf("Connection %d:", i);
2090 ml_printf("Entry Name: %s", rasbuffer[i].szEntryName);
2091 ml_printf("Device Type: %s", rasbuffer[i].szDeviceType);
2092 ml_printf("Device Name: %s", rasbuffer[i].szDeviceName);
2094 // get the connection status
2095 status.dwSize = sizeof(RASCONNSTATUS);
2096 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2098 FreeLibrary( ras_handle );
2102 // get the projection informatiom
2103 size = sizeof(projection);
2104 projection.dwSize = size;
2105 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2107 FreeLibrary( ras_handle );
2111 ml_printf("IP Address: %s", projection.szIpAddress);
2116 FreeLibrary( ras_handle );
2117 rasip = inet_addr((const char *)projection.szIpAddress);
2118 if(rasip==INADDR_NONE){
2122 //The ip of the RAS connection
2126 unsigned int psnet_ras_status()
2134 // functions to get the status of a RAS connection
2136 void psnet_ras_status()
2139 unsigned long size, num_connections, i;
2140 RASCONN rasbuffer[25];
2141 HINSTANCE ras_handle;
2145 // first, call a LoadLibrary to load the RAS api
2146 ras_handle = LoadLibrary( NOX("rasapi32.dll") );
2147 if ( ras_handle == NULL ) {
2151 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, NOX("RasEnumConnectionsA"));
2152 if (!pRasEnumConnections) {
2153 FreeLibrary( ras_handle );
2156 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, NOX("RasGetConnectStatusA"));
2157 if (!pRasGetConnectStatus) {
2158 FreeLibrary( ras_handle );
2161 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, NOX("RasGetProjectionInfoA"));
2162 if (!pRasGetProjectionInfo) {
2163 FreeLibrary( ras_handle );
2167 size = sizeof(rasbuffer);
2168 rasbuffer[0].dwSize = sizeof(RASCONN);
2170 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
2172 FreeLibrary( ras_handle );
2176 // JAS: My computer gets to this point, but I have no RAS connections,
2178 if ( num_connections < 1 ) {
2179 ml_printf("Found no connections" );
2180 FreeLibrary( ras_handle );
2184 ml_printf("Found %d connections", num_connections);
2186 for (i = 0; i < num_connections; i++ ) {
2187 RASCONNSTATUS status;
2188 RASPPPIP projection;
2191 ml_printf("Connection %d:", i);
2192 ml_printf("Entry Name: %s", rasbuffer[i].szEntryName);
2193 ml_printf("Device Type: %s", rasbuffer[i].szDeviceType);
2194 ml_printf("Device Name: %s", rasbuffer[i].szDeviceName);
2196 // get the connection status
2197 status.dwSize = sizeof(RASCONNSTATUS);
2198 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
2200 FreeLibrary( ras_handle );
2204 ml_printf("\tStatus: %s", (status.rasconnstate==RASCS_Connected)?"Connected":"Not Connected");
2206 // get the projection informatiom
2207 size = sizeof(projection);
2208 projection.dwSize = size;
2209 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
2211 FreeLibrary( ras_handle );
2215 ml_printf("IP Address: %s", projection.szIpAddress));
2220 FreeLibrary( ras_handle );
2224 // set some options on a socket
2225 void psnet_socket_options( SOCKET sock )
2227 int broadcast;//, ret;
2228 SOCKLEN_T cursize, cursizesize, bufsize;
2230 // Set the mode of the socket to allow broadcasting
2232 if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast) )){
2239 // setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&broadcast, sizeof(broadcast) );
2241 // try and increase the size of my receive buffer
2242 bufsize = MAX_RECEIVE_BUFSIZE;
2244 // set the current size of the receive buffer
2245 cursizesize = sizeof(int);
2246 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&cursize, &cursizesize);
2247 // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2248 /*ret =*/ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize));
2249 /*if ( ret == SOCKET_ERROR ) {
2252 wserr = WSAGetLastError();
2253 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
2257 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&cursize, &cursizesize);
2258 ml_printf("Receive buffer set to %d", cursize);
2260 // set the current size of the send buffer
2261 cursizesize = sizeof(int);
2262 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&cursize, &cursizesize);
2263 // for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
2264 /*ret =*/ setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize));
2265 /*if ( ret == SOCKET_ERROR ) {
2268 wserr = WSAGetLastError();
2269 // if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) ){
2273 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&cursize, &cursizesize);
2274 ml_printf("Send buffer set to %d", cursize);
2277 // initialize tcp socket
2278 int psnet_init_tcp()
2280 struct sockaddr_in sockaddr;
2282 TCP_socket = INVALID_SOCKET;
2284 TCP_socket = socket( AF_INET, SOCK_DGRAM, 0 );
2285 if ( TCP_socket == (int)INVALID_SOCKET ) {
2286 Tcp_failure_code = WSAGetLastError();
2287 ml_printf("Error on TCP startup %d", Tcp_failure_code);
2292 memset(&sockaddr,0,sizeof(struct sockaddr_in));
2293 sockaddr.sin_family = AF_INET;
2294 sockaddr.sin_addr.s_addr = psnet_get_ip();
2295 sockaddr.sin_port = htons( Psnet_default_port );
2296 if ( bind(TCP_socket, (struct sockaddr*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
2297 Tcp_failure_code = WSAGetLastError();
2298 ml_printf("Couldn't bind TCP socket (%d)! Invalidating TCP", Tcp_failure_code );
2302 // set socket options
2303 psnet_socket_options( TCP_socket );
2304 Tcp_can_broadcast = Can_broadcast;
2310 // get time in seconds
2311 float psnet_get_time()
2313 return (float)timer_get_milliseconds() / 1000.0f;
2316 // mark a socket as having received data
2317 void psnet_mark_received(PSNET_SOCKET_RELIABLE socket)
2320 if((socket == 0xffffffff) || (socket >= MAXRELIABLESOCKETS)){
2325 Reliable_sockets[socket].last_packet_received = psnet_get_time();