CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data )
{
	// DEBUG_Print( "RECEIVED SID_CHATEVENT" );
	// DEBUG_Print( data );

	// 2 bytes					-> Header
	// 2 bytes					-> Length
	// 4 bytes					-> EventID
	// 4 bytes					-> UserFlags
	// 4 bytes					-> Ping
	// 12 bytes					-> ???
	// null terminated string	-> User
	// null terminated string	-> Message

	if( ValidateLength( data ) && data.size( ) >= 29 )
	{
		BYTEARRAY EventID = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 );
		BYTEARRAY UserFlags = BYTEARRAY( data.begin( ) + 8, data.begin( ) + 12 );
		BYTEARRAY Ping = BYTEARRAY( data.begin( ) + 12, data.begin( ) + 16 );
		BYTEARRAY User = UTIL_ExtractCString( data, 28 );
		BYTEARRAY Message = UTIL_ExtractCString( data, User.size( ) + 29 );

		switch( UTIL_ByteArrayToUInt32( EventID, false ) )
		{
		case CBNETProtocol :: EID_SHOWUSER:
		case CBNETProtocol :: EID_JOIN:
		case CBNETProtocol :: EID_LEAVE:
		case CBNETProtocol :: EID_WHISPER:
		case CBNETProtocol :: EID_TALK:
		case CBNETProtocol :: EID_BROADCAST:
		case CBNETProtocol :: EID_CHANNEL:
		case CBNETProtocol :: EID_USERFLAGS:
		case CBNETProtocol :: EID_WHISPERSENT:
		case CBNETProtocol :: EID_CHANNELFULL:
		case CBNETProtocol :: EID_CHANNELDOESNOTEXIST:
		case CBNETProtocol :: EID_CHANNELRESTRICTED:
		case CBNETProtocol :: EID_INFO:
		case CBNETProtocol :: EID_ERROR:
		case CBNETProtocol :: EID_EMOTE:
			return new CIncomingChatEvent(	(CBNETProtocol :: IncomingChatEvent)UTIL_ByteArrayToUInt32( EventID, false ),
												UTIL_ByteArrayToUInt32( UserFlags, false ),
												UTIL_ByteArrayToUInt32( Ping, false ),
												string( User.begin( ), User.end( ) ),
												string( Message.begin( ), Message.end( ) ) );
		}

	}

	return NULL;
}
Example #2
0
vector<CIncomingFriendList *> CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRAY data )
{
    // DEBUG_Print( "RECEIVED SID_FRIENDSLIST" );
    // DEBUG_Print( data );

    // 2 bytes					-> Header
    // 2 bytes					-> Length
    // 1 byte					-> Total
    // for( 1 .. Total )
    //		null term string	-> Account
    //		1 byte				-> Status
    //		1 byte				-> Area
    //		4 bytes				-> ???
    //		null term string	-> Location

    vector<CIncomingFriendList *> Friends;

    if( ValidateLength( data ) && data.size( ) >= 5 )
    {
        unsigned int i = 5;
        unsigned char Total = data[4];

        while( Total > 0 )
        {
            Total--;

            if( data.size( ) < i + 1 )
                break;

            BYTEARRAY Account = UTIL_ExtractCString( data, i );
            i += Account.size( ) + 1;

            if( data.size( ) < i + 7 )
                break;

            unsigned char Status = data[i];
            unsigned char Area = data[i + 1];
            i += 6;
            BYTEARRAY Location = UTIL_ExtractCString( data, i );
            i += Location.size( ) + 1;
            Friends.push_back( new CIncomingFriendList(	string( Account.begin( ), Account.end( ) ),
                               Status,
                               Area,
                               string( Location.begin( ), Location.end( ) ) ) );
        }
    }

    return Friends;
}
Example #3
0
BYTEARRAY CBNLSProtocol :: RECEIVE_BNLS_WARDEN( BYTEARRAY data )
{
	// 2 bytes					-> Length
	// 1 byte					-> ID
	// (BYTE)					-> Usage
	// (DWORD)					-> Cookie
	// (BYTE)					-> Result
	// (WORD)					-> Length of data
	// (VOID)					-> Data

	if( ValidateLength( data ) && data.size( ) >= 11 )
	{
		unsigned char Usage = data[3];
		uint32_t Cookie = UTIL_ByteArrayToUInt32( data, false, 4 );
		unsigned char Result = data[8];
		uint16_t Length = UTIL_ByteArrayToUInt16( data, false, 10 );

		if( Result == 0x00 )
			return BYTEARRAY( data.begin( ) + 11, data.end( ) );
		else
			CONSOLE_Print( "[BNLSPROTO] received error code " + UTIL_ToString( data[8] ) );
	}

	return BYTEARRAY( );
}
Example #4
0
CIncomingGarenaUser *CGCBIProtocol :: RECEIVE_GCBI_INIT( BYTEARRAY data )
{
	// 2 bytes					-> Header
	// 2 bytes					-> Length
	// 4 bytes					-> actual IP address (big endian)
	// 4 bytes					-> Garena user ID (big endian)
	// 4 bytes					-> Garena room ID (big endian)
	// 4 bytes					-> Garena user experience (big endian)
	// 2 bytes					-> country string from Garena

	if( ValidateLength( data ) && data.size( ) == 22 )
	{
		BYTEARRAY IP = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 );
		BYTEARRAY UserID = BYTEARRAY( data.begin( ) + 8, data.begin( ) + 12 );
		BYTEARRAY RoomID = BYTEARRAY( data.begin( ) + 12, data.begin( ) + 16 );
		BYTEARRAY UserExp = BYTEARRAY( data.begin( ) + 16, data.begin( ) + 20 );
		BYTEARRAY Country = BYTEARRAY( data.begin( ) + 20, data.begin( ) + 22 );
		
		return new CIncomingGarenaUser(UTIL_ByteArrayToUInt32( IP, true ),
											UTIL_ByteArrayToUInt32( UserID, true ),
											UTIL_ByteArrayToUInt32( RoomID, true ),
											UTIL_ByteArrayToUInt32( UserExp, true ),
											string( Country.begin( ), Country.end( ) ) );
	}

	return NULL;
}
Example #5
0
void CBNLSClient :: ExtractPackets( )
{
	string *RecvBuffer = m_Socket->GetBytes( );
	BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) );

	while( Bytes.size( ) >= 3 )
	{
		uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false );

		if( Length >= 3 )
		{
			if( Bytes.size( ) >= Length )
			{
				m_Packets.push( new CCommandPacket( 0, Bytes[2], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) );
				*RecvBuffer = RecvBuffer->substr( Length );
				Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
			}
			else
				return;
		}
		else
		{
			CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] error - received invalid packet from BNLS server (bad length), disconnecting" );
			m_Socket->Disconnect( );
			return;
		}
	}
}
Example #6
0
CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRAY data )
{
    // DEBUG_Print( "RECEIVED SID_CLANMEMBERSTATUSCHANGE" );
    // DEBUG_Print( data );

    // 2 bytes					-> Header
    // 2 bytes					-> Length
    // null terminated string	-> Name
    // 1 byte					-> Rank
    // 1 byte					-> Status
    // null terminated string	-> Location

    if( ValidateLength( data ) && data.size( ) >= 5 )
    {
        BYTEARRAY Name = UTIL_ExtractCString( data, 4 );

        if( data.size( ) >= Name.size( ) + 7 )
        {
            unsigned char Rank = data[Name.size( ) + 5];
            unsigned char Status = data[Name.size( ) + 6];

            // in the original VB source the location string is read but discarded, so that's what I do here

            BYTEARRAY Location = UTIL_ExtractCString( data, Name.size( ) + 7 );
            return new CIncomingClanList(	string( Name.begin( ), Name.end( ) ),
                                            Rank,
                                            Status );
        }
    }

    return NULL;
}
Example #7
0
CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( BYTEARRAY data )
{
	// DEBUG_Print( "RECEIVED W3GS_REQJOIN" );
	// DEBUG_Print( data );

	// 2 bytes					-> Header
	// 2 bytes					-> Length
	// 4 bytes					-> Host Counter (Game ID)
	// 4 bytes					-> Entry Key (used in LAN)
	// 1 byte					-> ???
	// 2 bytes					-> Listen Port
	// 4 bytes					-> Peer Key
	// null terminated string	-> Name
	// 4 bytes					-> ???
	// 2 bytes					-> InternalPort (???)
	// 4 bytes					-> InternalIP

	if( ValidateLength( data ) && data.size( ) >= 20 )
	{
		uint32_t HostCounter = UTIL_ByteArrayToUInt32( data, false, 4 );
		BYTEARRAY Name = UTIL_ExtractCString( data, 19 );

		if( !Name.empty( ) && data.size( ) >= Name.size( ) + 30 )
		{
			BYTEARRAY InternalIP = BYTEARRAY( data.begin( ) + Name.size( ) + 26, data.begin( ) + Name.size( ) + 30 );
			return new CIncomingJoinPlayer( HostCounter, string( Name.begin( ), Name.end( ) ), InternalIP );
		}
	}

	return NULL;
}
Example #8
0
bool CPotentialPlayer :: Update( void *fd )
{
	if( m_DeleteMe )
		return true;

	if( !m_Socket )
		return false;

	m_Socket->DoRecv( (fd_set *)fd );
	
	// extract as many packets as possible from the socket's receive buffer and process them

	string *RecvBuffer = m_Socket->GetBytes( );
	BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) );

	// a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes

	while( Bytes.size( ) >= 4 )
	{
		if( Bytes[0] == W3GS_HEADER_CONSTANT || Bytes[0] == GPS_HEADER_CONSTANT )
		{
			// bytes 2 and 3 contain the length of the packet

			uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 );

			if( Length >= 4 )
			{
				if( Bytes.size( ) >= Length )
				{
                                        if( Bytes[0] == W3GS_HEADER_CONSTANT && Bytes[1] == CGameProtocol :: W3GS_REQJOIN )
                                        {
                                                delete m_IncomingJoinPlayer;
                                                m_IncomingJoinPlayer = m_Protocol->RECEIVE_W3GS_REQJOIN( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) );

                                                if( m_IncomingJoinPlayer )
                                                        m_Game->EventPlayerJoined( this, m_IncomingJoinPlayer );

                                                // this is the packet which interests us for now, the remaining is left for CGamePlayer

                                                *RecvBuffer = RecvBuffer->substr( Length );
                                                Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
                                                break;
                                        }

					*RecvBuffer = RecvBuffer->substr( Length );
					Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
				}
				else
					break;
			}
		}
	}        

	// don't call DoSend here because some other players may not have updated yet and may generate a packet for this player
	// also m_Socket may have been set to NULL during ProcessPackets but we're banking on the fact that m_DeleteMe has been set to true as well so it'll short circuit before dereferencing

	return m_DeleteMe || !m_Socket->GetConnected( ) || m_Socket->HasError( );
}
Example #9
0
void CReplay :: AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t result )
{
	BYTEARRAY Block;
	Block.push_back( REPLAY_LEAVEGAME );
	UTIL_AppendByteArray( Block, reason, false );
	Block.push_back( PID );
	UTIL_AppendByteArray( Block, result, false );
	UTIL_AppendByteArray( Block, (uint32_t)1, false );
	m_CompiledBlocks += string( Block.begin( ), Block.end( ) );
}
bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY salt, BYTEARRAY serverKey )
{
	// set m_M1

	char buf[20];
	// nls_get_M1( (nls_t *)m_nls, buf, string( serverKey.begin( ), serverKey.end( ) ).c_str( ), string( salt.begin( ), salt.end( ) ).c_str( ) );
	( (NLS *)m_NLS )->getClientSessionKey( buf, string( salt.begin( ), salt.end( ) ).c_str( ), string( serverKey.begin( ), serverKey.end( ) ).c_str( ) );
	m_M1 = UTIL_CreateByteArray( (unsigned char *)buf, 20 );
	return true;
}
Example #11
0
bool CUDPSocket :: SendTo( struct sockaddr_in sin, BYTEARRAY message )
{
	if( m_Socket == INVALID_SOCKET || m_HasError )
		return false;

	string MessageString = string( message.begin( ), message.end( ) );

	if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
		return false;

	return true;
}
Example #12
0
vector<CIncomingClanList *> CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARRAY data )
{
    // DEBUG_Print( "RECEIVED SID_CLANMEMBERLIST" );
    // DEBUG_Print( data );

    // 2 bytes					-> Header
    // 2 bytes					-> Length
    // 4 bytes					-> ???
    // 1 byte					-> Total
    // for( 1 .. Total )
    //		null term string	-> Name
    //		1 byte				-> Rank
    //		1 byte				-> Status
    //		null term string	-> Location

    vector<CIncomingClanList *> ClanList;

    if( ValidateLength( data ) && data.size( ) >= 9 )
    {
        unsigned int i = 9;
        unsigned char Total = data[8];

        while( Total > 0 )
        {
            Total--;

            if( data.size( ) < i + 1 )
                break;

            BYTEARRAY Name = UTIL_ExtractCString( data, i );
            i += Name.size( ) + 1;

            if( data.size( ) < i + 3 )
                break;

            unsigned char Rank = data[i];
            unsigned char Status = data[i + 1];
            i += 2;

            // in the original VB source the location string is read but discarded, so that's what I do here

            BYTEARRAY Location = UTIL_ExtractCString( data, i );
            i += Location.size( ) + 1;
            ClanList.push_back( new CIncomingClanList(	string( Name.begin( ), Name.end( ) ),
                                Rank,
                                Status ) );
        }
    }

    return ClanList;
}
Example #13
0
BYTEARRAY CBNETProtocol :: RECEIVE_SID_WARDEN( BYTEARRAY data )
{
    // DEBUG_Print( "RECEIVED SID_WARDEN" );
    // DEBUG_PRINT( data );

    // 2 bytes					-> Header
    // 2 bytes					-> Length
    // n bytes					-> Data

    if( ValidateLength( data ) && data.size( ) >= 4 )
        return BYTEARRAY( data.begin( ) + 4, data.end( ) );

    return BYTEARRAY( );
}
Example #14
0
void CGamePlayer :: ExtractPackets( )
{
    if( !m_Socket )
        return;

    // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue

    string *RecvBuffer = m_Socket->GetBytes( );
    BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) );

    // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes

    while( Bytes.size( ) >= 4 )
    {
        if( Bytes[0] == W3GS_HEADER_CONSTANT || Bytes[0] == GPS_HEADER_CONSTANT || Bytes[0] == GCBI_HEADER_CONSTANT )
        {
            // bytes 2 and 3 contain the length of the packet

            uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 );

            if( Length >= 4 )
            {
                if( Bytes.size( ) >= Length )
                {
                    m_Packets.push( new CCommandPacket( Bytes[0], Bytes[1], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) );

                    if( Bytes[0] == W3GS_HEADER_CONSTANT )
                        ++m_TotalPacketsReceived;

                    *RecvBuffer = RecvBuffer->substr( Length );
                    Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
                }
                else
                    return;
            }
            else
            {
                m_Error = true;
                m_ErrorString = "received invalid packet from player (bad length)";
                return;
            }
        }
        else
        {
            m_Error = true;
            m_ErrorString = "received invalid packet from player (bad header constant)";
            return;
        }
    }
}
Example #15
0
void CSaveGame :: PrepareForSave()
{
	// Custom W3Z file format type header
	// by freed

	BYTEARRAY packet;

	UTIL_AppendByteArray( packet, m_MapPath );
	UTIL_AppendByteArray( packet, customMarkFileType, true );
	UTIL_AppendByteArray( packet, m_GameName );
	UTIL_AppendByteArray( packet, customMarkFileType, true );
	UTIL_AppendByteArray( packet, customMarkFileType, true );

	UTIL_AppendByteArray( packet, (uint32_t)0, false );
	UTIL_AppendByteArray( packet, (uint32_t)0, false );
	UTIL_AppendByteArray( packet, (uint16_t)0, false );

	packet.push_back ( m_Slots.size() );

	for( unsigned char i = 0; i < m_Slots.size(); i++ )
	{
		packet.push_back( m_Slots[i].GetPID() );
		packet.push_back( m_Slots[i].GetDownloadStatus() );
		packet.push_back( m_Slots[i].GetSlotStatus() );
		packet.push_back( m_Slots[i].GetComputer() );
		packet.push_back( m_Slots[i].GetTeam() );
		packet.push_back( m_Slots[i].GetColour() );
		packet.push_back( m_Slots[i].GetRace() );
		packet.push_back( m_Slots[i].GetComputerType() );
		packet.push_back( m_Slots[i].GetHandicap() );
	}
	
	UTIL_AppendByteArray( packet, (uint32_t)m_RandomSeed, false );

	packet.push_back( 0 ); // GameType
	packet.push_back( m_PIDs.size() ); // number of player slots (non observer)

	UTIL_AppendByteArray( packet, m_MagicNumber );

	packet.push_back( m_PIDs.size() );

	for( vector<CGamePlayer*>::iterator i = m_PIDs.begin(); i != m_PIDs.end(); ++i )
	{
		packet.push_back( (*i)->GetPID() );
		UTIL_AppendByteArray( packet, (*i)->GetName(), true );
	}

    m_Decompressed = string( packet.begin( ), packet.end( ) );
}
Example #16
0
void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, string message )
{
	BYTEARRAY Block;
	Block.push_back( REPLAY_CHATMESSAGE );
	Block.push_back( PID );
	UTIL_AppendByteArray( Block, (uint16_t)0, false );
	Block.push_back( flags );
	UTIL_AppendByteArray( Block, chatMode, false );
	UTIL_AppendByteArrayFast( Block, message );

	// assign length

	BYTEARRAY LengthBytes = UTIL_CreateByteArray( (uint16_t)( Block.size( ) - 4 ), false );
	Block[2] = LengthBytes[0];
	Block[3] = LengthBytes[1];
	m_CompiledBlocks += string( Block.begin( ), Block.end( ) );
}
Example #17
0
CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data )
{
    // DEBUG_Print( "RECEIVED SID_GETADVLISTEX" );
    // DEBUG_Print( data );

    // 2 bytes					-> Header
    // 2 bytes					-> Length
    // 4 bytes					-> GamesFound
    // if( GamesFound > 0 )
    //		10 bytes			-> ???
    //		2 bytes				-> Port
    //		4 bytes				-> IP
    //		null term string	-> GameName
    //		2 bytes				-> ???
    //		8 bytes				-> HostCounter

    if( ValidateLength( data ) && data.size( ) >= 8 )
    {
        BYTEARRAY GamesFound = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 );

        if( UTIL_ByteArrayToUInt32( GamesFound, false ) > 0 && data.size( ) >= 25 )
        {
            BYTEARRAY Port = BYTEARRAY( data.begin( ) + 18, data.begin( ) + 20 );
            BYTEARRAY IP = BYTEARRAY( data.begin( ) + 20, data.begin( ) + 24 );
            BYTEARRAY GameName = UTIL_ExtractCString( data, 24 );

            if( data.size( ) >= GameName.size( ) + 35 )
            {
                BYTEARRAY HostCounter;
                HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 27, true ) );
                HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 29, true ) );
                HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 31, true ) );
                HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 33, true ) );
                return new CIncomingGameHost(	IP,
                                                UTIL_ByteArrayToUInt16( Port, false ),
                                                string( GameName.begin( ), GameName.end( ) ),
                                                HostCounter );
            }
        }
    }

    return NULL;
}
Example #18
0
void CBNET :: ExtractPackets( )
{
	// extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue
	string*		RecvBuffer	= m_Socket->GetBytes( );
	BYTEARRAY	Bytes		= UTIL_CreateByteArray( reinterpret_cast<unsigned char*>( const_cast<char*>( RecvBuffer->c_str() ) ), RecvBuffer->size() );

	// a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes
	while( Bytes.size() >= 4 )
	{
		// byte 0 is always 255
		if( Bytes[0] == BNET_HEADER_CONSTANT )
		{
			// bytes 2 and 3 contain the length of the packet

			uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 );

			if( Length >= 4 )
			{
				if( Bytes.size() >= Length )
				{
					m_Packets.push( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes[1], BYTEARRAY(Bytes.begin(), Bytes.begin() + Length) ) );
					*RecvBuffer = RecvBuffer->substr( Length );
					Bytes = BYTEARRAY( Bytes.begin() + Length, Bytes.end() );
				}
				else
					return;
			}
			else
			{
				cout << "[BNET: " << m_ServerAlias << "] error - received invalid packet from battle.net (bad length), disconnecting\n";
				m_Socket->Disconnect( );
				return;
			}
		}
		else
		{
			cout << "[BNET: " << m_ServerAlias << "] error - received invalid packet from battle.net (bad header constant), disconnecting\n";
			m_Socket->Disconnect( );
			return;
		}
	}
}
Example #19
0
bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message )
{
	if( m_Socket == INVALID_SOCKET || m_HasError )
		return false;

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = m_BroadcastTarget.s_addr;
	sin.sin_port = htons( port );

	string MessageString = string( message.begin( ), message.end( ) );

	if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
	{
		CONSOLE_Print( "[UDPSOCKET] failed to broadcast packet (port " + UTIL_ToString( port ) + ", size " + UTIL_ToString( MessageString.size( ) ) + " bytes)" );
		return false;
	}

	return true;
}
Example #20
0
void CReplay :: AddTimeSlot2( queue<CIncomingAction *> actions )
{
	BYTEARRAY Block;
	Block.push_back( REPLAY_TIMESLOT2 );
	UTIL_AppendByteArray( Block, (uint16_t)0, false );
	UTIL_AppendByteArray( Block, (uint16_t)0, false );

	while( !actions.empty( ) )
	{
		CIncomingAction *Action = actions.front( );
		actions.pop( );
		Block.push_back( Action->GetPID( ) );
		UTIL_AppendByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false );
		UTIL_AppendByteArrayFast( Block, *Action->GetAction( ) );
	}

	// assign length

	BYTEARRAY LengthBytes = UTIL_CreateByteArray( (uint16_t)( Block.size( ) - 3 ), false );
	Block[1] = LengthBytes[0];
	Block[2] = LengthBytes[1];
	m_CompiledBlocks += string( Block.begin( ), Block.end( ) );
}
Example #21
0
void CGame::SetDetials ( BYTEARRAY b )    
{
    m_details.assign( b.begin() , b.end() ); 
    m_state = STATUS_ABOUTTOSTART;
    m_lastUpdateTime = GetTime( ); 
}
Example #22
0
bool CGamePlayer :: Update( void *fd )
{
        uint32_t Time = GetTime( );
	
	// wait 4 seconds after joining before sending the /whois or /w
	// if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results

	if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.empty( ) && Time - m_JoinTime >= 4 )
	{
		// todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking

                for( vector<CBNET *> :: iterator i = m_Game->m_Aura->m_BNETs.begin( ); i != m_Game->m_Aura->m_BNETs.end( ); ++i )
		{
			if( (*i)->GetServer( ) == m_JoinedRealm )
			{
				if( m_Game->GetGameState( ) == GAME_PUBLIC || (*i)->GetPasswordHashType( ) == "pvpgn" )
					(*i)->QueueChatCommand( "/whois " + m_Name );
				else if( m_Game->GetGameState( ) == GAME_PRIVATE )
					(*i)->QueueChatCommand( m_Game->m_Aura->m_Language->SpoofCheckByReplying( ), m_Name, true, false );
			}
		}

		m_WhoisSent = true;
	}

	// check for socket timeouts
	// if we don't receive anything from a player for 35 seconds we can assume they've dropped
	// this works because in the lobby we send pings every 5 seconds and expect a response to each one
	// and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like)

	if( m_Socket && Time - m_Socket->GetLastRecv( ) >= 35 )
		m_Game->EventPlayerDisconnectTimedOut( this );

        // GProxy++ acks

	if( m_GProxy && Time - m_LastGProxyAckTime >= 10 )
	{
		if( m_Socket )
			m_Socket->PutBytes( m_Game->m_Aura->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) );

		m_LastGProxyAckTime = Time;
	}

	// base class update

        if( m_Socket->GetConnected( ) )
            m_Socket->DoRecv( (fd_set *)fd );

	// extract as many packets as possible from the socket's receive buffer and process them

	string *RecvBuffer = m_Socket->GetBytes( );
	BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) );

	// a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes

	CIncomingAction *Action = NULL;
	CIncomingChatPlayer *ChatPlayer = NULL;
	CIncomingMapSize *MapSize = NULL;
	uint32_t CheckSum = 0, Pong = 0;

	while( Bytes.size( ) >= 4 )
	{
            if( Bytes[0] == W3GS_HEADER_CONSTANT )
            {
                // bytes 2 and 3 contain the length of the packet

                uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 );

                if( Length >= 4 )
                {
                        if( Bytes.size( ) >= Length )
                        {
                                // m_Packets.push( new CCommandPacket( Bytes[0], Bytes[1], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) );

                                    switch( Bytes[1] )
                                    {
                                    case CGameProtocol :: W3GS_LEAVEGAME:
                                            m_Game->EventPlayerLeft( this, m_Protocol->RECEIVE_W3GS_LEAVEGAME( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) );
                                            break;

                                    case CGameProtocol :: W3GS_GAMELOADED_SELF:
                                            if( m_Protocol->RECEIVE_W3GS_GAMELOADED_SELF( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) )
                                            {
                                                    if( !m_FinishedLoading )
                                                    {
                                                            m_FinishedLoading = true;
                                                            m_FinishedLoadingTicks = GetTicks( );
                                                            m_Game->EventPlayerLoaded( this );
                                                    }
                                            }

                                            break;

                                    case CGameProtocol :: W3GS_OUTGOING_ACTION:
                                            Action = m_Protocol->RECEIVE_W3GS_OUTGOING_ACTION( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ), m_PID );

                                            if( Action )
                                                    m_Game->EventPlayerAction( this, Action );

                                            // don't delete Action here because the game is going to store it in a queue and delete it later

                                            break;

                                    case CGameProtocol :: W3GS_OUTGOING_KEEPALIVE:
                                            CheckSum = m_Protocol->RECEIVE_W3GS_OUTGOING_KEEPALIVE( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) );
                                            m_CheckSums.push( CheckSum );
                                            ++m_SyncCounter;
                                            m_Game->EventPlayerKeepAlive( );
                                            break;

                                    case CGameProtocol :: W3GS_CHAT_TO_HOST:
                                            ChatPlayer = m_Protocol->RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) );

                                            if( ChatPlayer )
                                                    m_Game->EventPlayerChatToHost( this, ChatPlayer );

                                            delete ChatPlayer;
                                            ChatPlayer = NULL;
                                            break;

                                    case CGameProtocol :: W3GS_DROPREQ:
                                            if( !m_DropVote )
                                            {
                                                    m_DropVote = true;
                                                    m_Game->EventPlayerDropRequest( this );
                                            }

                                            break;

                                    case CGameProtocol :: W3GS_MAPSIZE:
                                            MapSize = m_Protocol->RECEIVE_W3GS_MAPSIZE( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ), m_Game->m_Aura->m_Map->GetMapSize( ) );

                                            if( MapSize )
                                                    m_Game->EventPlayerMapSize( this, MapSize );

                                            delete MapSize;
                                            MapSize = NULL;
                                            break;

                                    case CGameProtocol :: W3GS_PONG_TO_HOST:
                                            Pong = m_Protocol->RECEIVE_W3GS_PONG_TO_HOST( BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) );

                                            // we discard pong values of 1
                                            // the client sends one of these when connecting plus we return 1 on error to kill two birds with one stone

                                            if( Pong != 1 )
                                            {
                                                    // we also discard pong values when we're downloading because they're almost certainly inaccurate
                                                    // this statement also gives the player a 5 second grace period after downloading the map to allow queued (i.e. delayed) ping packets to be ignored

                                                    if( !m_DownloadStarted || ( m_DownloadFinished && GetTime( ) - m_FinishedDownloadingTime >= 5 ) )
                                                    {
                                                            // we also discard pong values when anyone else is downloading if we're configured to

                                                            if( !m_Game->IsDownloading( ) )
                                                            {
                                                                    m_Pings.push_back( GetTicks( ) - Pong );

                                                                    if( m_Pings.size( ) > 20 )
                                                                            m_Pings.erase( m_Pings.begin( ) );
                                                            }
                                                    }
                                            }

                                            m_Game->EventPlayerPongToHost( this, Pong );
                                            break;
                                    }

                                    *RecvBuffer = RecvBuffer->substr( Length );
                                    Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
                            }
                            else
                                break;
                        }

                }
                else if( Bytes[0] == GPS_HEADER_CONSTANT )
                {
                    uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 );

                    if( Length >= 4 )
                    {
                        if( Bytes.size( ) >= Length )
                        {

                            BYTEARRAY Data = BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length );

                            if( Bytes[1] == CGPSProtocol :: GPS_ACK && Data.size( ) == 8 )
                            {
                                    uint32_t LastPacket = UTIL_ByteArrayToUInt32( Data, false, 4 );
                                    uint32_t PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( );

                                    if( LastPacket > PacketsAlreadyUnqueued )
                                    {
                                            uint32_t PacketsToUnqueue = LastPacket - PacketsAlreadyUnqueued;

                                            if( PacketsToUnqueue > m_GProxyBuffer.size( ) )
                                                    PacketsToUnqueue = m_GProxyBuffer.size( );

                                            while( PacketsToUnqueue > 0 )
                                            {
                                                    m_GProxyBuffer.pop( );
                                                    --PacketsToUnqueue;
                                            }
                                    }
                            }
                            else if( Bytes[1] == CGPSProtocol :: GPS_INIT )
                            {
                                    if( m_Game->m_Aura->m_Reconnect )
                                    {
                                            m_GProxy = true;
                                            m_Socket->PutBytes( m_Game->m_Aura->m_GPSProtocol->SEND_GPSS_INIT( m_Game->m_Aura->m_ReconnectPort, m_PID, m_GProxyReconnectKey, m_Game->GetGProxyEmptyActions( ) ) );
                                            Print( "[GAME: " + m_Game->GetGameName( ) + "] player [" + m_Name + "] is using GProxy++" );
                                    }
                            }

                            *RecvBuffer = RecvBuffer->substr( Length );
                            Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
                        }
                        else
                            break;
                    }
            }
        }

        bool Deleting;

	if( m_GProxy && m_Game->GetGameLoaded( ) )
		Deleting = m_DeleteMe;
	else
		Deleting = m_DeleteMe || m_Socket->HasError( ) || !m_Socket->GetConnected( );

	// try to find out why we're requesting deletion
	// in cases other than the ones covered here m_LeftReason should have been set when m_DeleteMe was set	

	if( m_Socket )
	{
		if( m_Socket->HasError( ) )
		{
			m_Game->EventPlayerDisconnectSocketError( this );
			m_Socket->Reset( );
		}
		else if( !m_Socket->GetConnected( ) )
		{
			m_Game->EventPlayerDisconnectConnectionClosed( this );
			m_Socket->Reset( );
		}
	}

	return Deleting;
}
Example #23
0
void CReplay :: BuildReplay( string gameName, string statString, uint32_t war3Version, uint16_t buildNumber )
{
	m_War3Version = war3Version;
	m_BuildNumber = buildNumber;
	m_Flags = 32768;

	CONSOLE_Print( "[REPLAY] building replay" );

	uint32_t LanguageID = 0x0012F8B0;

	BYTEARRAY Replay;
	Replay.push_back( 16 );															// Unknown (4.0)
	Replay.push_back( 1 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Host RecordID (4.1)
	Replay.push_back( m_HostPID );													// Host PlayerID (4.1)
	UTIL_AppendByteArrayFast( Replay, m_HostName );									// Host PlayerName (4.1)
	Replay.push_back( 1 );															// Host AdditionalSize (4.1)
	Replay.push_back( 0 );															// Host AdditionalData (4.1)
	UTIL_AppendByteArrayFast( Replay, gameName );									// GameName (4.2)
	Replay.push_back( 0 );															// Null (4.0)
	UTIL_AppendByteArrayFast( Replay, statString );									// StatString (4.3)
	UTIL_AppendByteArray( Replay, (uint32_t)m_Slots.size( ), false );				// PlayerCount (4.6)
	Replay.push_back( m_MapGameType );												// GameType (4.7)
	Replay.push_back( 32 );															// GameType (4.7)
	Replay.push_back( 73 );															// GameType (4.7)
	Replay.push_back( 0 );															// GameType (4.7)
	UTIL_AppendByteArray( Replay, LanguageID, false );								// LanguageID (4.8)

	// PlayerList (4.9)

	for( vector<PIDPlayer> :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ )
	{
		if( (*i).first != m_HostPID )
		{
			Replay.push_back( 22 );													// Player RecordID (4.1)
			Replay.push_back( (*i).first );											// Player PlayerID (4.1)
			UTIL_AppendByteArrayFast( Replay, (*i).second );						// Player PlayerName (4.1)
			Replay.push_back( 1 );													// Player AdditionalSize (4.1)
			Replay.push_back( 0 );													// Player AdditionalData (4.1)
			UTIL_AppendByteArray( Replay, (uint32_t)0, false );						// Unknown
		}
	}

	// GameStartRecord (4.10)

	Replay.push_back( 25 );															// RecordID (4.10)
	UTIL_AppendByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false );	// Size (4.10)
	Replay.push_back( m_Slots.size( ) );											// NumSlots (4.10)

	for( unsigned char i = 0; i < m_Slots.size( ); i++ )
		UTIL_AppendByteArray( Replay, m_Slots[i].GetByteArray( ) );

	UTIL_AppendByteArray( Replay, m_RandomSeed, false );							// RandomSeed (4.10)
	Replay.push_back( m_SelectMode );												// SelectMode (4.10)
	Replay.push_back( m_StartSpotCount );											// StartSpotCount (4.10)

	// ReplayData (5.0)

	Replay.push_back( REPLAY_FIRSTSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );
	Replay.push_back( REPLAY_SECONDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// leavers during loading need to be stored between the second and third start blocks

	while( !m_LoadingBlocks.empty( ) )
	{
		UTIL_AppendByteArray( Replay, m_LoadingBlocks.front( ) );
		m_LoadingBlocks.pop( );
	}

	Replay.push_back( REPLAY_THIRDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// initialize replay length to zero
	// we'll accumulate the replay length as we iterate through the timeslots
	// this is necessary because we might be discarding some timeslots due to not enough checksums and the replay length needs to be accurate

	m_ReplayLength = 0;
	uint32_t TimeSlotsDiscarded = 0;
	bool EndOfTimeSlots = false;

	while( !m_Blocks.empty( ) )
	{
		BYTEARRAY Block = m_Blocks.front( );
		m_Blocks.pop( );

		if( Block.size( ) >= 5 && Block[0] == REPLAY_TIMESLOT )
		{
			uint16_t TimeIncrement = UTIL_ByteArrayToUInt16( Block, false, 3 );

			if( TimeIncrement != 0 && m_CheckSums.empty( ) )
				EndOfTimeSlots = true;

			if( EndOfTimeSlots )
			{
				TimeSlotsDiscarded++;
				continue;
			}

			// append timeslot

			UTIL_AppendByteArrayFast( Replay, Block );

			// append checksum
			// todotodo: after experimenting, Strilanc discovered that checksums are NOT required in replays
			// we could optimize saving of replays by building a complete stream without waiting for checksums as the game progresses
			// alternatively, we could build that stream as the checksums were added if we wanted to keep them
			// rather than building it in one go right now, which might take a few hundred ms and cause a spike in other games

			if( TimeIncrement != 0 )
			{
				BYTEARRAY CheckSum;
				CheckSum.reserve( 6 );
				CheckSum.push_back( REPLAY_CHECKSUM );
				CheckSum.push_back( 4 );
				UTIL_AppendByteArray( CheckSum, m_CheckSums.front( ), false );
				m_CheckSums.pop( );
				UTIL_AppendByteArrayFast( Replay, CheckSum );
			}

			// accumulate replay length

			m_ReplayLength += TimeIncrement;
		}
		else
			UTIL_AppendByteArrayFast( Replay, Block );
	}

	if( TimeSlotsDiscarded > 0 )
		CONSOLE_Print( "[REPLAY] ran out of checksums, discarded " + UTIL_ToString( TimeSlotsDiscarded ) + " timeslots" );

	// done

	m_Decompressed = string( Replay.begin( ), Replay.end( ) );
}
Example #24
0
BYTEARRAY CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue<CIncomingAction *> actions )
{
	BYTEARRAY packet;
	packet.push_back( W3GS_HEADER_CONSTANT );				// W3GS header constant
	packet.push_back( W3GS_INCOMING_ACTION2 );				// W3GS_INCOMING_ACTION2
	packet.push_back( 0 );									// packet length will be assigned later
	packet.push_back( 0 );									// packet length will be assigned later
	packet.push_back( 0 );									// ??? (send interval?)
	packet.push_back( 0 );									// ??? (send interval?)

	// create subpacket

	if( !actions.empty( ) )
	{
		BYTEARRAY subpacket;

		while( !actions.empty( ) )
		{
			CIncomingAction *Action = actions.front( );
			actions.pop( );
			subpacket.push_back( Action->GetPID( ) );
			UTIL_AppendByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false );
			UTIL_AppendByteArrayFast( subpacket, *Action->GetAction( ) );
		}

		// calculate crc (we only care about the first 2 bytes though)

		BYTEARRAY crc32 = UTIL_CreateByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)string( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false );
		crc32.resize( 2 );

		// finish subpacket

		UTIL_AppendByteArrayFast( packet, crc32 );			// crc
		UTIL_AppendByteArrayFast( packet, subpacket );		// subpacket
	}

	AssignLength( packet );
	// DEBUG_Print( "SENT W3GS_INCOMING_ACTION2" );
	// DEBUG_Print( packet );
	return packet;
}
Example #25
0
void CReplay :: BuildReplay( string gameName, string statString )
{
	CONSOLE_Print( "[REPLAY] building replay" );

	uint32_t LanguageID = 0x0012F8B0;

	BYTEARRAY Replay;
	Replay.push_back( 16 );															// Unknown (4.0)
	Replay.push_back( 1 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Host RecordID (4.1)
	Replay.push_back( m_HostPID );													// Host PlayerID (4.1)
	UTIL_AppendByteArray( Replay, m_HostName );										// Host PlayerName (4.1)
	Replay.push_back( 1 );															// Host AdditionalSize (4.1)
	Replay.push_back( 0 );															// Host AdditionalData (4.1)
	UTIL_AppendByteArray( Replay, gameName );										// GameName (4.2)
	Replay.push_back( 0 );															// Null (4.0)
	UTIL_AppendByteArray( Replay, statString );										// StatString (4.3)
	UTIL_AppendByteArray( Replay, (uint32_t)m_Slots.size( ), false );				// PlayerCount (4.6)
	Replay.push_back( m_MapGameType );												// GameType (4.7)
	Replay.push_back( 32 );															// GameType (4.7)
	Replay.push_back( 73 );															// GameType (4.7)
	Replay.push_back( 0 );															// GameType (4.7)
	UTIL_AppendByteArray( Replay, LanguageID, false );								// LanguageID (4.8)

	// PlayerList (4.9)

	for( vector<ReplayPlayer> :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ )
	{
		if( (*i).first != m_HostPID )
		{
			Replay.push_back( 22 );													// Player RecordID (4.1)
			Replay.push_back( (*i).first );											// Player PlayerID (4.1)
			UTIL_AppendByteArray( Replay, (*i).second );							// Player PlayerName (4.1)
			Replay.push_back( 1 );													// Player AdditionalSize (4.1)
			Replay.push_back( 0 );													// Player AdditionalData (4.1)
			UTIL_AppendByteArray( Replay, (uint32_t)0, false );						// Unknown
		}
	}

	// GameStartRecord (4.10)

	Replay.push_back( 25 );															// RecordID (4.10)
	UTIL_AppendByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false );	// Size (4.10)
	Replay.push_back( m_Slots.size( ) );											// NumSlots (4.10)

	for( unsigned char i = 0; i < m_Slots.size( ); i++ )
		UTIL_AppendByteArray( Replay, m_Slots[i].GetByteArray( ) );

	UTIL_AppendByteArray( Replay, m_RandomSeed, false );							// RandomSeed (4.10)
	Replay.push_back( m_SelectMode );												// SelectMode (4.10)
	Replay.push_back( m_StartSpotCount );											// StartSpotCount (4.10)

	// ReplayData (5.0)

	Replay.push_back( REPLAY_FIRSTSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );
	Replay.push_back( REPLAY_SECONDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// leavers during loading need to be stored between the second and third start blocks

	while( !m_LoadingBlocks.empty( ) )
	{
		UTIL_AppendByteArray( Replay, m_LoadingBlocks.front( ) );
		m_LoadingBlocks.pop( );
	}

	Replay.push_back( REPLAY_THIRDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// initialize replay length to zero
	// we'll accumulate the replay length as we iterate through the timeslots
	// this is necessary because we might be discarding some timeslots due to not enough checksums and the replay length needs to be accurate

	m_ReplayLength = 0;
	uint32_t TimeSlotsDiscarded = 0;

	while( !m_Blocks.empty( ) )
	{
		BYTEARRAY Block = m_Blocks.front( );
		m_Blocks.pop( );

		if( Block.size( ) >= 5 && Block[0] == REPLAY_TIMESLOT )
		{
			if( m_CheckSums.empty( ) )
			{
				TimeSlotsDiscarded++;
				continue;
			}

			// append timeslot

			UTIL_AppendByteArray( Replay, Block );

			// append checksum

			BYTEARRAY CheckSum;
			CheckSum.push_back( REPLAY_CHECKSUM );
			CheckSum.push_back( 4 );
			UTIL_AppendByteArray( CheckSum, m_CheckSums.front( ), false );
			m_CheckSums.pop( );
			UTIL_AppendByteArray( Replay, CheckSum );

			// accumulate replay length

			m_ReplayLength += UTIL_ByteArrayToUInt16( Block, false, 3 );
		}
		else
			UTIL_AppendByteArray( Replay, Block );
	}

	if( TimeSlotsDiscarded > 0 )
		CONSOLE_Print( "[REPLAY] ran out of checksums, discarded " + UTIL_ToString( TimeSlotsDiscarded ) + " timeslots" );

	// done

	m_Decompressed = string( Replay.begin( ), Replay.end( ) );
}
Example #26
0
CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data )
{
	// DEBUG_Print( "RECEIVED W3GS_CHAT_TO_HOST" );
	// DEBUG_Print( data );

	// 2 bytes					-> Header
	// 2 bytes					-> Length
	// 1 byte					-> Total
	// for( 1 .. Total )
	//		1 byte				-> ToPID
	// 1 byte					-> FromPID
	// 1 byte					-> Flag
	// if( Flag == 16 )
	//		null term string	-> Message
	// elseif( Flag == 17 )
	//		1 byte				-> Team
	// elseif( Flag == 18 )
	//		1 byte				-> Colour
	// elseif( Flag == 19 )
	//		1 byte				-> Race
	// elseif( Flag == 20 )
	//		1 byte				-> Handicap
	// elseif( Flag == 32 )
	//		4 bytes				-> ExtraFlags
	//		null term string	-> Message

	if( ValidateLength( data ) )
	{
		unsigned int i = 5;
		unsigned char Total = data[4];

		if( Total > 0 && data.size( ) >= i + Total )
		{
			BYTEARRAY ToPIDs = BYTEARRAY( data.begin( ) + i, data.begin( ) + i + Total );
			i += Total;
			unsigned char FromPID = data[i];
			unsigned char Flag = data[i + 1];
			i += 2;

			if( Flag == 16 && data.size( ) >= i + 1 )
			{
				// chat message

				BYTEARRAY Message = UTIL_ExtractCString( data, i );
				return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, string( Message.begin( ), Message.end( ) ) );
			}
			else if( ( Flag >= 17 && Flag <= 20 ) && data.size( ) >= i + 1 )
			{
				// team/colour/race/handicap change request

				unsigned char Byte = data[i];
				return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, Byte );
			}
			else if( Flag == 32 && data.size( ) >= i + 5 )
			{
				// chat message with extra flags

				BYTEARRAY ExtraFlags = BYTEARRAY( data.begin( ) + i, data.begin( ) + i + 4 );
				BYTEARRAY Message = UTIL_ExtractCString( data, i + 4 );
				return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, string( Message.begin( ), Message.end( ) ), ExtraFlags );
			}
		}
	}

	return NULL;
}
Example #27
0
void CReplay :: BuildReplay( string gameName, string statString, uint32_t war3Version, uint16_t buildNumber )
{
	m_War3Version = war3Version;
	m_BuildNumber = buildNumber;
	m_Flags = 32768;

	CONSOLE_Print( "[REPLAY] building replay" );

	uint32_t LanguageID = 0x0012F8B0;

	BYTEARRAY Replay;
	Replay.push_back( 16 );															// Unknown (4.0)
	Replay.push_back( 1 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Host RecordID (4.1)
	Replay.push_back( m_HostPID );													// Host PlayerID (4.1)
	UTIL_AppendByteArrayFast( Replay, m_HostName );									// Host PlayerName (4.1)
	Replay.push_back( 1 );															// Host AdditionalSize (4.1)
	Replay.push_back( 0 );															// Host AdditionalData (4.1)
	UTIL_AppendByteArrayFast( Replay, gameName );									// GameName (4.2)
	Replay.push_back( 0 );															// Null (4.0)
	UTIL_AppendByteArrayFast( Replay, statString );									// StatString (4.3)
	UTIL_AppendByteArray( Replay, (uint32_t)m_Slots.size( ), false );				// PlayerCount (4.6)
	UTIL_AppendByteArray( Replay, m_MapGameType, false );							// GameType (4.7)
	UTIL_AppendByteArray( Replay, LanguageID, false );								// LanguageID (4.8)

	// PlayerList (4.9)

        for( vector<PIDPlayer> :: iterator i = m_Players.begin( ); i != m_Players.end( ); ++i )
	{
		if( (*i).first != m_HostPID )
		{
			Replay.push_back( 22 );													// Player RecordID (4.1)
			Replay.push_back( (*i).first );											// Player PlayerID (4.1)
			UTIL_AppendByteArrayFast( Replay, (*i).second );						// Player PlayerName (4.1)
			Replay.push_back( 1 );													// Player AdditionalSize (4.1)
			Replay.push_back( 0 );													// Player AdditionalData (4.1)
			UTIL_AppendByteArray( Replay, (uint32_t)0, false );						// Unknown
		}
	}

	// GameStartRecord (4.10)

	Replay.push_back( 25 );															// RecordID (4.10)
	UTIL_AppendByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false );	// Size (4.10)
	Replay.push_back( m_Slots.size( ) );											// NumSlots (4.10)

        for( unsigned char i = 0; i < m_Slots.size( ); ++i )
		UTIL_AppendByteArray( Replay, m_Slots[i].GetByteArray( ) );

	UTIL_AppendByteArray( Replay, m_RandomSeed, false );							// RandomSeed (4.10)
	Replay.push_back( m_SelectMode );												// SelectMode (4.10)
	Replay.push_back( m_StartSpotCount );											// StartSpotCount (4.10)

	// ReplayData (5.0)

	Replay.push_back( REPLAY_FIRSTSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );
	Replay.push_back( REPLAY_SECONDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// leavers during loading need to be stored between the second and third start blocks

	while( !m_LoadingBlocks.empty( ) )
	{
		UTIL_AppendByteArray( Replay, m_LoadingBlocks.front( ) );
		m_LoadingBlocks.pop( );
	}

	Replay.push_back( REPLAY_THIRDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// done

	m_Decompressed = string( Replay.begin( ), Replay.end( ) );
	m_Decompressed += m_CompiledBlocks;
}
Example #28
0
void CTCPSocket :: PutBytes( BYTEARRAY bytes )
{
	m_SendBuffer += string( bytes.begin( ), bytes.end( ) );
}
CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data )
{
	// DEBUG_Print( "RECEIVED SID_GETADVLISTEX" );
	// DEBUG_Print( data );

	// 2 bytes					-> Header
	// 2 bytes					-> Length
	// 4 bytes					-> GamesFound
	// if( GamesFound > 0 )
	//		10 bytes			-> ???
	//		2 bytes				-> Port
	//		4 bytes				-> IP
	//		null term string	-> GameName
	//		2 bytes				-> ???
	//		8 bytes				-> HostCounter

	if( ValidateLength( data ) && data.size( ) >= 8 )
	{
		BYTEARRAY GamesFound = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 );

/*
		if (UTIL_ByteArrayToUInt32( GamesFound, false )>1)
		{
			string sIP ="";
			string GN ="";
			uint32_t PR;
			uint32_t GF = UTIL_ByteArrayToUInt32( GamesFound, false );
			uint32_t Idx = 18;
			uint32_t Idx2 = 0;
			for (uint32_t i=0;i<GF;i++)
			{
				BYTEARRAY Port = BYTEARRAY( data.begin( ) + Idx, data.begin( ) + 2+Idx );
				BYTEARRAY IP = BYTEARRAY( data.begin( ) + 2+Idx, data.begin( ) + 6+Idx );
				BYTEARRAY GameName = UTIL_ExtractCString( data, 6+Idx );
				Idx2 = GameName.size( );
				Idx = Idx + Idx2+ 11;	
				GN = string( GameName.begin( ), GameName.end( ) );
				PR = UTIL_ByteArrayToUInt16( Port, false );
				CONSOLE_Print("[GHOST] Game "+UTIL_ToString(i)+ " "+ GN + " "+sIP+" "+UTIL_ToString(PR));
			}
		} 
		else
*/
		if( UTIL_ByteArrayToUInt32( GamesFound, false ) > 0 && data.size( ) >= 25 )
		{
			BYTEARRAY Port = BYTEARRAY( data.begin( ) + 18, data.begin( ) + 20 );
			BYTEARRAY IP = BYTEARRAY( data.begin( ) + 20, data.begin( ) + 24 );
			BYTEARRAY GameName = UTIL_ExtractCString( data, 24 );

			if( data.size( ) >= GameName.size( ) + 35 )
			{
				BYTEARRAY HostCounter;
				HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 27, true ) );
				HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 29, true ) );
				HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 31, true ) );
				HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 33, true ) );
				return new CIncomingGameHost(	IP,
												UTIL_ByteArrayToUInt16( Port, false ),
												string( GameName.begin( ), GameName.end( ) ),
												HostCounter );
			}
		}
	}

	return NULL;
}
Example #30
0
void CGame::SetStartHead ( BYTEARRAY b )    
{ 
    m_startHead.assign( b.begin() , b.end() ); 
    m_state = STATUS_STARTED;
    m_lastUpdateTime = GetTime( ); 
}