aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/net_pckt_peer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parsec/net_pckt_peer.cpp')
-rw-r--r--src/parsec/net_pckt_peer.cpp860
1 files changed, 860 insertions, 0 deletions
diff --git a/src/parsec/net_pckt_peer.cpp b/src/parsec/net_pckt_peer.cpp
new file mode 100644
index 0000000..3511815
--- /dev/null
+++ b/src/parsec/net_pckt_peer.cpp
@@ -0,0 +1,860 @@
+/*
+ * PARSEC - Packet Functions
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:39 $
+ *
+ * Orginally written by:
+ * Copyright (c) Clemens Beer <cbx@parsec.org> 2002
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// C library
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+
+// subsystem headers
+//#include "aud_defs.h"
+#include "net_defs.h"
+//#include "sys_defs.h"
+
+// mathematics header
+#include "utl_math.h"
+
+// network code config
+#include "net_conf.h"
+
+// subsystem linkage info
+#include "linkinfo.h"
+
+// local module header
+#include "net_pckt_peer.h"
+
+// proprietary module headers
+#include "con_aux.h"
+#include "net_game.h"
+#include "net_pckt.h"
+#include "net_rmev.h"
+#include "net_swap.h"
+#include "net_util.h"
+#include "obj_creg.h"
+
+
+#ifdef DBIND_PROTOCOL
+
+ #undef NETs_HandleOutPacket
+ #undef NETs_HandleOutPacket_DEMO
+ #undef NETs_HandleInPacket
+ #undef NETs_HandleInPacket_DEMO
+ #undef NETs_NetPacketExternal_DEMO_GetSize
+ #undef NETs_StdGameHeader
+ #undef NETs_WritePacketInfo
+
+ #define NETs_HandleOutPacket NETs_PEERTOPEER_HandleOutPacket
+ #define NETs_HandleOutPacket_DEMO NETs_PEERTOPEER_HandleOutPacket_DEMO
+ #define NETs_HandleInPacket NETs_PEERTOPEER_HandleInPacket
+ #define NETs_HandleInPacket_DEMO NETs_PEERTOPEER_HandleInPacket_DEMO
+ #define NETs_NetPacketExternal_DEMO_GetSize NETs_PEERTOPEER_NetPacketExternal_DEMO_GetSize
+ #define NETs_StdGameHeader NETs_PEERTOPEER_StdGameHeader
+ #define NETs_WritePacketInfo NETs_PEERTOPEER_WritePacketInfo
+
+#endif
+
+
+// flags ----------------------------------------------------------------------
+//
+#define _SET_RE_LISTSIZE_ON_PACK
+
+// protocol type signature ----------------------------------------------------
+//
+const char net_packet_signature_peer2peer[] = "PP2";
+
+// fill standard fields in gamepacket header ( peer-to-peer ) --------------
+//
+void NETs_StdGameHeader( byte command, NetPacket* gamepacket )
+{
+ ASSERT( gamepacket != NULL );
+
+ NetPacket_PEER* gamepacket_PEER = (NetPacket_PEER*) gamepacket;
+
+ // clear header and remote event list area
+ memset( gamepacket_PEER, 0, NET_MAX_DATA_LENGTH );
+
+ gamepacket_PEER->Universe = MyUniverse;
+ gamepacket_PEER->NumPlayers = NumRemPlayers;
+
+ gamepacket_PEER->Command = command;
+ gamepacket_PEER->SendPlayerId = LocalPlayerId;
+ gamepacket_PEER->MessageId = CurSendMessageId_PEER++;
+
+ // RE list size always includes the RE terminator
+ ((RE_Header* )&gamepacket_PEER->RE_List)->RE_Type = RE_EMPTY;
+ gamepacket_PEER->RE_ListSize = sizeof( dword );
+}
+
+
+// return the packetsize of a external DEMO packet ( PEER ) -------------------
+//
+size_t NETs_NetPacketExternal_DEMO_GetSize( const NetPacketExternal* ext_gamepacket )
+{
+ ASSERT( ext_gamepacket != NULL );
+ ASSERT( NET_ProtocolPEER() );
+
+ // header is always needed
+ size_t psize = sizeof( NetPacketExternal_DEMO_PEER ) - sizeof( dword );
+
+ // add size of remote event list
+ RE_Header* relist = (RE_Header *) &((NetPacketExternal_DEMO_PEER*)ext_gamepacket)->RE_List;
+ psize += NET_RmEvList_GetSize( relist );
+
+ ASSERT( psize <= (size_t)NET_MAX_DATA_LENGTH );
+ return psize;
+}
+
+// determine actually needed size of packet (strip unused remote event area) --
+//
+PRIVATE
+size_t PEER_NetPacketExternal_GetSize( NetPacketExternal_PEER* ext_gamepacket_PEER )
+{
+ //NOTE:
+ // even though this function is operating on a packet in network byte-order,
+ // swapping is not necessary since all accesses are byte-sized. (that is,
+ // byte-ordering is entirely irrelevant.)
+
+ // header is always needed
+ size_t psize = sizeof( NetPacketExternal_PEER ) - sizeof( dword );
+
+ // add size of remote event list
+ psize += NET_RmEvList_GetSize( (RE_Header *) &ext_gamepacket_PEER->RE_List );
+
+ ASSERT( psize <= (size_t)NET_MAX_DATA_LENGTH );
+ return psize;
+}
+
+// swap endianness of whole (external) network packet -------------------------
+//
+PRIVATE
+void PEER_NetPacketExternal_Swap( NetPacketExternal* ext_gamepacket, int incoming )
+{
+ ASSERT( ext_gamepacket != NULL );
+
+ NetPacketExternal_PEER* ext_gamepacket_PEER = (NetPacketExternal_PEER*)ext_gamepacket;
+
+#ifdef ENABLE_PACKET_SWAPPING
+
+ ext_gamepacket_PEER->Protocol = NET_SWAP_16( ext_gamepacket_PEER->Protocol );
+
+ ext_gamepacket_PEER->MessageId = NET_SWAP_32( ext_gamepacket_PEER->MessageId );
+ ext_gamepacket_PEER->param4 = NET_SWAP_32( ext_gamepacket_PEER->param4 );
+ ext_gamepacket_PEER->GameTime = NET_SWAP_32( ext_gamepacket_PEER->GameTime );
+
+ //NOTE:
+ // in PKTP_PING packets ShipRemInfo == ServerInfo
+
+ switch ( ext_gamepacket_PEER->Command ) {
+ case PKTP_COMMAND:
+ // invalid packets for PEER mode
+ ASSERT( FALSE );
+ break;
+ default:
+ {
+ // swap endianness of ShipRemInfo in normal packets
+ if ( incoming ) {
+ SWAP_ShipRemInfo_in( &ext_gamepacket_PEER->ShipInfo );
+ } else {
+ SWAP_ShipRemInfo_out( &ext_gamepacket_PEER->ShipInfo );
+ }
+ }
+ break;
+ }
+
+ // swap entire RE list
+ NET_RmEvList_Swap( (RE_Header*) &ext_gamepacket_PEER->RE_List, incoming );
+
+#endif // ENABLE_PACKET_SWAPPING
+}
+
+// swap endianness of whole (external) DEMO packet ----------------------------
+//
+PRIVATE
+void PEER_NetPacketExternal_DEMO_Swap( NetPacketExternal* ext_gamepacket, int incoming )
+{
+ ASSERT( ext_gamepacket != NULL );
+
+ NetPacketExternal_DEMO_PEER* ext_gamepacket_DEMO_PEER = (NetPacketExternal_DEMO_PEER*)ext_gamepacket;
+
+#ifdef ENABLE_PACKET_SWAPPING
+
+ ext_gamepacket_DEMO_PEER->MessageId = NET_SWAP_32( ext_gamepacket_DEMO_PEER->MessageId );
+ ext_gamepacket_DEMO_PEER->param4 = NET_SWAP_32( ext_gamepacket_DEMO_PEER->param4 );
+ ext_gamepacket_DEMO_PEER->GameTime = NET_SWAP_32( ext_gamepacket_DEMO_PEER->GameTime );
+ ext_gamepacket_DEMO_PEER->pktsize = NET_SWAP_32( ext_gamepacket_DEMO_PEER->pktsize );
+ ext_gamepacket_DEMO_PEER->crc32 = NET_SWAP_32( ext_gamepacket_DEMO_PEER->crc32 );
+
+ //NOTE:
+ // in PKTP_PING packets ShipRemInfo == ServerInfo
+
+ switch ( ext_gamepacket_DEMO_PEER->Command ) {
+ case PKTP_COMMAND:
+ // no swapping needed
+ break;
+ default:
+ {
+ // swap endianness of ShipRemInfo in normal packets
+ if ( incoming ) {
+ SWAP_ShipRemInfo_in( &ext_gamepacket_DEMO_PEER->ShipInfo );
+ } else {
+ SWAP_ShipRemInfo_out( &ext_gamepacket_DEMO_PEER->ShipInfo );
+ }
+ }
+ break;
+ }
+
+ // swap entire RE list
+ NET_RmEvList_Swap( (RE_Header*) &ext_gamepacket_DEMO_PEER->RE_List, incoming );
+
+#endif // ENABLE_PACKET_SWAPPING
+}
+
+
+// store the CRC in an external packet ----------------------------------------
+//
+PRIVATE
+void PEER_NetPacketExternal_StoreCRC( NetPacketExternal_PEER* ext_gamepacket, size_t pktsize )
+{
+ // set the crc32 field to known value and calculate the CRC for the header
+ ext_gamepacket->crc32 = 0;
+ ext_gamepacket->crc32 = NET_CalcCRC( (void*)ext_gamepacket, pktsize );
+
+ // swap CRC
+ ext_gamepacket->crc32 = NET_SWAP_32( ext_gamepacket->crc32 );
+}
+
+// pack an internal packet to an external packet ( peer-to-peer ) ---------
+//
+size_t NETs_HandleOutPacket( const NetPacket* int_gamepacket, NetPacketExternal* ext_gamepacket )
+{
+ ASSERT( int_gamepacket != NULL );
+ ASSERT( ext_gamepacket != NULL );
+ ASSERT( NET_ProtocolPEER() );
+
+ NetPacket_PEER* int_gamepacket_PEER = (NetPacket_PEER*) int_gamepacket;
+ NetPacketExternal_PEER* ext_gamepacket_PEER = (NetPacketExternal_PEER*) ext_gamepacket;
+
+ ASSERT( ( int_gamepacket_PEER->SendPlayerId != int_gamepacket_PEER->DestPlayerId ) ||
+ ( ( int_gamepacket_PEER->Command >= PKTP_CONNECT ) && ( int_gamepacket_PEER->Command <= PKTP_SUBDUE_SLAVE ) ) );
+
+ // fill header for external packets
+ strncpy( ext_gamepacket_PEER->Signature, net_packet_signature_peer2peer, SIGNATURE_LEN_PEER2PEER );
+ ext_gamepacket_PEER->Signature[ SIGNATURE_LEN_PEER2PEER ] = 0;
+ ext_gamepacket_PEER->Protocol = PROTOCOL_PEER2PEER;
+ ext_gamepacket_PEER->MajorVersion = P2P_PROTOCOL_MAJOR;
+ ext_gamepacket_PEER->MinorVersion = P2P_PROTOCOL_MINOR;
+ ext_gamepacket_PEER->MessageId = int_gamepacket_PEER->MessageId;
+
+ // pack internal packet data to external packet
+ ext_gamepacket_PEER->SendPlayerId = (signed char)int_gamepacket_PEER->SendPlayerId;
+ ext_gamepacket_PEER->MessageId = int_gamepacket_PEER->MessageId;
+ ext_gamepacket_PEER->Command = (byte)int_gamepacket_PEER->Command;
+ ext_gamepacket_PEER->param1 = (signed char)int_gamepacket_PEER->params[ 0 ];
+ ext_gamepacket_PEER->param2 = (signed char)int_gamepacket_PEER->params[ 1 ];
+ ext_gamepacket_PEER->param3 = (signed char)int_gamepacket_PEER->params[ 2 ];
+ ext_gamepacket_PEER->param4 = int_gamepacket_PEER->params[ 3 ];
+
+ ext_gamepacket_PEER->DestPlayerId = (signed char)int_gamepacket_PEER->DestPlayerId;
+ ext_gamepacket_PEER->Universe = int_gamepacket_PEER->Universe;
+ ext_gamepacket_PEER->NumPlayers = int_gamepacket_PEER->NumPlayers;
+ for( int nPlayer = 0; nPlayer < MAX_NET_ALLOC_SLOTS; nPlayer++ ) {
+ ext_gamepacket_PEER->PlayerKills[ nPlayer ] = int_gamepacket_PEER->PlayerKills[ nPlayer ];
+ }
+ memcpy( &ext_gamepacket_PEER->ShipInfo, &int_gamepacket_PEER->ShipInfo, sizeof( ShipRemInfo ) );
+ ext_gamepacket_PEER->GameTime = int_gamepacket_PEER->GameTime;
+
+ //FIXME: [1/30/2002] remove this, when RE_Listsize is correctly maintained
+#ifdef _SET_RE_LISTSIZE_ON_PACK
+ int_gamepacket_PEER->RE_ListSize = NET_RmEvList_GetSize( (RE_Header*)&int_gamepacket_PEER->RE_List );
+#endif // _SET_RE_LISTSIZE_ON_PACK
+
+ // check that RE_ListSize corresponds with the actual length of the remote event list
+ ASSERT( int_gamepacket_PEER->RE_ListSize == NET_RmEvList_GetSize( (RE_Header*)&int_gamepacket_PEER->RE_List ) );
+
+ memcpy( (void*)&ext_gamepacket_PEER->RE_List, (void*)&int_gamepacket_PEER->RE_List, int_gamepacket_PEER->RE_ListSize );
+
+ // get the size of the packet
+ size_t pktsize = PEER_NetPacketExternal_GetSize( ext_gamepacket_PEER );
+
+ // establish network byte-order for external packet ( outgoing )
+ PEER_NetPacketExternal_Swap( ext_gamepacket_PEER, FALSE );
+
+ // store the CRC in the packet
+ PEER_NetPacketExternal_StoreCRC( ext_gamepacket_PEER, pktsize );
+
+#ifdef ENCRYPT_PACKETS
+
+ if ( !( AUX_NETCODE_FLAGS & 2 ) ) {
+
+ // encrypt packet payload
+ NET_EncryptData( &ext_gamepacket_PEER->crc32, pktsize - offsetof( NetPacketExternal_PEER, crc32 ) );
+
+ // establish host byte order, modify field, and establish network order again
+ ext_gamepacket_PEER->Protocol = NET_SWAP_16( ext_gamepacket_PEER->Protocol );
+ ext_gamepacket_PEER->Protocol |= PROTOCOL_ENCRYPTED;
+ ext_gamepacket_PEER->Protocol = NET_SWAP_16( ext_gamepacket_PEER->Protocol );
+ }
+
+#endif // ENCRYPT_PACKETS
+
+ return pktsize;
+}
+
+// handle an incoming packet (peer-to-peer) -------------------------------
+//
+int NETs_HandleInPacket( const NetPacketExternal* ext_gamepacket, const int ext_pktsize, NetPacket* int_gamepacket )
+{
+ ASSERT( ext_gamepacket != NULL );
+ ASSERT( ( ext_pktsize > 0 ) && ( ext_pktsize < CurMaxDataLength ) );
+ ASSERT( int_gamepacket != NULL );
+ ASSERT( NET_ProtocolPEER() );
+
+ // sanity check for packet len
+ if ( ext_pktsize > CurMaxDataLength ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [invalid packet len]." ); );
+ return FALSE;
+ }
+
+ NetPacket_PEER* int_gamepacket_PEER = (NetPacket_PEER*) int_gamepacket;
+ NetPacketExternal_PEER* ext_gamepacket_PEER = (NetPacketExternal_PEER*)ext_gamepacket;
+
+#ifdef ENCRYPT_PACKETS
+
+ // establish host byte order
+ ext_gamepacket_PEER->Protocol = NET_SWAP_16( ext_gamepacket_PEER->Protocol );
+
+ // check whether the packet supposedly is encrypted
+ if ( ext_gamepacket_PEER->Protocol & PROTOCOL_ENCRYPTED ) {
+
+ if ( !( AUX_NETCODE_FLAGS & 2 ) ) {
+
+ // decrypt external packet
+ NET_DecryptData( &ext_gamepacket_PEER->crc32, ext_pktsize - offsetof( NetPacketExternal_PEER, crc32 ) );
+ }
+
+ // revert to decrypted protocol
+ ext_gamepacket_PEER->Protocol &= ~PROTOCOL_ENCRYPTED;
+ }
+
+ // establish network byte order
+ ext_gamepacket_PEER->Protocol = NET_SWAP_16( ext_gamepacket_PEER->Protocol );
+
+#endif // ENCRYPT_PACKETS
+
+ if ( !( AUX_NETCODE_FLAGS & 1 ) ) {
+
+ // as the CRC has been calculated with the crc32 field stored in the packet beeing set to zero.
+ // we need to do this here as well, backup CRC for compare
+ dword crc32_stored = NET_SWAP_32( ext_gamepacket_PEER->crc32 );
+ ext_gamepacket_PEER->crc32 = 0;
+
+ // calculate CRC over packet
+ dword crc32 = NET_CalcCRC( ext_gamepacket_PEER, ext_pktsize );
+
+ // check whether CRC is correct
+ if ( crc32 != crc32_stored ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [CRC check failed]." ); );
+ return FALSE;
+ }
+ }
+
+ // check for correct signature
+ if ( strncmp( ext_gamepacket_PEER->Signature, net_packet_signature_peer2peer, SIGNATURE_LEN_PEER2PEER ) != 0 ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [invalid signature]." ); );
+ return FALSE;
+ }
+
+ // convert external packet from packet byte-order to host byte-order
+ PEER_NetPacketExternal_Swap( ext_gamepacket_PEER, TRUE );
+
+ // check for correct protocol
+ if ( ext_gamepacket_PEER->Protocol != PROTOCOL_PEER2PEER ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [invalid protocol]." ); );
+ return FALSE;
+ }
+
+ // check for correct protocol version
+ if ( ( ext_gamepacket_PEER->MajorVersion != P2P_PROTOCOL_MAJOR ) || ( ext_gamepacket_PEER->MinorVersion != P2P_PROTOCOL_MINOR ) ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [incompatible protocol version]." ); );
+ return FALSE;
+ }
+
+ // check for correct universe
+ if ( ext_gamepacket_PEER->Universe != MyUniverse ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [wrong universe]." ); );
+ return FALSE;
+ }
+
+ // unpack external packet data to internal packet
+ int_gamepacket_PEER->SendPlayerId = (int)ext_gamepacket_PEER->SendPlayerId;
+ int_gamepacket_PEER->MessageId = ext_gamepacket_PEER->MessageId;
+ int_gamepacket_PEER->Command = (int)ext_gamepacket_PEER->Command;
+ int_gamepacket_PEER->params[ 0 ] = (int)ext_gamepacket_PEER->param1;
+ int_gamepacket_PEER->params[ 1 ] = (int)ext_gamepacket_PEER->param2;
+ int_gamepacket_PEER->params[ 2 ] = (int)ext_gamepacket_PEER->param3;
+ int_gamepacket_PEER->params[ 3 ] = ext_gamepacket_PEER->param4;
+
+ int_gamepacket_PEER->DestPlayerId = (int)ext_gamepacket_PEER->DestPlayerId;
+ int_gamepacket_PEER->Universe = ext_gamepacket_PEER->Universe;
+ int_gamepacket_PEER->NumPlayers = ext_gamepacket_PEER->NumPlayers;
+ for( int nPlayer = 0; nPlayer < MAX_NET_ALLOC_SLOTS; nPlayer++ ) {
+ int_gamepacket_PEER->PlayerKills[ nPlayer ] = ext_gamepacket_PEER->PlayerKills[ nPlayer ];
+ }
+ memcpy( &int_gamepacket_PEER->ShipInfo, &ext_gamepacket_PEER->ShipInfo, sizeof( ShipRemInfo ) );
+ int_gamepacket_PEER->GameTime = ext_gamepacket_PEER->GameTime;
+
+ ASSERT( ( int_gamepacket_PEER->SendPlayerId != int_gamepacket_PEER->DestPlayerId ) || ( ( int_gamepacket_PEER->Command >= PKTP_CONNECT ) && ( int_gamepacket_PEER->Command <= PKTP_SUBDUE_SLAVE ) ) );
+
+ // check whether external remote event list is well formed ( integrity and length )
+ if ( NET_RmEvList_IsWellFormed( (RE_Header*)&ext_gamepacket_PEER->RE_List ) == FALSE ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket: dropped packet [invalid RE list]." ); );
+ return FALSE;
+ }
+
+ // determine remote event list size ( includes RE termination )
+ int_gamepacket_PEER->RE_ListSize = NET_RmEvList_GetSize( (RE_Header*)&ext_gamepacket_PEER->RE_List );
+ memcpy( (void*)&int_gamepacket_PEER->RE_List, (void*)&ext_gamepacket_PEER->RE_List, int_gamepacket_PEER->RE_ListSize );
+
+ return TRUE;
+}
+
+// translate internal packet to external DEMO packet (peer-to-peer) -----------
+//
+size_t NETs_HandleOutPacket_DEMO( const NetPacket* int_gamepacket, NetPacketExternal* ext_gamepacket )
+{
+ ASSERT( int_gamepacket != NULL );
+ ASSERT( ext_gamepacket != NULL );
+ ASSERT( NET_ProtocolPEER() );
+
+ NetPacket_PEER* int_gamepacket_PEER = (NetPacket_PEER*) int_gamepacket;
+ NetPacketExternal_DEMO_PEER* ext_gamepacket_DEMO_PEER = (NetPacketExternal_DEMO_PEER*) ext_gamepacket;
+
+ ASSERT( ( int_gamepacket_PEER->SendPlayerId != int_gamepacket_PEER->DestPlayerId ) || ( ( int_gamepacket_PEER->Command >= PKTP_CONNECT ) && ( int_gamepacket_PEER->Command <= PKTP_SUBDUE_SLAVE ) ) );
+
+ // fill header for external packets
+ strncpy( ext_gamepacket_DEMO_PEER->Signature, net_packet_signature_peer2peer, SIGNATURE_LEN_PEER2PEER );
+ ext_gamepacket_DEMO_PEER->Signature[ SIGNATURE_LEN_PEER2PEER ] = 0;
+ ext_gamepacket_DEMO_PEER->Protocol = PROTOCOL_PEER2PEER;
+ ext_gamepacket_DEMO_PEER->MajorVersion = P2P_PROTOCOL_MAJOR;
+ ext_gamepacket_DEMO_PEER->MinorVersion = P2P_PROTOCOL_MINOR;
+ ext_gamepacket_DEMO_PEER->MessageId = int_gamepacket_PEER->MessageId;
+
+ // pack internal packet data to external packet
+ ext_gamepacket_DEMO_PEER->SendPlayerId = (signed char)int_gamepacket_PEER->SendPlayerId;
+ ext_gamepacket_DEMO_PEER->MessageId = int_gamepacket_PEER->MessageId;
+ ext_gamepacket_DEMO_PEER->Command = (byte)int_gamepacket_PEER->Command;
+ ext_gamepacket_DEMO_PEER->param1 = (signed char)int_gamepacket_PEER->params[ 0 ];
+ ext_gamepacket_DEMO_PEER->param2 = (signed char)int_gamepacket_PEER->params[ 1 ];
+ ext_gamepacket_DEMO_PEER->param3 = (signed char)int_gamepacket_PEER->params[ 2 ];
+ ext_gamepacket_DEMO_PEER->param4 = int_gamepacket_PEER->params[ 3 ];
+
+ ext_gamepacket_DEMO_PEER->DestPlayerId = (signed char)int_gamepacket_PEER->DestPlayerId;
+ ext_gamepacket_DEMO_PEER->Universe = int_gamepacket_PEER->Universe;
+ ext_gamepacket_DEMO_PEER->NumPlayers = int_gamepacket_PEER->NumPlayers;
+ for( int nPlayer = 0; nPlayer < MAX_NET_ALLOC_SLOTS; nPlayer++ ) {
+ ext_gamepacket_DEMO_PEER->PlayerKills[ nPlayer ] = int_gamepacket_PEER->PlayerKills[ nPlayer ];
+ }
+ memcpy( &ext_gamepacket_DEMO_PEER->ShipInfo, &int_gamepacket_PEER->ShipInfo, sizeof( ShipRemInfo ) );
+ ext_gamepacket_DEMO_PEER->GameTime = int_gamepacket_PEER->GameTime;
+
+ //FIXME: [1/30/2002] remove this, when RE_Listsize is correctly maintained
+#ifdef _SET_RE_LISTSIZE_ON_PACK
+ int_gamepacket_PEER->RE_ListSize = NET_RmEvList_GetSize( (RE_Header*)&int_gamepacket_PEER->RE_List );
+#endif // _SET_RE_LISTSIZE_ON_PACK
+
+ // check that RE_ListSize corresponds with the actual length of the remote event list
+ ASSERT( int_gamepacket_PEER->RE_ListSize == NET_RmEvList_GetSize( (RE_Header*)&int_gamepacket_PEER->RE_List ) );
+
+ memcpy( (void*)&ext_gamepacket_DEMO_PEER->RE_List, (void*)&int_gamepacket_PEER->RE_List, int_gamepacket_PEER->RE_ListSize );
+
+ // get the packet length and store it in the DEMO packet
+ size_t pktsize = NETs_NetPacketExternal_DEMO_GetSize( ext_gamepacket_DEMO_PEER );
+ ext_gamepacket_DEMO_PEER->pktsize = pktsize;
+
+ // establish network byte-order for external packet ( outgoing )
+ PEER_NetPacketExternal_DEMO_Swap( ext_gamepacket_DEMO_PEER, FALSE );
+
+ // set the crc32 and crc_header fields to known value
+ // FIXME: in GMSV mode we could set the CRC to the challenge
+ ext_gamepacket_DEMO_PEER->crc32 = 0;
+ ext_gamepacket_DEMO_PEER->crc_header = 0;
+
+ // calculate the CRC for the whole packet and establish network byte order
+ ext_gamepacket_DEMO_PEER->crc32 = NET_CalcCRC( (void*)ext_gamepacket_DEMO_PEER, pktsize );
+ ext_gamepacket_DEMO_PEER->crc32 = NET_SWAP_32( ext_gamepacket_DEMO_PEER->crc32 );
+
+#ifdef ENCRYPT_PACKETS
+
+ if ( !( AUX_NETCODE_FLAGS & 2 ) ) {
+
+ // encrypt packet payload and crc32 field
+ NET_EncryptData( &ext_gamepacket_DEMO_PEER->MessageId, pktsize - offsetof( NetPacketExternal_DEMO_PEER, MessageId ) );
+ NET_EncryptData( &ext_gamepacket_DEMO_PEER->crc32, sizeof( dword ) );
+
+ // modify protocol to indicate an encrypted packet
+ ext_gamepacket_DEMO_PEER->Protocol |= PROTOCOL_ENCRYPTED;
+ }
+
+#endif // ENCRYPY_PACKETS
+
+ // calculate the CRC for the whole packet and establish network byte order
+ ext_gamepacket_DEMO_PEER->crc_header = NET_CalcCRC( (void*)ext_gamepacket_DEMO_PEER, offsetof( NetPacketExternal_DEMO_PEER, crc_header ) );
+ ext_gamepacket_DEMO_PEER->crc_header = NET_SWAP_32( ext_gamepacket_DEMO_PEER->crc_header );
+
+ return pktsize;
+}
+
+
+// translate an external PEER DEMO packet to internal PEER packet. also handles 0190 packets
+//
+int NETs_HandleInPacket_DEMO( const NetPacketExternal* ext_gamepacket, NetPacket* int_gamepacket, size_t* psize_external )
+{
+ //NOTE: sets psize_external to the packetsize of the external packet
+ // ( needed for playback from compiled demos )
+
+ //NOTE: recorded packets can be in the following formats:
+ //
+ // - NetPacketExternal_DEMO_PEER_0190 = OldNetGameData ( P2P_PROTOCOL: 0.1 ) build 0190
+ // - NetPacketExternal_PEER ( P2P_PROTOCOL: 0.3 ) build >=0198
+ // - NetPacketExternal_GMSV ( GMSV_PROTOCOL: >= 0.19 ) build >=0198
+
+ ASSERT( ext_gamepacket != NULL );
+ ASSERT( int_gamepacket != NULL );
+ ASSERT( NET_ProtocolPEER() );
+
+ // check whether this is a >= 0.3 PEER packet
+ if( strncmp( ext_gamepacket->Signature, net_packet_signature_peer2peer, SIGNATURE_LEN_PEER2PEER ) == 0 ) {
+
+ NetPacket_PEER* int_gamepacket_PEER = (NetPacket_PEER*) int_gamepacket;
+ NetPacketExternal_DEMO_PEER* ext_gamepacket_DEMO_PEER = (NetPacketExternal_DEMO_PEER*) ext_gamepacket;
+
+ //NOTE:
+ // as we must ensure that the pktsize stored in the packet is not tampered
+ // with, we calculate a seperate CRC for the header in a DEMO_PEER packet
+
+ if ( !( AUX_NETCODE_FLAGS & 1 ) ) {
+
+ // calculate the CRC over the header ( does not include crc_header field itself )
+ dword crc_header = NET_CalcCRC( (void*)ext_gamepacket_DEMO_PEER, offsetof( NetPacketExternal_DEMO_PEER, crc_header ) );
+
+ // check whether CRC of header matches
+ if ( crc_header != NET_SWAP_32( ext_gamepacket_DEMO_PEER->crc_header ) ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [header CRC check failed]." ); );
+
+ // indicate, that the stored packet len cannot be trusted, as the CRC check failed, this
+ // stops replaying the demo
+ *psize_external = (size_t)-1;
+
+ return FALSE;
+ }
+ }
+
+ // get the stored length of the packet, as this can be trusted now
+ size_t ext_pktsize = NET_SWAP_32( ext_gamepacket_DEMO_PEER->pktsize );
+
+ // sanity check for packet len
+ if ( ext_pktsize > (size_t)CurMaxDataLength ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [invalid packet len]." ); );
+
+ // indicate, that the stored packet len cannot be trusted, as the CRC
+ // check failed, this stops replaying the demo
+ *psize_external = (size_t)-1;
+
+ return FALSE;
+ }
+
+ // establish host byte order
+ ext_gamepacket_DEMO_PEER->Protocol = NET_SWAP_16( ext_gamepacket_DEMO_PEER->Protocol );
+
+#ifdef ENCRYPT_PACKETS
+
+ // check whether the packet supposedly is encrypted
+ if ( ext_gamepacket_DEMO_PEER->Protocol & PROTOCOL_ENCRYPTED ) {
+
+ if ( !( AUX_NETCODE_FLAGS & 2 ) ) {
+
+ // decrypt packet payload and crc32 field
+ NET_DecryptData( &ext_gamepacket_DEMO_PEER->MessageId, ext_pktsize - offsetof( NetPacketExternal_DEMO_PEER, MessageId ) );
+ NET_DecryptData( &ext_gamepacket_DEMO_PEER->crc32, sizeof( dword ) );
+ }
+
+ // revert to decrypted protocol
+ ext_gamepacket_DEMO_PEER->Protocol &= ~PROTOCOL_ENCRYPTED;
+ }
+
+#endif // ENCRYPT_PACKETS
+
+ //NOTE:
+ // we need to return the proper packetsize, in order for CON_ACT::ExecBinCommands
+ // to know the stepsize for the next action command. thus we set it to
+ // the size stored in the DEMO packets
+ *psize_external = ext_pktsize;
+
+ if ( !( AUX_NETCODE_FLAGS & 1 ) ) {
+
+ // as the CRC for the whole packet has been calculated with the crc32
+ // and crc_header field set to zero we need to save the CRC of the packet
+ dword crc32_stored = NET_SWAP_32( ext_gamepacket_DEMO_PEER->crc32 );
+
+ // establish same format as in outgoing packet
+ ext_gamepacket_DEMO_PEER->crc32 = 0;
+ ext_gamepacket_DEMO_PEER->crc_header = 0;
+
+ // calculate CRC over packet
+ dword crc32 = NET_CalcCRC( (void*)ext_gamepacket_DEMO_PEER, ext_pktsize );
+
+ // check whether CRC is correct
+ if ( crc32 != crc32_stored ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [CRC check failed]." ); );
+ return FALSE;
+ }
+ }
+
+ // check for correct signature
+ if ( strncmp( ext_gamepacket_DEMO_PEER->Signature, net_packet_signature_peer2peer, SIGNATURE_LEN_PEER2PEER ) != 0 ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [invalid signature]." ); );
+ return FALSE;
+ }
+
+ // check for correct protocol
+ if ( ext_gamepacket_DEMO_PEER->Protocol != PROTOCOL_PEER2PEER ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [invalid protocol]." ); );
+ return FALSE;
+ }
+
+ // check for correct protocol version
+ if ( ( ext_gamepacket_DEMO_PEER->MajorVersion != P2P_PROTOCOL_MAJOR ) ||
+ ( ext_gamepacket_DEMO_PEER->MinorVersion != P2P_PROTOCOL_MINOR ) ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [incompatible protocol version]." ); );
+ return FALSE;
+ }
+
+ // convert external packet from packet byte-order to host byte-order
+ PEER_NetPacketExternal_DEMO_Swap( ext_gamepacket_DEMO_PEER, TRUE );
+
+ // determine remote event list size ( includes RE termination )
+ int_gamepacket_PEER->RE_ListSize = NET_RmEvList_GetSize(
+ (RE_Header*)&ext_gamepacket_DEMO_PEER->RE_List );
+
+ // sanety check, whether the length stored in the packet actually is correct
+ ASSERT( ext_pktsize == ( int_gamepacket_PEER->RE_ListSize +
+ sizeof( NetPacketExternal_DEMO_PEER ) - sizeof( dword ) ) );
+
+ //NOTE: we do not check the universe here
+
+ // unpack external packet data to internal packet
+ int_gamepacket_PEER->SendPlayerId = (int)ext_gamepacket_DEMO_PEER->SendPlayerId;
+ int_gamepacket_PEER->MessageId = ext_gamepacket_DEMO_PEER->MessageId;
+ int_gamepacket_PEER->Command = (int)ext_gamepacket_DEMO_PEER->Command;
+ int_gamepacket_PEER->params[ 0 ] = (int)ext_gamepacket_DEMO_PEER->param1;
+ int_gamepacket_PEER->params[ 1 ] = (int)ext_gamepacket_DEMO_PEER->param2;
+ int_gamepacket_PEER->params[ 2 ] = (int)ext_gamepacket_DEMO_PEER->param3;
+ int_gamepacket_PEER->params[ 3 ] = ext_gamepacket_DEMO_PEER->param4;
+
+ int_gamepacket_PEER->DestPlayerId = (int)ext_gamepacket_DEMO_PEER->DestPlayerId;
+ int_gamepacket_PEER->Universe = ext_gamepacket_DEMO_PEER->Universe;
+ int_gamepacket_PEER->NumPlayers = ext_gamepacket_DEMO_PEER->NumPlayers;
+ for( int nPlayer = 0; nPlayer < MAX_NET_ALLOC_SLOTS; nPlayer++ ) {
+ int_gamepacket_PEER->PlayerKills[ nPlayer ] = ext_gamepacket_DEMO_PEER->PlayerKills[ nPlayer ];
+ }
+ memcpy( &int_gamepacket_PEER->ShipInfo, &ext_gamepacket_DEMO_PEER->ShipInfo, sizeof( ShipRemInfo ) );
+ int_gamepacket_PEER->GameTime = ext_gamepacket_DEMO_PEER->GameTime;
+
+ ASSERT( ( int_gamepacket_PEER->SendPlayerId != int_gamepacket_PEER->DestPlayerId ) || ( ( int_gamepacket_PEER->Command >= PKTP_CONNECT ) && ( int_gamepacket_PEER->Command <= PKTP_SUBDUE_SLAVE ) ) );
+
+ // check whether external remote event list is well formed ( integrity and length )
+ if ( NET_RmEvList_IsWellFormed( (RE_Header*)&ext_gamepacket_DEMO_PEER->RE_List ) == FALSE ) {
+ DBGTXT( MSGOUT( "NETs_HandleInPacket_DEMO: dropped packet [invalid RE list]." ); );
+ return FALSE;
+ }
+
+ memcpy( (void*)&int_gamepacket_PEER->RE_List, (void*)&ext_gamepacket_DEMO_PEER->RE_List, int_gamepacket_PEER->RE_ListSize );
+
+ return TRUE;
+
+ } else {
+ // convert NetPacketExternal_DEMO_PEER_0190 to NetPacket_PEER
+
+ NetPacketExternal_DEMO_PEER_0190* ext_gamepacket_DEMO_PEER_0190 = (NetPacketExternal_DEMO_PEER_0190*)ext_gamepacket;
+
+ // default to nothing stripped
+ size_t pkt_stripped_size = 0;
+
+ // check whether this is a packet with the signature removed ( old compiled demos ( < 0198 ) )
+ if ( strncmp( ext_gamepacket_DEMO_PEER_0190->Signature, net_game_signature, PACKET_SIGNATURE_SIZE ) != 0 ) {
+
+#define COPY_STRIPPED_PACKET
+#ifdef COPY_STRIPPED_PACKET
+ // adjust for missing signature
+ char tempbuffer[ RECORD_PACKET_SIZE ];
+ memcpy( tempbuffer + PACKET_SIGNATURE_SIZE, ext_gamepacket_DEMO_PEER_0190, RECORD_PACKET_SIZE - PACKET_SIGNATURE_SIZE );
+ memset( tempbuffer, 0, PACKET_SIGNATURE_SIZE );
+
+ ext_gamepacket_DEMO_PEER_0190 = (NetPacketExternal_DEMO_PEER_0190*)tempbuffer;
+#else
+ //HACK: to avoid copy. this definitely has problems if ext_gamepacket_DEMO_PEER_0190 is at adress 0x00000007 or lower :)
+ ext_gamepacket_DEMO_PEER_0190 = (NetPacketExternal_DEMO_PEER_0190*) (((long)ext_gamepacket_DEMO_PEER_0190) - PACKET_SIGNATURE_SIZE);
+#endif // COPY_STRIPPED_PACKET
+
+ pkt_stripped_size = PACKET_SIGNATURE_SIZE;
+ }
+
+ //TODO: we must find some additional "typical" pattern to identify packet as NetPacketExternal_DEMO_PEER_0190 !!!
+
+ NetPacket_PEER* int_gamepacket_PEER = (NetPacket_PEER*)int_gamepacket;
+
+ // clear internal packet
+ memset( int_gamepacket_PEER, 0, NET_MAX_NETPACKET_INTERNAL_LEN );
+
+ int_gamepacket_PEER->SendPlayerId = (int) ext_gamepacket_DEMO_PEER_0190->SendPlayerId;
+ int_gamepacket_PEER->MessageId = NET_SWAP_32( ext_gamepacket_DEMO_PEER_0190->MessageId );
+ int_gamepacket_PEER->Command = (int) ext_gamepacket_DEMO_PEER_0190->Command;
+ int_gamepacket_PEER->params[ 0 ] = (int) ext_gamepacket_DEMO_PEER_0190->param1;
+ int_gamepacket_PEER->params[ 1 ] = (int) ext_gamepacket_DEMO_PEER_0190->param1;
+ int_gamepacket_PEER->params[ 2 ] = (int) ext_gamepacket_DEMO_PEER_0190->param1;
+ int_gamepacket_PEER->params[ 3 ] = (int) ext_gamepacket_DEMO_PEER_0190->param1;
+ int_gamepacket_PEER->DestPlayerId = (int) ext_gamepacket_DEMO_PEER_0190->DestPlayerId;
+ int_gamepacket_PEER->Universe = ext_gamepacket_DEMO_PEER_0190->Universe;
+ int_gamepacket_PEER->NumPlayers = ext_gamepacket_DEMO_PEER_0190->NumPlayers;
+ int_gamepacket_PEER->PlayerKills[ 0 ] = ext_gamepacket_DEMO_PEER_0190->PlayerKills[ 0 ];
+ int_gamepacket_PEER->PlayerKills[ 1 ] = ext_gamepacket_DEMO_PEER_0190->PlayerKills[ 1 ];
+ int_gamepacket_PEER->PlayerKills[ 2 ] = ext_gamepacket_DEMO_PEER_0190->PlayerKills[ 2 ];
+ int_gamepacket_PEER->PlayerKills[ 3 ] = ext_gamepacket_DEMO_PEER_0190->PlayerKills[ 3 ];
+ int_gamepacket_PEER->GameTime = NET_SWAP_32( ext_gamepacket_DEMO_PEER_0190->GameTime );
+
+ memcpy( &int_gamepacket_PEER->ShipInfo, &ext_gamepacket_DEMO_PEER_0190->ShipInfo, sizeof( ShipRemInfo ) );
+ SWAP_ShipRemInfo_in( &int_gamepacket_PEER->ShipInfo );
+
+ // RE size can be determined without swapping
+ int_gamepacket_PEER->RE_ListSize = NET_RmEvList_GetSize( (RE_Header*)&ext_gamepacket_DEMO_PEER_0190->RE_List );
+ memcpy( &int_gamepacket_PEER->RE_List, &ext_gamepacket_DEMO_PEER_0190->RE_List, int_gamepacket_PEER->RE_ListSize );
+
+ // swap RE list
+ NET_RmEvList_Swap( (RE_Header*) &int_gamepacket_PEER->RE_List, TRUE );
+
+ //TODO: check RE list with RmEvList_IsWellFormed
+
+ // replace class ids in RE_CREATEEXTRA remote events with current extra indexes
+ for( RE_Header* relist = (RE_Header*) &int_gamepacket_PEER->RE_List; relist->RE_Type != RE_EMPTY; ) {
+
+ if ( relist->RE_Type == RE_CREATEEXTRA ) {
+
+ RE_CreateExtra* re_ce = (RE_CreateExtra*) relist;
+
+ //NOTE:
+ // re_ce->ExtraIndex is actually a classid at this point
+ // packet is already in host byte-order
+
+ word classid = re_ce->ExtraIndex;
+
+ ASSERT( classid != (word)CLASS_ID_INVALID );
+ ASSERT( ObjClassExtraIndex[ classid ] != EXTRAINDEX_NO_EXTRA );
+
+ re_ce->ExtraIndex = ObjClassExtraIndex[ classid ];
+ }
+
+ // advance to next event in list
+ ASSERT( ( relist->RE_BlockSize == RE_BLOCKSIZE_INVALID ) ||
+ ( relist->RE_BlockSize == NET_RmEvGetSize( relist ) ) );
+
+ relist = (RE_Header*) ( (char*) relist + NET_RmEvGetSize( relist ) );
+ }
+
+ // size of RE list already contains the terminating RE header, also account for the missing signature
+ *psize_external = int_gamepacket_PEER->RE_ListSize + sizeof( NetPacketExternal_DEMO_PEER_0190 ) - sizeof( dword ) - pkt_stripped_size;
+
+ return TRUE;
+ }
+}
+
+
+
+// fp to which PacketInfo functions write -------------------------------------
+//
+extern FILE *dest_fp_PacketInfo;
+
+
+// write verbose packet info as comment to recording file ---------------------
+//
+void NETs_WritePacketInfo( FILE *fp, NetPacketExternal* ext_gamepacket )
+{
+ ASSERT( fp != NULL );
+ ASSERT( ext_gamepacket != NULL );
+
+ // store fp for PrInf_ functions
+ dest_fp_PacketInfo = fp;
+
+ // create packet copy and swap from network byte-order
+ NetPacketExternal_PEER* ext_gamepacket_copy = (NetPacketExternal_PEER*) ALLOCMEM( NET_MAX_DATA_LENGTH );
+ if ( ext_gamepacket_copy == NULL )
+ return;
+
+ memcpy( ext_gamepacket_copy, ext_gamepacket, NET_MAX_DATA_LENGTH );
+
+ // swap to host byte order
+ PEER_NetPacketExternal_Swap( ext_gamepacket_copy, TRUE );
+
+ NET_PacketInfo( ";-- command %d, param1=%d, param2=%d, param3=%d, param4=%d\n",
+ ext_gamepacket_copy->Command,
+ ext_gamepacket_copy->param1,
+ ext_gamepacket_copy->param2,
+ ext_gamepacket_copy->param3,
+ ext_gamepacket_copy->param4 );
+
+ NET_PacketInfo( ";-- universe=%d, numplayers=%d, srcid=%d, destid=%d\n",
+ ext_gamepacket_copy->Universe,
+ ext_gamepacket_copy->NumPlayers,
+ ext_gamepacket_copy->SendPlayerId,
+ ext_gamepacket_copy->DestPlayerId );
+
+ NET_PacketInfo( ";-- kills[0]=%d, kills[1]=%d, kills[2]=%d, kills[3]=%d\n",
+ ext_gamepacket_copy->PlayerKills[ 0 ],
+ ext_gamepacket_copy->PlayerKills[ 1 ],
+ ext_gamepacket_copy->PlayerKills[ 2 ],
+ ext_gamepacket_copy->PlayerKills[ 3 ] );
+
+ if ( CurMaxPlayers > 4 ) {
+ NET_PacketInfo( ";-- kills[4]=%d, kills[5]=%d, kills[6]=%d, kills[7]=%d\n",
+ ext_gamepacket_copy->PlayerKills[ 4 ],
+ ext_gamepacket_copy->PlayerKills[ 5 ],
+ ext_gamepacket_copy->PlayerKills[ 6 ],
+ ext_gamepacket_copy->PlayerKills[ 7 ] );
+ }
+
+ // process remote event list
+ NET_RmEvList_WriteInfo( fp, (RE_Header *) &ext_gamepacket_copy->RE_List );
+}
+
+