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/PsNet.cpp $
15 * C file containing application level network-interface.
18 * Revision 1.5 2002/06/09 04:41:24 relnev
19 * added copyright header
21 * Revision 1.4 2002/06/02 02:29:39 relnev
24 * Revision 1.3 2002/05/26 20:49:54 theoddone33
27 * Revision 1.2 2002/05/07 03:16:48 theoddone33
28 * The Great Newline Fix
30 * Revision 1.1.1.1 2002/05/03 03:28:10 root
34 * 7 7/15/99 9:20a Andsager
35 * FS2_DEMO initial checkin
37 * 6 11/19/98 4:19p Dave
38 * Put IPX sockets back in psnet. Consolidated all multiplayer config
41 * 5 11/19/98 8:04a Dave
42 * Full support for D3-style reliable sockets. Revamped packet lag/loss
43 * system, made it receiver side and at the lowest possible level.
45 * 4 11/17/98 11:12a Dave
46 * Removed player identification by address. Now assign explicit id #'s.
48 * 3 10/09/98 2:57p Dave
49 * Starting splitting up OS stuff.
51 * 2 10/07/98 10:53a Dave
54 * 1 10/07/98 10:50a Dave
56 * 107 9/15/98 4:04p Allender
57 * added back in the -ip_addr command line switch because it needs to be
58 * in the standalone server only executable
60 * 106 9/14/98 11:28a Allender
61 * support for server bashing of address when received from client. Added
62 * a cmdline.cfg file to process command line arguments from a file
64 * 105 9/08/98 2:20p Allender
65 * temporary code to force IP address to a specific value.
67 * 104 8/21/98 1:15p Dave
68 * Put in log system hooks in useful places.
70 * 103 8/12/98 4:50p Allender
71 * fix error with new write socket code
73 * 102 8/11/98 11:45a Allender
74 * fix major problem in psnet_send where select() would block until ready
75 * to send, which for slow modems could be a long time. Doesn't block,
76 * and now correctly returns when socket is not set for writing
78 * 101 8/07/98 10:40a Allender
79 * new command line flags for starting netgames. Only starting currently
80 * works, and PXO isn't implemented yet
82 * 100 7/28/98 4:43p Allender
83 * fix bug where error on receiving of reliable data would sometimes
86 * 99 7/06/98 5:05p Allender
87 * dont use default port to send UDP data to. Use port stored in address
89 * 98 6/13/98 9:32p Mike
90 * Kill last character in file which caused "Find in Files" to report the
91 * file as "not a text file."
93 * 97 6/13/98 6:01p Hoffoss
94 * Externalized all new (or forgot to be added) strings to all the code.
96 * 96 6/13/98 3:19p Hoffoss
97 * NOX()ed out a bunch of strings that shouldn't be translated.
99 * 95 6/10/98 2:56p Dave
100 * Substantial changes to reduce bandwidth and latency problems.
102 * 94 6/05/98 9:55a Lawrance
105 * 93 5/24/98 2:17p Allender
106 * make reliable socket read all data before returning
108 * 92 5/22/98 10:54a Allender
109 * new dialog information for networking to tell user if connection type
110 * doesn't match the setup specified type
112 * 91 5/21/98 3:31p Allender
113 * more RAS stuff -- fix possible problem when unable to read data on
116 * 90 5/20/98 4:34p John
117 * fixed some bugs with rasenum connections. HAd to specify ansi versions
118 * in dll. Also, my pc returned 0 connections, before that still said
119 * there was a connection.
127 #include <windowsx.h>
131 #include <raserror.h>
133 #include <sys/types.h>
134 #include <sys/socket.h>
135 #include <netinet/in.h>
136 #include <arpa/inet.h>
137 #include <sys/ioctl.h>
147 #include "multiutil.h"
148 #include "multilag.h"
149 #include "osregistry.h"
151 #include "multi_log.h"
156 // old style packet buffering
157 // #define PSNET_BUFFER_OLD_SCHOOL
161 SOCKET TCP_reliable_socket;
162 SOCKET TCP_listen_socket;
164 // the sockets that the game will use when selecting network type
165 SOCKET Unreliable_socket = INVALID_SOCKET;
166 SOCKET Reliable_socket = INVALID_SOCKET;
167 SOCKET Listen_socket = INVALID_SOCKET;
169 int Psnet_my_addr_valid;
170 net_addr_t Psnet_my_addr;
172 ubyte Null_address[IP_ADDRESS_LENGTH];
175 int Can_broadcast; // can we do broadcasting on our socket?
176 int Tcp_can_broadcast = 0;
181 int Tcp_failure_code = 0;
183 int Psnet_connection;
185 ushort Psnet_default_port;
187 unsigned int Serverconn = 0xffffffff;
189 // specified their internet connnection type
190 #define NETWORK_CONNECTION_NONE 1
191 #define NETWORK_CONNECTION_DIALUP 2
192 #define NETWORK_CONNECTION_LAN 3
194 // defines and variables to indicate network connection status
195 #define NETWORK_STATUS_NOT_INITIALIZED 1
196 #define NETWORK_STATUS_NO_WINSOCK 2 // winsock failed to initialize
197 #define NETWORK_STATUS_NO_PROTOCOL 3 // specified protocol doesn't appear to be loaded
198 #define NETWORK_STATUS_NO_RELIABLE 4
199 #define NETWORK_STATUS_RUNNING 5 // everything should be running
201 // defintion of structures that actually leave this machine. psnet_send give us only
202 // the data that we want to send. We will add a header onto this data (packet sequence
203 // number, possibly a checksum). We must include a 2 byte flags variable into both structure
204 // since the receiving end of this packet must know whether or not to checksum the packet.
206 // use the pack pragma to pack these structures to 2 byte aligment. Really only needed for
209 #pragma pack(push, 2)
211 // packet def for a checksum'ed packet
212 #define MAX_CHECKSUM_PACKET_SIZE 1024
213 typedef struct network_checksum_packet
218 ubyte data[MAX_CHECKSUM_PACKET_SIZE];
219 } network_checksum_packet;
221 // definition for a non-checksum packet
222 typedef struct network_packet
226 ubyte data[MAX_PACKET_SIZE];
227 } network_naked_packet;
229 // structure definition for our packet buffers
230 typedef struct network_packet_buffer
234 net_addr_t from_addr;
235 ubyte data[MAX_PACKET_SIZE];
236 } network_packet_buffer;
240 #define MAX_PACKET_BUFFERS 96
242 #ifdef PSNET_BUFFER_OLD_SCHOOL
243 static network_packet_buffer packet_buffers[MAX_PACKET_BUFFERS]; // buffer to hold packets sent to us
244 static short packet_free_list[MAX_PACKET_BUFFERS]; // contains id's of free packet buffers
245 static Num_packet_buffers;
246 static int Largest_packet_index = 0;
252 // variables to keep track of bytes read/written during the course of network play
255 #define PSNET_FRAME_FILTER 32
256 #define MAX_NET_STATS 32
260 net_addr_t addr; // stats for this address
261 int total_read; // total bytes read
262 int total_written; // total bytes read.
270 net_stats Psnet_stats[MAX_NET_STATS];
271 socket_xlate Psnet_socket_addr[MAX_NET_STATS];
273 int psnet_bytes_read_frame; // running count of bytes read this frame
274 int psnet_bytes_written_frame; // running count of bytes written this frame
276 int Psnet_bytes_read; // globally available numbers for printing on the hud
277 int Psnet_bytes_written;
279 int psnet_read_sizes[PSNET_FRAME_FILTER];
280 int psnet_write_sizes[PSNET_FRAME_FILTER];
282 int psnet_read_total;
283 int psnet_write_total;
285 int psnet_frame_count;
289 #define MAXHOSTNAME 128
291 #define MAX_RECEIVE_BUFSIZE (1<<15) // 32 K, eh?
292 #define MAX_SEND_RETRIES 20 // number of retries when sending would block
293 #define MAX_LINGER_TIME 0 // in seconds -- when lingering to close a socket
297 int psnet_same_no_port( net_addr_t * a1, net_addr_t * a2 );
299 // do stats for a particular address. num_bytes is the number of bytes either read or
300 // written (depending on the read flag. read flag is true when reading, 0 when writing
301 void psnet_do_net_stats( net_addr_t *addr, int num_bytes, int read )
305 for ( i = 0; i < MAX_NET_STATS; i++ ) {
306 if ( !Psnet_stats[i].in_use )
308 if ( addr && psnet_same_no_port(&Psnet_stats[i].addr, addr) )
312 if ( i == MAX_NET_STATS ) {
313 // find the first NULL entry
314 for ( i = 0; i < MAX_NET_STATS; i++ ) {
315 if ( !Psnet_stats[i].in_use )
318 if ( i == MAX_NET_STATS ) {
319 Int3(); // we should always have a slot
322 Psnet_stats[i].addr = *addr;
323 Psnet_stats[i].in_use = 1;
326 Psnet_stats[i].total_read += num_bytes;
328 Psnet_stats[i].total_written += num_bytes;
331 // returns the stats for the given network address. returns 1 when (i.e. net_addr was found),
332 // 0 otherwise. total read and total written are returned in the parameters
333 int psnet_get_stats( net_addr_t *addr, int *tr, int *tw )
337 for ( i = 0; i < MAX_NET_STATS; i++ ) {
338 if ( !Psnet_stats[i].in_use )
341 if ( addr && psnet_same_no_port(&Psnet_stats[i].addr, addr) )
345 if ( i == MAX_NET_STATS )
348 *tr = Psnet_stats[i].total_read;
349 *tw = Psnet_stats[i].total_written;
354 void psnet_stats_init()
358 for ( i = 0; i < MAX_NET_STATS; i++ ) {
359 Psnet_stats[i].in_use = 0;
360 Psnet_stats[i].total_read = 0;
361 Psnet_stats[i].total_written = 0;
362 Psnet_socket_addr[i].socket = INVALID_SOCKET;
369 // function called from high level FreeSpace code to determine the status of the networking
370 // code returns one of a handful of macros
371 int psnet_get_network_status()
373 // first case is when "none" is selected
374 if ( Psnet_connection == NETWORK_CONNECTION_NONE ) {
375 return NETWORK_ERROR_NO_TYPE;
378 // first, check the connection status of the network
379 if ( Network_status == NETWORK_STATUS_NO_WINSOCK )
380 return NETWORK_ERROR_NO_WINSOCK;
382 if ( Network_status == NETWORK_STATUS_NO_PROTOCOL )
383 return NETWORK_ERROR_NO_PROTOCOL;
385 // network is running -- be sure that the RAS people know to connect if they currently cannot.
387 if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
388 // if on a dialup connection, be sure that RAS is active.
389 if ( !Ras_connected ) {
390 return NETWORK_ERROR_CONNECT_TO_ISP;
392 } else if ( Psnet_connection == NETWORK_CONNECTION_LAN ) {
393 // if on a LAN, and they have a dialup connection active, return error to indicate that they need
394 // to pick the right connection type
395 if ( Ras_connected ) {
396 return NETWORK_ERROR_LAN_AND_RAS;
399 return NETWORK_ERROR_NONE;
403 DWORD (__stdcall *pRasEnumConnections)(LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections) = NULL;
404 DWORD (__stdcall *pRasGetConnectStatus)(HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) = NULL;
405 DWORD (__stdcall *pRasGetProjectionInfo)(HRASCONN hrasconn, RASPROJECTION rasprojection, LPVOID lpprojection, LPDWORD lpcb ) = NULL;
408 // functions to get the status of a RAS connection
409 void psnet_ras_status()
413 unsigned long size, num_connections, i;
414 RASCONN rasbuffer[25];
415 HINSTANCE ras_handle;
419 // first, call a LoadLibrary to load the RAS api
420 ras_handle = LoadLibrary( (LPCWSTR)"rasapi32.dll" );
421 if ( ras_handle == NULL ) {
425 pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, NOX("RasEnumConnectionsA"));
426 if (!pRasEnumConnections) {
427 FreeLibrary( ras_handle );
430 pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, NOX("RasGetConnectStatusA"));
431 if (!pRasGetConnectStatus) {
432 FreeLibrary( ras_handle );
435 pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, NOX("RasGetProjectionInfoA"));
436 if (!pRasGetProjectionInfo) {
437 FreeLibrary( ras_handle );
441 size = sizeof(rasbuffer);
442 rasbuffer[0].dwSize = sizeof(RASCONN);
444 rval = pRasEnumConnections( rasbuffer, &size, &num_connections );
446 FreeLibrary( ras_handle );
450 // JAS: My computer gets to this point, but I have no RAS connections,
452 if ( num_connections < 1 ) {
453 nprintf(("Network", "Found no connections\n" ));
454 FreeLibrary( ras_handle );
458 nprintf(("Network", "Found %d connections\n", num_connections));
460 for (i = 0; i < num_connections; i++ ) {
461 RASCONNSTATUS status;
465 nprintf(("Network", "Connection %d:\n", i));
466 nprintf(("Network", "Entry Name: %s\n", rasbuffer[i].szEntryName));
467 nprintf(("Network", "Device Type: %s\n", rasbuffer[i].szDeviceType));
468 nprintf(("Network", "Device Name: %s\n", rasbuffer[i].szDeviceName));
470 // get the connection status
471 status.dwSize = sizeof(RASCONNSTATUS);
472 rval = pRasGetConnectStatus(rasbuffer[i].hrasconn, &status);
474 FreeLibrary( ras_handle );
478 nprintf(("Network", "\tStatus: %s\n", (status.rasconnstate==RASCS_Connected)?"Connected":"Not Connected"));
480 // get the projection informatiom
481 size = sizeof(projection);
482 projection.dwSize = size;
483 rval = pRasGetProjectionInfo(rasbuffer[i].hrasconn, RASP_PppIp, &projection, &size );
485 FreeLibrary( ras_handle );
489 nprintf(("Network", "\tIP Address: %s\n", projection.szIpAddress));
494 FreeLibrary( ras_handle );
498 // -------------------------------------------------------------------------------------------------
499 // netmisc_calc_checksum() calculates the checksum of a block of memory.
502 ushort psnet_calc_checksum( void * vptr, int len )
504 ubyte * ptr = (ubyte *)vptr;
505 unsigned int sum1,sum2;
511 if (sum1 >= 255 ) sum1 -= 255;
516 return (unsigned short)((sum1<<8)+ sum2);
519 // -------------------------------------------------------------------------------------------------
520 // psnet_set_socket_mode()
524 int psnet_set_socket_mode(SOCKET sock_id, int opt, int toggle)
526 return (setsockopt(sock_id, SOL_SOCKET, opt, (char *)&toggle, sizeof(toggle)));
530 // -------------------------------------------------------------------------------------------------
531 // sock_get_ip() returns the IP address of this computer.
537 char LclHost[MAXHOSTNAME];
538 struct hostent *Hostent;
539 struct sockaddr_in LclAddr;
540 struct sockaddr_in RmtAddr;
544 // Init local address to zero
545 LclAddr.sin_addr.s_addr = INADDR_ANY;
547 // Get the local host name
548 nRet = gethostname(LclHost, MAXHOSTNAME );
549 if (nRet != SOCKET_ERROR ) {
550 // Resolve host name for local address
551 Hostent = gethostbyname((char *)LclHost);
553 LclAddr.sin_addr.s_addr = ((in_addr *)(Hostent->h_addr))->s_addr;
556 return LclAddr.sin_addr.s_addr;
562 // psnet_get_ip() attempts to get the local IP address of this machine
563 // returns 0 on failure, and 1 on success
564 int psnet_get_ip( SOCKET s )
572 struct sockaddr_in local_addr;
574 if ( Psnet_my_addr_valid ){
578 memset(&local_addr, 0, sizeof(struct sockaddr_in));
579 len = sizeof(struct sockaddr_in);
580 rval = getsockname(s, (struct sockaddr *)&local_addr, &len );
581 if ( rval == SOCKET_ERROR )
584 // now we should have an IP address of this machine.
585 memcpy(Psnet_my_addr.addr, &(local_addr.sin_addr), 4);
586 Psnet_my_addr.port = ntohs(local_addr.sin_port);
588 Psnet_my_addr_valid = 1;
592 // -------------------------------------------------------------------------------------------------
599 #ifndef PSNET_RELIABLE_OLD_SCHOOL
600 psnet_reliable_close();
603 if ( Network_status != NETWORK_STATUS_RUNNING )
607 WSACancelBlockingCall();
610 if ( TCP_listen_socket != (SOCKET)INVALID_SOCKET ) {
611 shutdown( TCP_listen_socket, 1 );
612 closesocket( TCP_listen_socket );
615 if ( TCP_reliable_socket != (SOCKET)INVALID_SOCKET ) {
616 shutdown( TCP_reliable_socket, 1 );
617 closesocket( TCP_reliable_socket );
620 if ( TCP_socket != (SOCKET)INVALID_SOCKET ) {
621 shutdown( TCP_socket, 1 );
622 closesocket( TCP_socket );
627 //Warning( LOCATION, "Error closing wsock!\n" );
631 Network_status = NETWORK_STATUS_NOT_INITIALIZED;
634 // function to initialize a reliable socket. All it does is call the socket() command.
635 // returns 1 on success, 0 on failure.
636 int psnet_init_stream( SOCKET *s, int type )
640 SDL_assert(type == NET_TCP);
642 sock = socket(AF_INET,SOCK_STREAM,0);
643 if ( sock == (SOCKET)INVALID_SOCKET )
651 // called by psnet_init to initialize the listen socket used by a host/server
652 int psnet_init_reliable(ushort port, int should_listen, int type)
654 SOCKET sock = 0; // JAS: Get rid of optimized warning
655 struct sockaddr_in sockaddr; // UDP/TCP socket structure
657 // set up the reliable TCP transport socket
658 if ( !psnet_init_stream(&sock, type) ) {
659 nprintf(("Network", "Unable to initialize reliable socket on port %d (%d)!\n" , port, WSAGetLastError() ));
660 return INVALID_SOCKET;
663 // bind the socket to the port
664 SDL_assert(type == NET_TCP);
666 memset( &sockaddr, 0, sizeof(struct sockaddr_in) );
667 sockaddr.sin_family = AF_INET;
668 sockaddr.sin_addr.s_addr = INADDR_ANY; //fill in with our IP
669 sockaddr.sin_port = htons( port );
670 if ( bind(sock, (struct sockaddr*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
671 nprintf(("Network", "Unable to bind reliable socket on port %d (%d)!\n" , port, WSAGetLastError() ));
672 return INVALID_SOCKET;
676 // set up the listen on the Reliable_socket port
677 if ( should_listen && listen(sock, 5) ) {
678 nprintf(("Network", "Unable to listen on Listen Socket (%d)!\n" , WSAGetLastError() ));
679 return INVALID_SOCKET;
682 // make any reliable sockets which we create that aren't listening non-blocking sockets
683 if ( !should_listen ) {
688 error = ioctlsocket( sock, FIONBIO, &arg );
689 if ( error == SOCKET_ERROR ) {
690 nprintf(("Network", "Unable to make reliable socket non-blocking -- %d", WSAGetLastError() ));
691 return INVALID_SOCKET;
694 // set the reuse option
695 if ( psnet_set_socket_mode(sock, SO_REUSEADDR, 1) == SOCKET_ERROR ) {
696 error = WSAGetLastError();
697 nprintf(("Network", "Error setting socket to reuse address -- %d\n", error));
705 void psnet_socket_options( SOCKET sock )
708 int ret, cursize, bufsize, trysize;
712 socklen_t cursizesize;
715 // Set the mode of the socket to allow broadcasting. We need to be able to broadcast
716 // when a game is searched for in IPX mode.
718 if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast) )){
724 // try and increase the size of my receive buffer
725 bufsize = MAX_RECEIVE_BUFSIZE;
727 // set the current size of the receive buffer
728 cursizesize = sizeof(int);
729 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&cursize, &cursizesize);
730 for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
731 ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&trysize, sizeof(trysize));
732 if ( ret == SOCKET_ERROR ) {
735 wserr = WSAGetLastError();
736 if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
741 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&cursize, &cursizesize);
742 nprintf(("Network", "Receive buffer set to %d\n", cursize));
744 // set the current size of the send buffer
745 cursizesize = sizeof(int);
746 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&cursize, &cursizesize);
747 for ( trysize = bufsize; trysize >= cursize; trysize >>= 1 ) {
748 ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&trysize, sizeof(trysize));
749 if ( ret == SOCKET_ERROR ) {
752 wserr = WSAGetLastError();
753 if ( (wserr == WSAENOPROTOOPT) || (wserr == WSAEINVAL) )
758 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&cursize, &cursizesize);
759 nprintf(("Network", "Send buffer set to %d\n", cursize));
763 // psnet_init called at game startup time and initializes all sockets that the game might use (i.e. for both
765 void psnet_init( int protocol, int port_num )
767 const char *internet_connection;
772 // UDP/TCP socket structure
773 struct sockaddr_in sockaddr;
777 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
781 // GAME PORT INITIALIZATION STUFF
782 if ( Network_status == NETWORK_STATUS_RUNNING )
785 // 'lan' should be a safe default in 2015
786 internet_connection = os_config_read_string("Network", "NetworkConnection", "LAN");
788 if ( !SDL_strcasecmp(internet_connection, NOX("dialup")) ) {
789 ml_string("psnet_init() detected dialup connection");
791 Psnet_connection = NETWORK_CONNECTION_DIALUP;
792 } else if ( !SDL_strcasecmp(internet_connection, NOX("lan")) ) {
793 ml_string("psnet_init() detected lan connection");
795 Psnet_connection = NETWORK_CONNECTION_LAN;
797 ml_string("psnet_init() detected no connection");
799 Psnet_connection = NETWORK_CONNECTION_NONE;
802 Network_status = NETWORK_STATUS_NO_WINSOCK;
805 if (WSAStartup(0x101, &wsa_data )){
810 // get the port for running this game on. Be careful that it cannot be out of bounds
811 Psnet_default_port = DEFAULT_GAME_PORT;
812 if ( (port_num > 1023) && (port_num < USHRT_MAX) ) {
813 Psnet_default_port = (ushort)port_num;
816 #ifndef PSNET_RELIABLE_OLD_SCHOOL
817 if(!psnet_reliable_init()){
818 nprintf(("Network","PSNET RELIABLE : init failed - no networking available!\n"));
823 // initialize TCP now
824 TCP_socket = INVALID_SOCKET;
825 TCP_reliable_socket = INVALID_SOCKET;
826 TCP_listen_socket = INVALID_SOCKET;
828 Network_status = NETWORK_STATUS_NO_PROTOCOL;
829 TCP_socket = socket( AF_INET, SOCK_DGRAM, 0 );
830 if ( TCP_socket == (SOCKET)INVALID_SOCKET ) {
831 Tcp_failure_code = WSAGetLastError();
832 nprintf(("Network", "Error on TCP startup %d\n", Tcp_failure_code));
837 memset(&sockaddr,0,sizeof(struct sockaddr_in));
838 sockaddr.sin_family = AF_INET;
840 sockaddr.sin_addr.s_addr = INADDR_ANY; //fill in with our IP
842 sockaddr.sin_port = htons( Psnet_default_port );
843 if ( bind(TCP_socket, (struct sockaddr*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
844 Tcp_failure_code = WSAGetLastError();
845 nprintf(( "Network", "Couldn't bind TCP socket (%d)! Invalidating TCP\n", Tcp_failure_code ));
849 #ifdef PSNET_RELIABLE_OLD_SCHOOL
850 // set up reliable socket (using SPX).
851 TCP_reliable_socket = psnet_init_reliable( 0, 0, NET_TCP );
852 if ( TCP_reliable_socket == (SOCKET)INVALID_SOCKET ) {
853 Tcp_failure_code = WSAGetLastError();
854 nprintf(( "Network", "Couldn't initialize TCP reliable socket (OLD SCHOOL) (%d)! Invalidating TCP\n", Tcp_failure_code ));
858 TCP_listen_socket = psnet_init_reliable( (u_short)(Psnet_default_port-1), 1, NET_TCP );
859 if ( TCP_listen_socket == (SOCKET)INVALID_SOCKET ) {
860 Tcp_failure_code = WSAGetLastError();
861 nprintf(( "Network", "Couldn't initialize TCP listen socket (OLD SCHOOL) (%d)! Invalidating TCP\n", Tcp_failure_code ));
868 psnet_socket_options( TCP_socket );
869 Tcp_can_broadcast = Can_broadcast;
872 // fire up a second UDP socket for "reliable" transport
873 #ifndef PSNET_RELIABLE_OLD_SCHOOL
874 TCP_reliable_socket = socket( AF_INET, SOCK_DGRAM, 0 );
875 if ( TCP_reliable_socket != INVALID_SOCKET ) {
877 memset(&sockaddr,0,sizeof(struct sockaddr_in));
878 sockaddr.sin_family = AF_INET;
880 sockaddr.sin_addr.s_addr = INADDR_ANY; //fill in with our IP
881 //unsigned long my_ip = sock_get_ip();
882 //memcpy(&sockaddr.sin_addr.s_addr,&my_ip,sizeof(uint));
884 sockaddr.sin_port = htons( (ushort)(port+1) );
885 if ( bind(TCP_reliable_socket, (struct sockaddr*)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR) {
886 nprintf(( "Network", "Couldn't bind TCP socket (%d)! Invalidating TCP\n", WSAGetLastError() ));
890 psnet_socket_options( TCP_reliable_socket );
897 Network_status = NETWORK_STATUS_RUNNING;
899 nprintf(("Network","TCP Initialized\n"));
901 // with TCP initialized, see if the RAS services are installed
905 psnet_frame_int = -1; // for counting bytes per frame
908 #ifdef PSNET_BUFFER_OLD_SCHOOL
912 // initialize the packet buffer stuff. We use an array (the packet_free_list) to determine
913 // which of the packet buffers we can use next.
915 for (i=0; i<MAX_PACKET_BUFFERS; i++ ) {
916 packet_buffers[i].sequence_number = -1;
917 packet_free_list[i] = (short)i;
919 Num_packet_buffers = 0;
920 Largest_packet_index = 0;
922 // initialize the new buffering system
927 #define MAX_TMPBUF_SIZE 1024
929 #ifdef PSNET_RELIABLE_OLD_SCHOOL
930 // function to shutdown and close the given socket. It takes a couple of things into consideration
931 // when closing, such as possibly reiniting reliable sockets if they are closed here.
932 void psnet_rel_close_socket( PSNET_SOCKET *p_sockp )
938 sockp = (SOCKET *)p_sockp;
940 if ( *sockp == (SOCKET)INVALID_SOCKET )
944 if ( *sockp == TCP_reliable_socket )
945 nprintf(("network", "Closing my relibale TCP socket\n"));
947 nprintf(("Network", "Closing client's reliable socket\n"));
950 // make the socket blocking
951 //unsigned long val = 0;
952 //rval = ioctlsocket(*sockp,FIONBIO,&val);
953 //if ( rval == SOCKET_ERROR ) {
954 // error = WSAGetLastError();
955 // nprintf(("Network", "Error %d when trying to make reliable socket blocking.\n", error));
958 // set the socket to linger with a timeout of 0
962 rval = setsockopt(*sockp,SOL_SOCKET,SO_LINGER,(char*)&l_val,sizeof(linger));
963 if ( rval == SOCKET_ERROR ) {
964 error = WSAGetLastError();
965 nprintf(("Network", "Error %d when trying to set linger value.\n", error));
968 // see if this socket is my Reliable_socket. If so, I will have to reinitialize it!
970 if ( *sockp == TCP_reliable_socket )
971 reinit_type = NET_TCP;
973 // if this is the server connection, mark it as done
974 if (*sockp == (SOCKET)Serverconn) {
975 Serverconn = 0xffffffff;
979 rval = shutdown( *sockp, 2); // shut the whole damn thing down.
980 if ( rval == SOCKET_ERROR ) {
981 error = WSAGetLastError();
982 nprintf(("Network", "Error %d on socket shutdown\n", error));
986 shutdown( *sockp, 1 );
988 while ( rval && (rval != SOCKET_ERROR) ) {
989 char tmp_buf[MAX_TMPBUF_SIZE];
991 rval = recv( *sockp, tmp_buf, MAX_TMPBUF_SIZE, 0 );
992 if ( rval == SOCKET_ERROR ) {
995 error = WSAGetLastError();
996 if ( NETCALL_WOULDBLOCK(error) )
1001 rval = closesocket( *sockp );
1002 if ( rval == SOCKET_ERROR ) {
1003 error = WSAGetLastError();
1004 nprintf(("Network", "Error %d on closing socket\n", error ));
1007 *sockp = INVALID_SOCKET;
1009 // see if we need to reinitialize
1010 if ( reinit_type != -1 ) {
1011 if ( reinit_type == NET_TCP){
1012 TCP_reliable_socket = psnet_init_reliable( 0, 0, NET_TCP);
1013 Reliable_socket = TCP_reliable_socket;
1018 // function to shutdown and close the given socket. It takes a couple of things into consideration
1019 // when closing, such as possibly reiniting reliable sockets if they are closed here.
1020 void psnet_close_socket( PSNET_SOCKET *p_sockp )
1024 // copy the address to be removed
1025 memcpy(&remove,&((net_addr_t*)(*p_sockp)),sizeof(net_addr_t));
1027 // remove it from the reliable address list
1028 psnet_reliable_notify_drop_addr(&remove);
1030 // invalidate the passed in "socket"
1035 // function to check the status of the reliable socket and try to re-initialize it if necessary.
1036 // win95 seems to have trouble doing a reinit of the socket immediately after close, so this
1037 // function exists to check the status, and reinitialize if we need to
1038 int psnet_rel_check()
1040 // if our Reliable_socket is valid, simply return true to indicate all is well.
1041 if ( Reliable_socket != (SOCKET)INVALID_SOCKET )
1044 // based on our protocol type, try to reinitialize the socket we need.
1045 SDL_assert(Socket_type == NET_TCP);
1047 TCP_reliable_socket = psnet_init_reliable( 0, 0, NET_TCP);
1048 Reliable_socket = TCP_reliable_socket;
1050 // return our status.
1051 if ( Reliable_socket == (SOCKET)INVALID_SOCKET )
1057 // this function is called from a high level at FreeSpace to set the protocol that the user wishes to use
1058 int psnet_use_protocol( int protocol )
1060 // zero out my address
1061 Psnet_my_addr_valid = 0;
1062 memset( &Psnet_my_addr, 0, sizeof(Psnet_my_addr) );
1064 // wait until we choose a protocol to determine if we can broadcast
1067 SDL_assert(protocol == NET_TCP);
1069 if ( Network_status != NETWORK_STATUS_RUNNING )
1072 // assign the TCP_* sockets to the socket values used elsewhere
1073 Unreliable_socket = TCP_socket;
1074 Reliable_socket = TCP_reliable_socket;
1075 Listen_socket = TCP_listen_socket;
1077 Can_broadcast = Tcp_can_broadcast;
1079 nprintf(("Network","Psnet : TCP broadcast\n"));
1082 nprintf(("Network","Psnet using - NET_TCP\n"));
1084 Psnet_my_addr.type = protocol;
1085 Socket_type = protocol;
1090 #define MAX_CONNECT_TRIES 10
1092 // attacmpt to connect() to the server's tcp socket. socket parameter is simply assigned to the
1093 // Reliable_socket socket created in psnet_init
1094 void psnet_rel_connect_to_server( PSNET_SOCKET *psocket, net_addr_t *server_addr)
1096 struct sockaddr_in sockaddr; // UDP/TCP socket structure
1097 struct sockaddr *addr; // pointer to struct sockaddr to make coding easier
1099 ubyte iaddr[IP_ADDRESS_LENGTH];
1101 int name_length, val;
1103 memset(iaddr, 0x00, IP_ADDRESS_LENGTH);
1104 memcpy(iaddr, server_addr->addr, IP_ADDRESS_LENGTH);
1105 port = (u_short)(server_addr->port - 1);
1107 socket = (SOCKET *)psocket;
1109 SDL_assert(Socket_type == NET_TCP);
1111 sockaddr.sin_family = AF_INET;
1112 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1113 sockaddr.sin_port = htons(port);
1114 addr = (struct sockaddr *)&sockaddr;
1115 name_length = sizeof(sockaddr);
1118 ml_string(NOX("Attempting to perform reliable TCP connect to server"));
1120 // connect this guys Reliable_socket to the socket parameter passed in
1121 *socket = INVALID_SOCKET;
1122 val = connect(Reliable_socket, addr, name_length);
1124 // I suppose that we could have a valid socket right away
1125 if ( val != SOCKET_ERROR ) {
1126 *socket = Reliable_socket;
1130 error = WSAGetLastError();
1131 if ( NETCALL_WOULDBLOCK(error) ) { // use select to find out when socket is writeable
1132 int is_set, num_tries;
1134 struct timeval timeout;
1136 // call select -- and return if an error leaving our connection to the client invalid
1140 FD_SET( Reliable_socket, &wfds );
1142 timeout.tv_usec = 500000; //500000 micro seconds is 1/2 second
1144 is_set = select( Reliable_socket+1, NULL, &wfds, NULL, &timeout);
1146 // check for error on select first
1147 if ( is_set == SOCKET_ERROR ) {
1148 nprintf(("Network", "Error on select for connect %d\n", WSAGetLastError() ));
1150 } else if (is_set) { // if set, then we have connection, move forward
1153 SDL_Delay(10); // sleep for 10 ms and try again
1156 } while ( num_tries < MAX_CONNECT_TRIES );
1158 if ( num_tries == MAX_CONNECT_TRIES )
1161 *socket = Reliable_socket;
1164 nprintf(("Network", "Connecting with server failed %d\n", error ));
1165 *socket = INVALID_SOCKET;
1169 // if we have a connection, get my address from getsockname
1170 if ( *socket == Reliable_socket ) {
1171 if ( !psnet_get_ip(Reliable_socket) ) {
1172 *socket = INVALID_SOCKET;
1176 Serverconn = *socket;
1181 void psnet_calc_bytes_per_frame()
1186 // -------------------------------------------------------------------------------------------------
1191 int psnet_same_no_port( net_addr_t * a1, net_addr_t * a2 )
1193 if ( !memcmp(a1->addr, a2->addr, IP_ADDRESS_LENGTH) )
1198 int psnet_same( net_addr_t * a1, net_addr_t * a2 )
1200 return psnet_same_no_port( a1, a2 );
1202 if ( !memcmp(a1->addr, a2->addr, 6) && a1->port == a2->port)
1208 // -------------------------------------------------------------------------------------------------
1213 char* psnet_addr_to_string( char * text, const int max_textlen, net_addr_t * address )
1216 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1217 SDL_strlcpy( text, XSTR("[no networking]",910), max_textlen );
1223 SDL_assert(address->type == NET_TCP);
1225 switch ( address->type ) {
1227 memcpy(&temp_addr.s_addr, address->addr, 4);
1228 SDL_strlcpy( text, inet_ntoa(temp_addr), max_textlen );
1241 // -------------------------------------------------------------------------------------------------
1242 // psnet_undescribe()
1246 void psnet_string_to_addr( net_addr_t * address, char * text, const int max_textlen )
1249 char str[255], *c, *port;
1252 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1253 SDL_strlcpy( text, XSTR("[no networking]",910), max_textlen );
1257 // copy the text string to local storage to look for ports
1258 SDL_assert( strlen(text) < 255 );
1259 SDL_strlcpy(str, text, SDL_arraysize(str));
1260 c = strrchr(str, ':');
1267 switch ( address->type ) {
1269 addr.s_addr = inet_addr(str);
1270 // if we get INADDR_NONE returns, then we need to try and resolve the host
1272 if ( addr.s_addr == INADDR_NONE ) {
1273 he = gethostbyname( str );
1274 // returns a non-null pointer if successful, so get the address
1276 addr.s_addr = ((in_addr *)(he->h_addr))->s_addr; // this is the address in network byte order
1278 addr.s_addr = INADDR_NONE;
1282 memset(address->addr, 0x00, IP_ADDRESS_LENGTH);
1283 memcpy(address->addr, &addr.s_addr, 4);
1285 address->port = (ushort)(atoi(port));
1296 // psnet_get_socket_data() will get data out of the socket and stuff it into the packet_buffers
1297 // The original psnet_get() now calls this function, then determines which of the packet buffers
1298 // to package up and use
1299 void psnet_get_socket_data(SOCKET socket, int flags = PSNET_FLAG_RAW)
1301 struct sockaddr_in ip_addr; // UDP/TCP socket structure
1310 net_addr_t from_addr;
1311 network_checksum_packet packet_read;
1312 network_checksum_packet packet_data;
1314 // clear the addresses to remove compiler warnings
1315 memset(&ip_addr, 0, sizeof(struct sockaddr_in));
1317 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1318 nprintf(("Network","Network ==> socket not inited in psnet_get\n"));
1323 #ifdef PSNET_BUFFER_OLD_SCHOOL
1325 // if there are no more packet buffers that we can use, then we must bail here before reading
1327 if ( Num_packet_buffers >= MAX_PACKET_BUFFERS ) {
1328 nprintf(("Network", "Packet buffer overrun in psnet_get()\n"));
1333 // check if there is any data on the socket to be read. The amount of data that can be
1334 // atomically read is stored in len.
1337 FD_SET( socket, &rfds );
1339 timeout.tv_usec = 0;
1341 if ( select( socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1342 nprintf(("Network", "Error %d doing a socket select on read\n", WSAGetLastError()));
1346 // if the read file descriptor is not set, then bail!
1347 if ( !FD_ISSET(socket, &rfds ) )
1350 // get data off the socket and process
1351 read_len = SOCKET_ERROR;
1352 switch ( Socket_type ) {
1354 from_len = sizeof(struct sockaddr_in);
1355 if(flags & PSNET_FLAG_RAW){
1356 read_len = recvfrom( socket, (char*)packet_read.data, MAX_PACKET_SIZE, 0, (struct sockaddr*)&ip_addr, &from_len );
1358 read_len = recvfrom( socket, (char *)&packet_read, sizeof(packet_data), 0, (struct sockaddr*)&ip_addr, &from_len );
1367 // set the from_addr for storage into the packet buffer structure
1368 from_addr.type = Socket_type;
1370 switch ( Socket_type ) {
1372 if(socket == Reliable_socket){
1373 from_addr.port = Psnet_default_port;
1375 from_addr.port = ntohs( ip_addr.sin_port );
1377 memset(from_addr.addr, 0x00, IP_ADDRESS_LENGTH);
1378 memcpy(from_addr.addr, &ip_addr.sin_addr.s_addr, 4);
1386 if ( read_len == SOCKET_ERROR ) {
1387 int x = WSAGetLastError();
1388 nprintf(("Network", "Read error on socket. Winsock error %d \n", x));
1392 #ifndef PSNET_RELIABLE_OLD_SCHOOL
1394 // now we check to see if this is a reliable packet, and act accordindly
1395 if(socket == Reliable_socket){
1396 // this function processes the incoming packet, and determines if the system should continue to process the data
1397 shave_size = psnet_reliable_should_process(&from_addr,packet_read.data,read_len);
1401 // copy in from data+2, so we skip the reliable data header
1402 memcpy(packet_data.data,packet_read.data + shave_size,read_len);
1404 // subtract out the size of the reliable header
1405 read_len -= shave_size;
1408 memcpy(packet_data.data,packet_read.data,read_len);
1411 memcpy(packet_data.data,packet_read.data,read_len);
1414 #ifdef PSNET_BUFFER_OLD_SCHOOL
1418 // if we had no error reading from the socket, then determine if we need to calculate a
1419 // checksum on the packet
1420 if ( !(flags & PSNET_FLAG_RAW) && (packet_data.flags & PSNET_FLAG_CHECKSUM) ) {
1423 // calculate the size of the data that is actual real data
1424 len = read_len - (sizeof(packet_data) - MAX_CHECKSUM_PACKET_SIZE);
1425 checksum = psnet_calc_checksum( packet_data.data, len );
1426 if ( checksum != packet_data.checksum ) {
1427 nprintf(("Network", "bad checksum on incoming packet -- discarding\n"));
1430 data = packet_data.data;
1431 packet_id = packet_data.sequence_number;
1433 network_naked_packet *packet;
1435 // just read in the raw socket data and length
1436 if(flags & PSNET_FLAG_RAW){
1437 data = packet_data.data;
1442 // we don't have a checksum packet. cast the data to the naked packet type and
1443 // copy it over to passed parameters
1444 packet = (network_naked_packet *)&packet_data;
1446 len = read_len - (sizeof(network_naked_packet) - MAX_PACKET_SIZE);
1447 data = packet->data;
1449 packet_id = packet->sequence_number;
1453 // look at the sequence number compared to what we last received
1454 if ( Last_packet_id > -1 ) {
1455 if ( packet_id != (Last_packet_id+1) ) {
1456 //if ( packet_id < Last_packet_id )
1457 // nprintf(("network", "packet %d came in delayed (last id was %d\n", packet_id, Last_packet_id));
1458 //else if ( packet_id > (Last_packet_id+1) )
1459 // nprintf(("Network", "missed %d packet(s). last id %d. This id %d\n", (packet_id - Last_packet_id), Last_packet_id, packet_id));
1462 Last_packet_id = packet_id;
1465 psnet_do_net_stats( &from_addr, read_len, 1 );
1466 psnet_bytes_read_frame += read_len;
1469 // put all of the data (length, who from, etc.) into the next available packet buffer
1470 // slot. We should be assured of a slot here because of the check at the beginning
1471 // of the while loop
1472 SDL_assert ( Num_packet_buffers < MAX_PACKET_BUFFERS );
1473 id = packet_free_list[ Num_packet_buffers++ ];
1474 if (id > Largest_packet_index ) Largest_packet_index = id;
1475 packet_buffers[id].len = len; // use the flags field of the packet structure to hold the data length
1476 packet_buffers[id].sequence_number = packet_id;
1477 packet_buffers[id].from_addr = from_addr;
1478 memcpy( packet_buffers[id].data, data, len );
1481 psnet_do_net_stats( &from_addr, read_len, 1 );
1482 psnet_bytes_read_frame += read_len;
1485 // buffer the packet
1486 psnet_buffer_packet(packet_data.data,read_len,&from_addr);
1491 // -------------------------------------------------------------------------------------------------
1496 int psnet_send( net_addr_t * who_to, void * data, int len, int flags, int reliable_socket )
1500 struct sockaddr_in sockaddr; // UDP/TCP socket structure
1502 ubyte iaddr[IP_ADDRESS_LENGTH], *send_data;
1505 struct timeval timeout;
1507 if(!reliable_socket){
1508 send_sock = Unreliable_socket;
1510 send_sock = Reliable_socket;
1513 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1514 nprintf(("Network","Network ==> Socket not inited in psnet_send\n"));
1518 if ( psnet_same( who_to, &Psnet_my_addr) ){
1522 memset(iaddr, 0x00, IP_ADDRESS_LENGTH);
1523 memcpy(iaddr, who_to->addr, IP_ADDRESS_LENGTH);
1525 if ( memcmp(iaddr, Null_address, IP_ADDRESS_LENGTH) == 0) {
1526 nprintf(("Network","Network ==> send to address is 0 in psnet_send\n"));
1530 if(send_sock == Unreliable_socket){
1531 port = who_to->port;
1532 } else if(send_sock == Reliable_socket){
1533 port = DEFAULT_GAME_PORT + 1;
1535 port = who_to->port;
1539 nprintf(("Network","Network ==> destination port %d invalid in psnet_send\n", port));
1543 #ifdef PSNET_BUFFER_OLD_SCHOOL
1544 network_checksum_packet Send_network_checksum_packet;
1545 network_naked_packet Send_network_naked_packet;
1547 // determine from the flags whether or not this packet should have a checksum.
1548 if ( flags & PSNET_FLAG_CHECKSUM ) {
1549 // can't send raw data with a checksum, dumbass!
1550 SDL_assert(!(flags & PSNET_FLAG_RAW));
1552 Send_network_checksum_packet.sequence_number = Next_packet_id++;
1553 Send_network_checksum_packet.flags = PSNET_FLAG_CHECKSUM;
1555 Send_network_checksum_packet.checksum = psnet_calc_checksum(data, len);
1556 memcpy( Send_network_checksum_packet.data, data, len );
1557 send_len = sizeof(Send_network_checksum_packet) - MAX_CHECKSUM_PACKET_SIZE + len;
1558 send_data = (ubyte *)&Send_network_checksum_packet;
1560 // send standard psnet stuff
1561 if(!(flags & PSNET_FLAG_RAW)){
1562 Send_network_naked_packet.sequence_number = Next_packet_id++;
1563 Send_network_naked_packet.flags = 0;
1565 memcpy(Send_network_naked_packet.data, data, len);
1566 send_len = sizeof(Send_network_naked_packet) - MAX_PACKET_SIZE + len; // gets us the real size of the structure
1567 send_data = (ubyte *)&Send_network_naked_packet;
1571 send_data = (ubyte*)data;
1576 send_data = (ubyte*)data;
1582 FD_SET( send_sock, &wfds );
1584 timeout.tv_usec = 0;
1586 if ( select( send_sock+1, NULL, &wfds, NULL, &timeout) == SOCKET_ERROR ) {
1587 nprintf(("Network", "Error on blocking select for write %d\n", WSAGetLastError() ));
1591 // if the write file descriptor is not set, then bail!
1592 if ( !FD_ISSET(send_sock, &wfds ) )
1596 switch ( who_to->type ) {
1599 sockaddr.sin_family = AF_INET;
1600 memcpy(&sockaddr.sin_addr.s_addr, iaddr, 4);
1601 sockaddr.sin_port = htons(port);
1603 ret = sendto( send_sock, (char *)send_data, send_len, 0, (struct sockaddr*)&sockaddr, sizeof(sockaddr) );
1607 SDL_assert(0); // unknown protocol
1612 if ( ret != SOCKET_ERROR ) {
1614 psnet_bytes_written_frame += send_len;
1615 psnet_do_net_stats( who_to, send_len, 0 );
1619 //Warning( LOCATION, "Couldn't send data (0x%x)!\n", WSAGetLastError() );
1623 #ifdef PSNET_BUFFER_OLD_SCHOOL
1624 // routine to "free" a packet buffer
1625 void free_packet( int id )
1627 packet_buffers[id].sequence_number = -1;
1628 packet_free_list[ --Num_packet_buffers ] = (short)id;
1629 if ( Largest_packet_index == id)
1630 while ((--Largest_packet_index>0) && (packet_buffers[Largest_packet_index].sequence_number == -1 ));
1634 #ifdef PSNET_RELIABLE_OLD_SCHOOL
1635 // psnet_send_reliable sends the given data through the given reliable socket.
1637 #define MAX_RSEND_BUFFER 2048
1638 ubyte rsend_buffer[MAX_RSEND_BUFFER];
1640 int psnet_rel_send( PSNET_SOCKET psocket, ubyte *data, int length, int flags )
1643 int num_sent, total_sent, error, retries;
1645 unsigned short s_length;
1647 socket = (SOCKET)psocket;
1650 if ( Network_status != NETWORK_STATUS_RUNNING ) {
1651 nprintf(("Network","Network ==> Socket not inited in psnet_send\n"));
1655 if ( socket == (SOCKET)INVALID_SOCKET ) // might happen in race conditions -- should get cleaned up.
1658 SDL_assert( length < MAX_RSEND_BUFFER );
1660 // copy the length of the data into the beginning of the buffer. then put the data into the buffer
1661 // after the length value
1662 SDL_assert( length > 0 );
1663 s_length = (ushort)length;
1664 memcpy( &rsend_buffer[0], &s_length, sizeof(s_length) );
1665 memcpy( &rsend_buffer[2], data, length );
1671 num_sent = send( socket, (char *)rsend_buffer, length+sizeof(s_length), 0 );
1672 if ( num_sent == SOCKET_ERROR ) {
1673 error = WSAGetLastError();
1674 if ( !NETCALL_WOULDBLOCK(error) || (retries > MAX_SEND_RETRIES) ) { // means that we would block on send -- not really an error
1676 // if error is would block, then set error to aborted connection
1677 if ( NETCALL_WOULDBLOCK(error) )
1678 error = WSAECONNABORTED;
1680 multi_eval_socket_error(socket, error);
1683 retries++; // keep a try count
1686 send_data += num_sent;
1687 total_sent += num_sent;
1689 } while ( length > 0 );
1692 psnet_bytes_written_frame += total_sent;
1695 //index = psnet_find_stats_loc( who_to );
1696 //if ( index != -1 )
1697 // Psnet_stats[index].total_written += send_len;
1702 // get data off the reliable socket
1703 int psnet_rel_get( PSNET_SOCKET psocket, ubyte *buffer, int max_len, int flags)
1705 int from_len, total_read, error;
1708 struct timeval timeout;
1710 ubyte rread_buffer[2];
1712 socket = (SOCKET)psocket;
1714 // see if there is data to be read
1716 FD_SET( socket, &rfds );
1718 timeout.tv_usec = 0;
1720 if ( select( socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1721 nprintf(("Network", "Error on select for read reliable: %d\n", WSAGetLastError() ));
1725 // if no data, then we can leave.
1726 if ( !FD_ISSET(socket, &rfds ) )
1729 // we know we have data to read. We must read the two byte length of the packet first
1733 from_len = recv(socket, (char *)(&rread_buffer[total_read]), read_len - total_read, 0);
1735 // from_len will be 0 when back end gracefully closes connection. We will assume that since
1736 // the close is graceful, we will info from him telling us he's left. So we'll ignore
1737 // this condition here.
1738 if ( from_len == 0 ) {
1739 nprintf(("Network", "Dumping player because recv returned 0\n"));
1740 multi_eval_socket_error( socket, WSAECONNRESET ); // this error drops player from game.
1744 // on a socket error, we need to check for WSAEWOULDBLOCK meaning that there is no more
1746 else if ( from_len == SOCKET_ERROR ) {
1747 error = WSAGetLastError();
1748 if ( !NETCALL_WOULDBLOCK(error) )
1749 multi_eval_socket_error( socket, error );
1750 return 0; // get it next frame?
1753 total_read += from_len;
1754 } while ( total_read < read_len );
1758 memcpy(&read_len, &rread_buffer[0], 2);
1759 SDL_assert( (read_len > 0) && (read_len < max_len) );
1760 if ( read_len == 0 )
1764 from_len = recv(socket, (char *)(buffer + total_read), read_len - total_read, 0);
1766 // from_len will be 0 when back end gracefully closes connection. We will assume that since
1767 // the close is graceful, we will info from him telling us he's left. So we'll ignore
1768 // this condition here.
1769 if ( from_len == 0 ) {
1770 nprintf(("Network", "Dumping player because recv returned 0\n"));
1771 multi_eval_socket_error( socket, WSAECONNRESET ); // this error drops player from game.
1775 // on a socket error, we need to check for WSAEWOULDBLOCK meaning that there is no more
1777 else if ( from_len == SOCKET_ERROR ) {
1778 error = WSAGetLastError();
1779 if ( !NETCALL_WOULDBLOCK(error) ) {
1780 multi_eval_socket_error( socket, error );
1786 total_read += from_len;
1787 } while ( total_read < read_len );
1792 // psnet_send_reliable sends the given data through the given reliable socket.
1793 int psnet_send_reliable( PSNET_SOCKET psocket, ubyte *data, int length, int flags )
1795 // don't do anything if the socket is null
1796 if(psocket == NULL){
1800 // send a reliable data packet
1801 return psnet_reliable_send(data,length,(net_addr_t*)psocket);
1804 int psnet_get_reliable( PSNET_SOCKET psocket, ubyte *buffer, int max_len, int flags)
1807 int best, best_id, i, n, size;
1809 // call the routine to read data out of the socket (which stuffs it into the packet buffers)
1810 psnet_get_socket_data(Reliable_socket,flags);
1812 #ifdef PSNET_BUFFER_OLD_SCHOOL
1813 // now determine which (if any) of the packet buffers we should look at!
1818 for (i=0; i <= Largest_packet_index; i++ ) {
1819 if ( packet_buffers[i].sequence_number > -1 ) {
1821 if ( best == -1 || (packet_buffers[i].sequence_number < best) ) {
1822 best = packet_buffers[i].sequence_number;
1828 //mprintf( (0, "Best id = %d, pn = %d, last_ecb = %x, len=%x, ne = %d\n", best_id, best, last_ecb, lastlen, neterrors ));
1829 //mprintf( (1, "<%d> ", neterrors ));
1831 if ( best_id < 0 ) return 0;
1833 size = packet_buffers[best_id].len;
1834 memcpy( buffer, packet_buffers[best_id].data, size );
1835 memcpy( psocket, &packet_buffers[best_id].from_addr, sizeof(net_addr_t) );
1836 free_packet(best_id);
1845 // function which checks the Listen_socket for possibly incoming requests to be connected.
1846 // returns 0 on error or nothing waiting. 1 if we should try to accept
1847 int psnet_rel_check_for_listen(net_addr_t *from_addr)
1851 SOCKET sock; // when trying to accept, this is new socket
1852 struct sockaddr_in ip_addr; // UDP/TCP socket structure
1862 FD_SET( Listen_socket, &rfds );
1864 timeout.tv_usec = 0;
1866 if ( select(Listen_socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1867 nprintf(("Network", "Error %d doing select on listen socket\n", WSAGetLastError() ));
1871 // check to see if Listen_socket has something -- if not, return
1872 if ( !FD_ISSET(Listen_socket, &rfds) )
1873 return INVALID_SOCKET;
1875 sock = INVALID_SOCKET;
1876 switch ( Socket_type ) {
1878 from_len = sizeof(struct sockaddr_in);
1879 sock = accept( Listen_socket, (struct sockaddr*)&ip_addr, &from_len );
1880 from_addr->port = ntohs( ip_addr.sin_port );
1881 memset(from_addr->addr, 0x00, IP_ADDRESS_LENGTH);
1882 memcpy(from_addr->addr, &ip_addr.sin_addr.s_addr, 4);
1883 nprintf(("Network","Accepted TCP connected!!\n"));
1891 if ( !psnet_get_ip(sock) ) {
1892 return INVALID_SOCKET;
1895 // make the new socket non-blocking
1896 if(sock != (SOCKET)INVALID_SOCKET){
1898 error = ioctlsocket( sock, FIONBIO, &arg );
1899 if ( error == SOCKET_ERROR ) {
1900 nprintf(("Network", "Unable to make accepted socket non-blocking -- %d", WSAGetLastError() ));
1901 return INVALID_SOCKET;
1909 int psnet_rel_get_status(PSNET_SOCKET psocket)
1913 int error_code_size = sizeof(error_code);
1915 socklen_t error_code_size = sizeof(error_code);
1919 socket = (SOCKET)psocket;
1921 if (socket == (SOCKET)INVALID_SOCKET) {
1925 if ( getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &error_code_size) ) {
1929 if ( !error_code ) {
1930 return RNF_CONNECTED;
1933 if ( NETCALL_WOULDBLOCK(error_code) ) {
1934 return RNF_CONNECTING;
1937 return RNF_DISCONNECTED;
1940 // psnet_get() will call the above function to read data out of the socket. It will then determine
1941 // which of the buffers we should use and pass to the routine which called us
1942 int psnet_get( void * data, net_addr_t* from_addr, int flags )
1944 // USE THIS CODE TO TEST NON-BUFFERED SOCKET READS. OUT-OF-ORDER PACKETS DROP TO NEARLY 0
1949 int read_len,from_len;
1950 struct sockaddr_in ip_addr;
1952 FD_SET( Unreliable_socket, &rfds );
1954 timeout.tv_usec = 0;
1956 if ( select( Unreliable_socket+1, &rfds, NULL, NULL, &timeout) == SOCKET_ERROR ) {
1957 nprintf(("Network", "Error %d doing a socket select on read\n", WSAGetLastError()));
1961 // if the read file descriptor is not set, then bail!
1962 if ( !FD_ISSET(Unreliable_socket, &rfds ) )
1965 // get data off the socket and process
1966 read_len = SOCKET_ERROR;
1967 from_len = sizeof(struct sockaddr_in);
1968 read_len = recvfrom( Unreliable_socket, (char*)data, MAX_PACKET_SIZE, 0, (struct sockaddr*)&ip_addr, &from_len );
1969 from_addr->port = ntohs( ip_addr.sin_port );
1970 memset(from_addr->addr, 0x00, 6);
1971 memcpy(from_addr->addr, &ip_addr.sin_addr.S_un.S_addr, 4);
1975 // call the routine to read data out of the socket (which stuffs it into the packet buffers)
1976 psnet_get_socket_data(Unreliable_socket,flags);
1978 #ifdef PSNET_BUFFER_OLD_SCHOOL
1979 int best, best_id, i, n, size;
1981 // now determine which (if any) of the packet buffers we should look at!
1986 for (i=0; i <= Largest_packet_index; i++ ) {
1987 if ( packet_buffers[i].sequence_number > -1 ) {
1989 if ( best == -1 || (packet_buffers[i].sequence_number < best) ) {
1990 best = packet_buffers[i].sequence_number;
1996 //mprintf( (0, "Best id = %d, pn = %d, last_ecb = %x, len=%x, ne = %d\n", best_id, best, last_ecb, lastlen, neterrors ));
1997 //mprintf( (1, "<%d> ", neterrors ));
1999 if ( best_id < 0 ) return 0;
2001 size = packet_buffers[best_id].len;
2002 memcpy( data, packet_buffers[best_id].data, size );
2003 memcpy( from_addr, &packet_buffers[best_id].from_addr, sizeof(net_addr_t) );
2004 free_packet(best_id);
2010 // try and get a free buffer and return its size
2011 if(psnet_buffer_get_next((ubyte*)data,&buffer_size,from_addr)){
2022 // -------------------------------------------------------------------------------------------------
2023 // psnet_broadcast()
2027 int psnet_broadcast( net_addr_t * who_to, void * data, int len, int flags )
2029 if ( Network_status != NETWORK_STATUS_RUNNING ) {
2030 nprintf(("Network","Network ==> Socket not inited in psnet_broadcast\n"));
2034 if ( !Can_broadcast ) {
2035 nprintf(("Network", "Cannot broadcast -- returning without doing anything\n"));
2039 ubyte broadcast[IP_ADDRESS_LENGTH] = {0xff, 0xff, 0xff, 0xff};
2041 // broadcasting works on a local subnet which is all we really want to do for now anyway.
2042 // we might keep this in as an option for freespace later.
2043 switch ( who_to->type ) {
2046 memcpy(who_to->addr, broadcast, IP_ADDRESS_LENGTH);
2047 psnet_send(who_to, data, len, flags);
2055 // called to clear out the socket of any remaining data
2059 ubyte data[MAX_PACKET_SIZE];
2060 net_addr_t from_addr;
2062 while ( psnet_get( data, &from_addr ) > 0 ) ;
2068 // function to keep track of bytes read/written on average during the frame
2069 void psnet_calc_socket_stats()
2071 if ( psnet_frame_int == -1 ) {
2073 for ( i = 0; i < PSNET_FRAME_FILTER; i++ ) {
2074 psnet_read_sizes[i] = 0;
2075 psnet_write_sizes[i] = 0;
2077 psnet_read_total = 0;
2078 psnet_write_total = 0;
2079 psnet_frame_int = 0;
2081 psnet_read_total -= psnet_read_sizes[psnet_frame_int];
2082 psnet_write_total -= psnet_write_sizes[psnet_frame_int];
2084 psnet_read_total += psnet_bytes_read_frame;
2085 psnet_write_total += psnet_bytes_written_frame;
2087 psnet_read_sizes[psnet_frame_int] = psnet_bytes_read_frame;
2088 psnet_write_sizes[psnet_frame_int] = psnet_bytes_written_frame;
2090 psnet_frame_int = (psnet_frame_int + 1 ) % PSNET_FRAME_FILTER;
2092 if ( psnet_frame_count > 0 ) {
2093 if ( psnet_frame_count >= PSNET_FRAME_FILTER )
2094 Psnet_bytes_read = psnet_read_total / PSNET_FRAME_FILTER;
2096 Psnet_bytes_read = psnet_read_total / psnet_frame_count;
2098 if ( psnet_frame_count >= PSNET_FRAME_FILTER )
2099 Psnet_bytes_written = psnet_write_total / PSNET_FRAME_FILTER;
2101 Psnet_bytes_written = psnet_write_total / psnet_frame_count;
2104 psnet_frame_count++;
2105 psnet_bytes_read_frame = 0;
2106 psnet_bytes_written_frame = 0;
2110 int psnet_is_valid_numeric_ip(char *ip)
2114 int val1,val2,val3,val4;
2116 // get the first ip value
2117 SDL_strlcpy(copy, ip, SDL_arraysize(copy));
2118 token = strtok(copy,".");
2122 // get the value of the token
2124 if((val1 < 0) || (val1 > 255)){
2130 token = strtok(NULL,".");
2134 // get the value of the token
2136 if((val2 < 0) || (val2 > 255)){
2142 token = strtok(NULL,".");
2146 // get the value of the token
2148 if((val3 < 0) || (val3 > 255)){
2154 token = strtok(NULL,"");
2158 // get the value of the token
2160 if((val4 < 0) || (val4 > 255)){
2165 // make sure he hasn't entered all 0's
2166 if((val1 == 0) && (val2 == 0) && (val3 == 0) && (val4 == 0)){
2175 // returns true or false if the given string is a valid ip string or not.
2176 // allow port allows us to append the port number on the end of the ip string with
2178 // so we must be sure to remove the port number
2179 int psnet_is_valid_ip_string( char *ip_string, int allow_port )
2182 struct hostent *host_ent;
2185 // our addresses may have ports, so make local copy and remove port number
2186 SDL_assert( strlen(ip_string) < 255 );
2187 SDL_strlcpy(str, ip_string, SDL_arraysize(str));
2188 c = strrchr(str, ':');
2193 addr.s_addr = inet_addr(ip_string);
2194 if ( addr.s_addr != INADDR_NONE ){
2195 // make sure the ip string is a valid format string
2196 if(psnet_is_valid_numeric_ip(ip_string)){
2201 // try name resolution
2202 host_ent = gethostbyname( ip_string );
2207 // valid host entry so return 1;
2212 // ------------------------------------------------------------------------------------------------------
2213 // PACKET BUFFERING FUNCTIONS
2216 #ifndef PSNET_BUFFER_OLD_SCHOOL
2218 // a sequence number of -1 will indicate that this packet is not valid
2219 static network_packet_buffer Psnet_buffers[MAX_PACKET_BUFFERS];
2220 static int Psnet_seq_number = 0;
2221 static int Psnet_lowest_id = 0;
2222 static int Psnet_highest_id = 0;
2224 // initialize the buffering system
2225 void psnet_buffer_init()
2229 // blast the buffer clean
2230 memset(Psnet_buffers,0,sizeof(network_packet_buffer) * MAX_PACKET_BUFFERS);
2232 // set all buffer sequence #'s to -1
2233 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2234 Psnet_buffers[idx].sequence_number = -1;
2237 // initialize the sequence #
2238 Psnet_seq_number = 0;
2239 Psnet_lowest_id = -1;
2240 Psnet_highest_id = -1;
2243 // buffer a packet (maintain order!)
2244 void psnet_buffer_packet(ubyte *data, int length, net_addr_t *from)
2249 // find the first empty packet
2250 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2251 if(Psnet_buffers[idx].sequence_number == -1){
2257 // if we didn't find the buffer, report an overrun
2259 nprintf(("Network","WARNING - Buffer overrun in psnet\n"));
2262 memcpy(Psnet_buffers[idx].data,data,length);
2263 Psnet_buffers[idx].len = length;
2264 memcpy(&Psnet_buffers[idx].from_addr,from,sizeof(net_addr_t));
2265 Psnet_buffers[idx].sequence_number = Psnet_seq_number;
2267 // keep track of the highest id#
2268 Psnet_highest_id = Psnet_seq_number++;
2270 // set the lowest id# for the first time
2271 if(Psnet_lowest_id == -1){
2272 Psnet_lowest_id = Psnet_highest_id;
2277 // get the index of the next packet in order!
2278 int psnet_buffer_get_next(ubyte *data, int *length, net_addr_t *from)
2283 // if there are no buffers, do nothing
2284 if((Psnet_lowest_id == -1) || (Psnet_lowest_id > Psnet_highest_id)){
2288 // search until we find the lowest packet index id#
2289 for(idx=0;idx<MAX_PACKET_BUFFERS;idx++){
2290 // if we found the buffer
2291 if(Psnet_buffers[idx].sequence_number == Psnet_lowest_id){
2297 // at this point, we should _always_ have found the buffer
2298 SDL_assert(found_buf);
2300 // copy out the buffer data
2301 memcpy(data,Psnet_buffers[idx].data,Psnet_buffers[idx].len);
2302 *length = Psnet_buffers[idx].len;
2303 memcpy(from,&Psnet_buffers[idx].from_addr,sizeof(net_addr_t));
2305 // now we need to cleanup the packet list
2307 // mark the buffer as free
2308 Psnet_buffers[idx].sequence_number = -1;
2316 // initialize the buffering system
2317 void psnet_buffer_init() {}
2319 // buffer a packet (maintain order!)
2320 void psnet_buffer_packet(ubyte *data, int length) {}
2322 // get the index of the next packet in order!
2323 int psnet_buffer_get_next() { return -1; }
2327 // ------------------------------------------------------------------------------------------------------
2328 // RELIABLE UDP FUNCTIONS
2331 // verbose debug output
2332 #define PSNET_RELIABLE_VERBOSE
2334 // overall buffer space allocated to the buffers
2335 #define PSNET_RELIABLE_MAX_OUT_BUFFER_SIZE (1<<18) // 256k
2336 #define PSNET_RELIABLE_MAX_IN_BUFFER_SIZE (1<<12) // 4k
2338 // outgoing reliable packets
2339 typedef struct reliable_packet_out {
2340 ubyte data[MAX_PACKET_SIZE]; // data in the original packet
2341 ushort packet_size; // size of the original packet
2342 ushort player_flags; // bitflags indexing (1<<N) into the Psnet_reliable_addr[N] array
2343 ushort player_acks; // bitflags indexing (1<<N) into the Psnet_reliable_addr[N] array
2344 int player_stamps[MAX_PLAYERS]; // timeouts for each player
2345 ubyte num_resends[MAX_PLAYERS]; // # of times we've resent to a given player
2346 ushort out_id; // identifier of the packet
2347 fix age; // how old this packet is
2348 } reliable_packet_out;
2350 // incoming reliable packets
2351 typedef struct reliable_packet_in {
2352 ushort in_id; // identifier of the received packet
2353 fix age; // when we received the packet
2354 } reliable_packet_in;
2356 // # of outgoing and incoming buffers we'll allocate
2357 #define PSNET_RELIABLE_NUM_OUT_BUFFERS (int)(PSNET_RELIABLE_MAX_OUT_BUFFER_SIZE / sizeof(reliable_packet_out))
2358 #define PSNET_RELIABLE_NUM_IN_BUFFERS (int)(PSNET_RELIABLE_MAX_IN_BUFFER_SIZE / sizeof(reliable_packet_in))
2360 // timeout to be used for the packets
2361 #define PSNET_RELIABLE_TIMEOUT 1500 // in ms
2363 // # of repeats to use
2364 #define PSNET_RELIABLE_REPEAT 8 // repeat this many times max
2367 #define PSNET_RELIABLE_INVALID 0
2370 #define PSNET_RELIABLE_ACK 0xffff
2372 // the outgoing and incoming buffers themselves
2373 reliable_packet_out *Psnet_reliable_out[PSNET_RELIABLE_NUM_OUT_BUFFERS];
2374 reliable_packet_in *Psnet_reliable_in[PSNET_RELIABLE_NUM_IN_BUFFERS];
2376 // psnet reliable address list
2377 net_addr_t Psnet_reliable_addr[MAX_PLAYERS]; // address of registered "reliable" addrs
2378 int Psnet_reliable_addr_flags; // bitflags indicating which of the above are valid
2380 // my local identifier # (will only use lower 12 bits)
2381 ushort Psnet_reliable_local_id = 0x1;
2383 // is the reliable system initialized
2384 int Psnet_reliable_inited = 0;
2386 // # of times a packet has not been delivered
2387 int Psnet_reliable_fail_count = 0;
2389 // # of times packets have had to be resent
2390 int Psnet_reliable_resend_count = 0;
2392 // # of times we've run out of packets and had to overwrite existing ones
2393 int Psnet_reliable_overwrite_count = 0;
2395 // forward declarations ------------------------------------------------------
2397 // free up all used buffers
2398 void psnet_reliable_free_all_buffers();
2400 // get the index of the passed address or -1 if it doesn't exist
2401 int psnet_reliable_addr_index(net_addr_t *addr);
2403 // get the index into the address array from the passed bitflag
2404 int psnet_reliable_index_addr(int flags);
2406 // kill all outgoing packets belonging to the passed index
2407 void psnet_reliable_kill_outgoing(int index);
2409 // generate a unique id #, given the passed in value and the address it came from, return PSNET_RELIABLE_INVALID
2410 // upper 12 bytes should be valid # and the lower 4 should be free for this function to fill in
2411 ushort psnet_reliable_get_unique_id(ushort id_num,net_addr_t *from);
2413 // get the upper 12 bit version of my id# and increment the original
2414 ushort psnet_reliable_get_next_id();
2416 // get the index of a free outgoing relible packet buffer, killing the oldest if necessary
2417 int psnet_reliable_get_free_outgoing();
2419 // get the index of a free incoming relible packet buffer, killing the oldest if necessary
2420 int psnet_reliable_get_free_incoming();
2422 // actually send the data contained with the reliable_packet_out
2423 int psnet_reliable_send_packet(reliable_packet_out *out,int force_index = 0);
2425 // evaluate the status of a reliable packet - and free it up if the thing is _done_
2426 void psnet_reliable_evaluate_status(reliable_packet_out *out);
2428 // determine if the passed id# exists in the in-packet list, return the instance where it exists, or -1 if it doesn't
2429 int psnet_reliable_find_in_id(ushort id_num);
2431 // determine if the passed id# exists in the out-packet list, return the instance where it exists, or -1 if it doesn't
2432 int psnet_reliable_find_out_id(ushort id_num);
2434 // send an ack to the specified address
2435 void psnet_reliable_send_ack(net_addr_t *addr,ushort id_num);
2438 // extern functions -----------------------------------------------------------
2440 // initialize the psnet reliable system (return 0 on fail, 1 on success)
2441 int psnet_reliable_init()
2445 // if the system is already inited, do nothing
2446 if(Psnet_reliable_inited){
2450 #ifdef PSNET_RELIABLE_VERBOSE
2451 nprintf(("Network","PSNET RELIABLE SIZES : \n OUT BUFFER SIZE : %d\n OUT BUFFER COUNT %d\n IN BUFFER SIZE %d\n IN BUFFER COUNT %d\n",
2452 PSNET_RELIABLE_MAX_OUT_BUFFER_SIZE,PSNET_RELIABLE_NUM_OUT_BUFFERS,PSNET_RELIABLE_MAX_IN_BUFFER_SIZE,PSNET_RELIABLE_NUM_IN_BUFFERS));
2456 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2457 Psnet_reliable_out[idx] = NULL;
2459 for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2460 Psnet_reliable_in[idx] = NULL;
2463 // initialize all outgoing buffers
2464 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2465 Psnet_reliable_out[idx] = NULL;
2466 Psnet_reliable_out[idx] = (reliable_packet_out*)malloc(sizeof(reliable_packet_out));
2468 // if we failed to allocate the buffer, return failure
2469 if(Psnet_reliable_out[idx] == NULL){
2470 psnet_reliable_free_all_buffers();
2473 memset(Psnet_reliable_out[idx],0,sizeof(reliable_packet_out));
2476 // initialize all incoming buffers
2477 for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2478 Psnet_reliable_in[idx] = NULL;
2479 Psnet_reliable_in[idx] = (reliable_packet_in*)malloc(sizeof(reliable_packet_in));
2481 // if we failed to allocate the buffer, return failure
2482 if(Psnet_reliable_in[idx] == NULL){
2483 psnet_reliable_free_all_buffers();
2486 memset(Psnet_reliable_in[idx],0,sizeof(reliable_packet_in));
2489 // blast the reliable address list free
2490 memset(Psnet_reliable_addr,0,sizeof(net_addr_t) * MAX_PLAYERS);
2491 Psnet_reliable_addr_flags = 0;
2493 // set the system to be initialized
2494 Psnet_reliable_inited = 1;
2496 // initialize my local id #
2497 Psnet_reliable_local_id = 0x1;
2499 // initialize the packet delivery fail count
2500 Psnet_reliable_fail_count = 0;
2502 // intialize the packet necessary resend count
2503 Psnet_reliable_resend_count = 0;
2505 // initialize # of times we've run out of packets and had to overwrite existing ones
2506 Psnet_reliable_overwrite_count = 0;
2512 // shutdown the reliable system (free up buffers, etc)
2513 void psnet_reliable_close()
2515 // if the system is not initialized, don't do anything
2516 if(!Psnet_reliable_inited){
2520 // free up all buffers
2521 psnet_reliable_free_all_buffers();
2523 // blast all addresses clean
2524 memset(Psnet_reliable_addr,0,sizeof(net_addr_t) * MAX_PLAYERS);
2525 Psnet_reliable_addr_flags = 0;
2527 // set the system as being uninitialized
2528 Psnet_reliable_inited = 0;
2531 // notify the reliable system of a new address at index N
2532 void psnet_reliable_notify_new_addr(net_addr_t *addr,int index)
2534 // copy in the address
2535 memcpy(&Psnet_reliable_addr[index],addr,sizeof(net_addr_t));
2537 // set the bit indicating its validity
2538 Psnet_reliable_addr_flags |= (1<<index);
2541 // notify the reliable system of a drop at index N
2542 void psnet_reliable_notify_drop_addr(net_addr_t *addr)
2546 // do a lookup for the address
2547 index = psnet_reliable_addr_index(addr);
2549 // clear out all packets belonging exclusively to this address
2550 psnet_reliable_kill_outgoing(index);
2552 // clear the address and its existence bit
2553 memset(&Psnet_reliable_addr[index],0,sizeof(net_addr_t));
2554 Psnet_reliable_addr_flags &= ~(1<<index);
2558 // send a reliable data packet
2559 int psnet_reliable_send(ubyte *data,int packet_size,net_addr_t *addr)
2563 reliable_packet_out *p;
2565 // if the system is not initialized, don't do anything
2566 if(!Psnet_reliable_inited){
2570 // try and find a guy to send to
2572 to_index = psnet_reliable_addr_index(addr);
2574 nprintf(("Network","PSNET RELIABLE : could not find player for outgoing packet!\n"));
2578 // attempt to get a free buffer
2580 free_buffer = psnet_reliable_get_free_outgoing();
2581 if(free_buffer == -1){
2582 Int3(); // should never happen - we should always overwrite the oldest buffer
2585 // setup the data for the outgoing packet
2586 p = Psnet_reliable_out[free_buffer];
2587 memcpy(p->data,data,packet_size);
2588 p->packet_size = (ushort)packet_size;
2589 p->player_flags |= (1<<to_index);
2590 memset(p->player_stamps,0xf,sizeof(int) * MAX_PLAYERS);
2591 p->player_stamps[to_index] = timestamp(PSNET_RELIABLE_TIMEOUT);
2592 p->out_id = psnet_reliable_get_next_id();
2593 p->age = timer_get_fixed_seconds();
2596 return psnet_reliable_send_packet(p);
2599 // process frame for all reliable stuff (call once per frame)
2600 void psnet_reliable_process()
2603 reliable_packet_out *p;
2605 // if the system is not initialized, don't do anything
2606 if(!Psnet_reliable_inited){
2610 // go through all active packets
2611 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2612 // if the packet is active
2613 if(Psnet_reliable_out[idx]->out_id != PSNET_RELIABLE_INVALID){
2614 p = Psnet_reliable_out[idx];
2616 // loop through all active players and see if we need to resend
2617 for(s_idx=0;s_idx<MAX_PLAYERS;s_idx++){
2618 // if the packet is active for this player and he hasn't acked
2619 if(p->player_flags & (1<<s_idx) && !(p->player_acks & (1<<s_idx))){
2620 // if the timestamp has elapsed
2621 if((p->player_stamps[s_idx] != -1) && timestamp_elapsed(p->player_stamps[s_idx])){
2622 // if we are at max resends, bomb!
2623 if(p->num_resends[s_idx] >= PSNET_RELIABLE_REPEAT){
2624 #ifdef PSNET_RELIABLE_VERBOSE
2625 nprintf(("Network","PSNET RELIABLE : packet failed to be delivered (%d retries) !!\n",PSNET_RELIABLE_REPEAT));
2627 p->player_flags &= ~(1<<s_idx);
2629 // increment the fail count
2630 Psnet_reliable_fail_count++;
2632 // otherwise resend the packet
2634 // actually send the data contained with the reliable_packet_out
2635 psnet_reliable_send_packet(p,s_idx);
2637 // increment the resend count
2638 Psnet_reliable_resend_count++;
2640 #ifdef PSNET_RELIABLE_VERBOSE
2641 nprintf(("Network","PSNET RELIABLE : resending packet\n"));
2648 // evaluate if this packet has completed
2649 psnet_reliable_evaluate_status(p);
2654 // determine if the passed in reliable data should be processed, and sends an ack if necessary
2655 // return # of bytes which should be stripped off the data (reliable data header)
2656 int psnet_reliable_should_process(net_addr_t *addr,ubyte *data,int packet_size)
2658 ushort id_num,unique_id;
2662 reliable_packet_in *p;
2664 // get the reliable packet id #
2665 memcpy(&id_num,data,sizeof(ushort));
2667 // if the id# is an ack, get the id# do a lookup
2668 if(id_num == PSNET_RELIABLE_ACK){
2669 #ifdef PSNET_RELIABLE_VERBOSE
2670 nprintf(("Network","PSNET RELIABLE : ACK 1\n"));
2674 memcpy(&id_num,data+2,sizeof(ushort));
2676 // get the packet index
2677 // unique_id = psnet_reliable_get_unique_id(id_num,addr);
2679 packet_index = psnet_reliable_find_out_id(unique_id);
2680 player_index = psnet_reliable_addr_index(addr);
2681 if((packet_index != -1) && (player_index != -1)){
2682 #ifdef PSNET_RELIABLE_VERBOSE
2683 nprintf(("Network","PSNET RELIABLE : ACK 2\n"));
2686 Psnet_reliable_out[packet_index]->player_acks |= (1<<player_index);
2688 // check to see if this packet is _done_
2689 psnet_reliable_evaluate_status(Psnet_reliable_out[packet_index]);
2692 // return 4 bytes processed
2696 // otherwise - see if this is a new packet
2697 packet_index = psnet_reliable_find_in_id(id_num);
2698 if(packet_index == -1){
2701 free_index = psnet_reliable_get_free_incoming();
2702 if(free_index == -1){
2706 // setup the incoming packet
2707 p = Psnet_reliable_in[free_index];
2708 p->age = timer_get_fixed_seconds();
2709 p->in_id = psnet_reliable_get_unique_id(id_num,addr);
2712 psnet_reliable_send_ack(addr,id_num);
2714 // return 2 bytes processed
2717 // send another ack for good measure
2719 psnet_reliable_send_ack(addr,id_num);
2725 // forward definitions --------------------------------------------
2727 // free up all used buffers
2728 void psnet_reliable_free_all_buffers()
2732 // free all outgoing buffers
2733 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2734 // if the buffer is not null, free it
2735 if(Psnet_reliable_out[idx] != NULL){
2736 free(Psnet_reliable_out[idx]);
2737 Psnet_reliable_out[idx] = NULL;
2741 // free all incoming buffers
2742 for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2743 // if the buffer is not null, free it
2744 if(Psnet_reliable_in[idx] != NULL){
2745 free(Psnet_reliable_in[idx]);
2746 Psnet_reliable_in[idx] = NULL;
2751 // get the index of the passed address or -1 if it doesn't exist
2752 int psnet_reliable_addr_index(net_addr_t *addr)
2756 // look through all valid addresses
2757 for(idx=0;idx<MAX_PLAYERS;idx++){
2758 if((Psnet_reliable_addr_flags & (1<<idx)) && psnet_same(addr,&Psnet_reliable_addr[idx])){
2763 // couldn't find the address
2767 // get the index into the address array from the passed bitflag
2768 int psnet_reliable_index_addr(int flags)
2772 // look through all the bits in the flags
2773 for(idx=0;idx<MAX_PLAYERS;idx++){
2774 if(flags & (1<<idx)){
2779 // couldn't find any
2783 // kill all outgoing packets belonging to the passed index
2784 void psnet_reliable_kill_outgoing(int index)
2788 // go through all buffers
2789 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2790 if(Psnet_reliable_out[idx]->out_id != PSNET_RELIABLE_INVALID){
2791 // if it is exclusively his, kill the whole packet
2792 if(Psnet_reliable_out[idx]->player_flags == (1<<index)){
2793 memset(Psnet_reliable_out[idx],0,sizeof(reliable_packet_out));
2796 // if it belongs to him and other players, kill his entry
2797 else if(Psnet_reliable_out[idx]->player_flags & (1<<index)){
2798 Psnet_reliable_out[idx]->player_flags &= ~(1<<index);
2799 Psnet_reliable_out[idx]->num_resends[index] = 0;
2805 // generate a unique id #, given the passed in value and the address it came from, return PSNET_RELIABLE_INVALID
2806 // upper 12 bytes should be valid # and the lower 4 should be free for this function to fill in
2807 ushort psnet_reliable_get_unique_id(ushort id_num,net_addr_t *from)
2812 // if the lower 4 bits are not clear, we've got a problem
2817 // lookup through the Psnet_reliable_addr[] list and try and find the index
2818 for(idx=0;idx<MAX_PLAYERS;idx++){
2819 if((idx == 1) /*(Psnet_reliable_addr_flags & (1<<idx)) && (psnet_same(from,&Psnet_reliable_addr[idx]))*/){
2820 // fill in the lower 4 bits
2822 id_num |= (cast & 0xf);
2827 // couldn't find an id#
2828 return PSNET_RELIABLE_INVALID;
2831 // get the upper 12 bit version of my id# and increment the original
2832 ushort psnet_reliable_get_next_id()
2834 ushort id_num = Psnet_reliable_local_id;
2836 // clear out the upper 4 bits
2839 // shift 4 bits to the left
2842 // increment the local id #
2843 if(Psnet_reliable_local_id == 0x0fff){
2844 Psnet_reliable_local_id = 0x1;
2846 Psnet_reliable_local_id++;
2849 // return the shifted value
2853 // get the index of a free outgoing relible packet buffer, killing the oldest if necessary
2854 int psnet_reliable_get_free_outgoing()
2857 int oldest_index = -1;
2860 // search through all buffers
2861 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
2862 if(Psnet_reliable_out[idx]->out_id == PSNET_RELIABLE_INVALID){
2866 // keep track of the oldest packet
2867 if((oldest_index == -1) || (Psnet_reliable_out[idx]->age < oldest)){
2869 oldest = Psnet_reliable_out[idx]->age;
2873 // if we got here, all of our buffers are full, so we should kill the oldest one
2874 memset(Psnet_reliable_out[oldest_index],0,sizeof(reliable_packet_out));
2875 Psnet_reliable_overwrite_count = 0;
2876 #ifdef PSNET_RELIABLE_VERBOSE
2877 nprintf(("Network","PSNET RELIABLE : overwriting old send buffer\n"));
2879 return oldest_index;
2882 // get the index of a free incoming relible packet buffer, killing the oldest if necessary
2883 int psnet_reliable_get_free_incoming()
2886 int oldest_index = -1;
2889 // search through all buffers
2890 for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2891 if(Psnet_reliable_in[idx]->in_id == PSNET_RELIABLE_INVALID){
2895 // keep track of the oldest packet
2896 if((oldest_index == -1) || (Psnet_reliable_in[idx]->age < oldest)){
2898 oldest = Psnet_reliable_in[idx]->age;
2902 // if we got here, all of our buffers are full, so we should kill the oldest one
2903 memset(Psnet_reliable_in[oldest_index],0,sizeof(reliable_packet_in));
2904 #ifdef PSNET_RELIABLE_VERBOSE
2905 nprintf(("Network","PSNET RELIABLE : overwriting old recv buffer\n"));
2907 return oldest_index;
2910 // actually send the data contained with the reliable_packet_out
2911 int psnet_reliable_send_packet(reliable_packet_out *out,int force_index)
2913 ubyte data[MAX_PACKET_SIZE];
2915 int packet_size = 2 + out->packet_size;
2917 // stick the identifier on the front of the packet
2918 memcpy(data,&out->out_id,sizeof(ushort));
2920 // copy in the actual data
2921 memcpy(data+2,out->data,out->packet_size);
2923 // send the packet and update the timestamp for all players
2925 // send to one specified player in the packet
2927 if(force_index != 0){
2928 if(out->player_flags & (1<<force_index) && !(out->player_acks & (1<<force_index))){
2929 bytes_sent = psnet_send(&Psnet_reliable_addr[force_index],data,packet_size,PSNET_FLAG_RAW,1);
2930 out->player_stamps[force_index] = timestamp(PSNET_RELIABLE_TIMEOUT);
2931 out->num_resends[force_index]++;
2934 // send to all players contained in the packet
2936 for(idx=0;idx<MAX_PLAYERS;idx++){
2937 // if this guy is flagged and he exists and he hasn't already acked
2938 if(out->player_flags & (1<<idx) && (Psnet_reliable_addr_flags & (1<<idx)) && !(out->player_acks & (1<<idx))){
2939 bytes_sent = psnet_send(&Psnet_reliable_addr[idx],data,packet_size,PSNET_FLAG_RAW,1);
2940 out->player_stamps[idx] = timestamp(PSNET_RELIABLE_TIMEOUT);
2941 out->num_resends[idx]++;
2950 // evaluate the status of a reliable packet - and free it up if the thing is _done_
2951 void psnet_reliable_evaluate_status(reliable_packet_out *out)
2955 // check to see if all players have acked or failed miserably
2957 for(idx=0;idx<MAX_PLAYERS;idx++){
2958 // if the packet is active for this guy but he has not acked yet
2959 if((out->player_flags & (1<<idx)) && !(out->player_acks & (1<<idx))){
2965 // if its ok to annihilate this packet, do so
2967 memset(out,0,sizeof(reliable_packet_out));
2971 // determine if the passed id# exists in the in-packet list, return the instance where it exists, or -1 if it doesn't
2972 int psnet_reliable_find_in_id(ushort id_num)
2976 // if the id is 0, its invalid
2977 if(id_num == PSNET_RELIABLE_INVALID){
2981 // look through all in packets
2982 for(idx=0;idx<PSNET_RELIABLE_NUM_IN_BUFFERS;idx++){
2983 if(id_num == Psnet_reliable_in[idx]->in_id){
2992 // determine if the passed id# exists in the out-packet list, return the instance where it exists, or -1 if it doesn't
2993 int psnet_reliable_find_out_id(ushort id_num)
2997 // if the id is 0, its invalid
2998 if(id_num == PSNET_RELIABLE_INVALID){
3002 // look through all in packets
3003 for(idx=0;idx<PSNET_RELIABLE_NUM_OUT_BUFFERS;idx++){
3004 if(id_num == Psnet_reliable_out[idx]->out_id){
3013 // send an ack to the specified address
3014 void psnet_reliable_send_ack(net_addr_t *addr,ushort id_num)
3020 val = PSNET_RELIABLE_ACK;
3021 memcpy(data,&val,sizeof(ushort));
3024 memcpy(data+2,&id_num,sizeof(ushort));
3027 psnet_send(addr,data,4,PSNET_FLAG_RAW,Reliable_socket);
3030 // wrappers around select() and recvfrom() for lagging/losing data, and for sorting through different packet types
3031 int RECVFROM(SOCKET s, char * buf, int len, int flags, sockaddr *from, int *fromlen, int psnet_type)
3037 // if we have no buffer! The user should have made sure this wasn't the case by calling SELECT()
3038 ret = psnet_buffer_get_next((ubyte*)buf, &ret_len, &addr);
3044 // otherwise, stuff the outgoing data
3045 ((struct sockaddr_in*)from)->sin_port = htons(addr.port);
3046 memcpy(&((struct sockaddr_in*)from)->sin_addr.s_addr, addr.addr, 4);
3047 ((struct sockaddr_in*)from)->sin_family = AF_INET;
3048 *fromlen = sizeof(struct sockaddr_in);
3050 // return bytes read
3054 int SELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set*exceptfds, struct timeval* timeout, int psnet_type)
3056 // if this is a check for writability, just return the select
3057 if(writefds != NULL){
3058 return select(nfds, readfds, writefds, exceptfds, timeout);
3061 // do we have any buffers in here?
3062 if((Psnet_lowest_id == -1) || (Psnet_lowest_id > Psnet_highest_id)){
3070 // wrappers around sendto to sorting through different packet types
3071 int SENDTO(SOCKET s, char * buf, int len, int flags, sockaddr * to, int tolen, int psnet_type)
3073 return sendto(s, buf, len, flags, (struct sockaddr *)to, tolen);
3076 // call this once per frame to read everything off of our socket
3077 void PSNET_TOP_LAYER_PROCESS()
3079 psnet_get_socket_data(Unreliable_socket);
3082 #endif // #ifndef PSNET2