Exemplo n.º 1
0
CDeltaCalculator::CDeltaCalculator(
	CSendTablePrecalc *pPrecalc,
	const void *pFromState,
	const int nFromBits,
	const void *pToState,
	const int nToBits,
	int *pDeltaProps,
	int nMaxDeltaProps,
	const int objectID ) 
	
	: m_bfFromState( "CDeltaCalculator->m_bfFromState", pFromState, Bits2Bytes( nFromBits ), nFromBits ),
	m_FromBitsReader( &m_bfFromState ),
	m_bfToState( "CDeltaCalculator->m_bfToState", pToState, Bits2Bytes( nToBits ), nToBits ),
	m_ToBitsReader( &m_bfToState )
{
	m_pPrecalc = pPrecalc;
	m_ObjectID = objectID;

	m_pDeltaProps = pDeltaProps;
	m_nMaxDeltaProps = nMaxDeltaProps;
	m_nDeltaProps = 0;
	
	// Walk through each property in the to state, looking for ones in the from 
	// state that are missing or that are different.
	if ( pFromState)
	{
		m_iFromProp = NextProp( &m_FromBitsReader );
	}
	else
	{
		m_iFromProp = PROP_SENTINEL;
	}
	
	m_iToProp = -1;
}
Exemplo n.º 2
0
void yxyDES2::DecryptData(char* _srcBytes,unsigned int keyN)
{
	char szSrcBits[64] = {0};
	char sz_IP[64] = {0};
	char sz_Li[32] = {0};
	char sz_Ri[32] = {0};
	char sz_Final64[64] = {0};
	Bytes2Bits(_srcBytes,szSrcBits,64);
	//IP --- return is sz_IP
	InitialPermuteData(szSrcBits,sz_IP);
	//divide the 64 bits data to two parts
	memcpy(sz_Ri,sz_IP,32); //exchange L to R
	memcpy(sz_Li,sz_IP + 32,32);  //exchange R to L
	//16 rounds F and xor and exchange
	for(int i=0;i<16;i++)
	{
		FunctionF(sz_Ri,sz_Li,15-i,keyN);
	}
	memcpy(sz_Final64,sz_Li,32);
	memcpy(sz_Final64 + 32,sz_Ri,32);
	// ~IP
	for(int j=0;j<64;j++)
	{
		szPlaintextRaw[j] = sz_Final64[IPR_Table[j]-1];
	}
	Bits2Bytes(szPlaintextInBytes,szPlaintextRaw,64);
}
Exemplo n.º 3
0
void yxyDES2::EncryptData(char* _srcBytes,unsigned int keyN)
{
	char szSrcBits[64] = {0};
	char sz_IP[64] = {0};
	char sz_Li[32] = {0};
	char sz_Ri[32] = {0};
	char sz_Final64[64] = {0};

	Bytes2Bits(_srcBytes,szSrcBits,64);
	//IP
	InitialPermuteData(szSrcBits,sz_IP);
	memcpy(sz_Li,sz_IP,32);
	memcpy(sz_Ri,sz_IP + 32,32);

	for(int i=0;i<16;i++)
	{
		FunctionF(sz_Li,sz_Ri,i,keyN);
	}
	//so D=LR

	memcpy(sz_Final64,sz_Ri,32);
	memcpy(sz_Final64 + 32,sz_Li,32);

	//~IP
	for(int j=0;j<64;j++)
	{
		szCiphertextRaw[j] = sz_Final64[IPR_Table[j]-1];
	}
	Bits2Bytes(szCiphertextInBytes,szCiphertextRaw,64);
}
bool CHLTVClientState::ProcessVoiceData( SVC_VoiceData *msg )
{
	int	 size = PAD_NUMBER( Bits2Bytes(msg->m_nLength), 4);
	byte *buffer = (byte*) stackalloc( size );
	msg->m_DataIn.ReadBits( buffer, msg->m_nLength );
	msg->m_DataOut = buffer;

	return m_pHLTV->SendNetMsg( *msg ); // relay to server
}
Exemplo n.º 5
0
bool CGameClient::ProcessVoiceData( CLC_VoiceData *msg )
{
	char voiceDataBuffer[4096];

	msg->m_DataIn.ReadBits( voiceDataBuffer, msg->m_nLength );

	SV_BroadcastVoiceData( this, Bits2Bytes(msg->m_nLength), voiceDataBuffer, msg->m_xuid ); // length is in bits

	return true;
}
Exemplo n.º 6
0
//-----------------------------------------------------------------------------
// Purpose: check integrity of an unpacked entity send table
//-----------------------------------------------------------------------------
bool SendTable_CheckIntegrity( SendTable *pTable, const void *pData, const int nDataBits )
{
#ifdef _DEBUG
	if ( pData == NULL && nDataBits == 0 )
		return true;

	bf_read bfRead(	"SendTable_CheckIntegrity", pData, Bits2Bytes(nDataBits), nDataBits );
	CDeltaBitsReader bitsReader( &bfRead );

	int iProp = PROP_SENTINEL;
	int iLastProp = -1;
	int nMaxProps = pTable->m_pPrecalc->GetNumProps();
	int nPropCount = 0;

	Assert( nMaxProps > 0 && nMaxProps < MAX_DATATABLE_PROPS );

	while( -1 != (iProp = bitsReader.ReadNextPropIndex()) )
	{
		Assert( (iProp>=0) && (iProp<nMaxProps) );

		// must be larger
		Assert( iProp > iLastProp );

		const SendProp *pProp = pTable->m_pPrecalc->GetProp( iProp );

		Assert( pProp );

		// ok check that SkipProp & IsEncodedZero read the same bit length
		int iStartBit = bfRead.GetNumBitsRead();
		g_PropTypeFns[ pProp->GetType() ].SkipProp( pProp, &bfRead );
		int nLength = bfRead.GetNumBitsRead() - iStartBit;

		Assert( nLength > 0 ); // a prop must have some bits

		bfRead.Seek( iStartBit ); // read it again

		g_PropTypeFns[ pProp->GetType() ].IsEncodedZero( pProp, &bfRead );

		Assert( nLength == (bfRead.GetNumBitsRead() - iStartBit) ); 

		nPropCount++;
		iLastProp = iProp;
	}

	Assert( nPropCount <= nMaxProps );
	Assert( bfRead.GetNumBytesLeft() < 4 ); 
	Assert( !bfRead.IsOverflowed() );

#endif

	return true;
}
bool CClientState::ProcessUserMessage(SVC_UserMessage *msg)
{
	// buffer for incoming user message
	byte userdata[ MAX_USER_MSG_DATA ] = { 0 };
	bf_read userMsg( "UserMessage(read)", userdata, sizeof( userdata ) );
	msg->m_DataIn.ReadBits( userdata, msg->m_nLength );
	userMsg.StartReading( userdata, Bits2Bytes( msg->m_nLength ) );

	// dispatch message to client.dll
	if ( !g_ClientDLL->DispatchUserMessage( msg->m_nMsgType, userMsg ) )
	{
		ConMsg( "Couldn't dispatch user message (%i)\n", msg->m_nMsgType );
		return false;
	}

	return true;
}
Exemplo n.º 8
0
void yxDES::DecryptData(char* _srcBytes,unsigned int keyN)
{
	char temp[8];
	char tempszivRev[8];
	memset(temp,0x0,8);
	memset(tempszivRev,0x0,8);
	if(1 == m_iMode)//cbc
	{
		memcpy(tempszivRev,_srcBytes,8);
	}
	
	char szSrcBits[64] = {0};
	char sz_IP[64] = {0};
	char sz_Li[32] = {0};
	char sz_Ri[32] = {0};
	char sz_Final64[64] = {0};
	Bytes2Bits(_srcBytes,szSrcBits,64);
	//IP --- return is sz_IP
	InitialPermuteData(szSrcBits,sz_IP);
	//divide the 64 bits data to two parts
	memcpy(sz_Ri,sz_IP,32); //exchange L to R
	memcpy(sz_Li,sz_IP + 32,32);  //exchange R to L
	//16 rounds F and xor and exchange
	for(int i=0;i<16;i++)
	{
		FunctionF(sz_Ri,sz_Li,15-i,keyN);
	}
	memcpy(sz_Final64,sz_Li,32);
	memcpy(sz_Final64 + 32,sz_Ri,32);
	// ~IP
	for(int j=0;j<64;j++)
	{
		szPlaintextRaw[j] = sz_Final64[IPR_Table[j]-1];
	}
	Bits2Bytes(szPlaintextInBytes,szPlaintextRaw,64);
	if(1 == m_iMode)//cbc
	{
		XOR(szPlaintextInBytes,szivRev,8,temp);
		memcpy(szPlaintextInBytes,temp,8);
		memcpy(szivRev,tempszivRev,8);
	}
	
}
Exemplo n.º 9
0
void yxDES::EncryptData(char* _srcBytes,unsigned int keyN)
{
	char temp[8];
	memset(temp,0x0,8);
	if(1 == m_iMode)//cbc
	{
		XOR(_srcBytes,sziv,8,temp);
		memcpy(_srcBytes,temp,8);
	}
	
	char szSrcBits[64] = {0};
	char sz_IP[64] = {0};
	char sz_Li[32] = {0};
	char sz_Ri[32] = {0};
	char sz_Final64[64] = {0};

	Bytes2Bits(_srcBytes,szSrcBits,64);
	//IP
	InitialPermuteData(szSrcBits,sz_IP);
	memcpy(sz_Li,sz_IP,32);
	memcpy(sz_Ri,sz_IP + 32,32);

	for(int i=0;i<16;i++)
	{
		FunctionF(sz_Li,sz_Ri,i,keyN);
	}
	//so D=LR

	memcpy(sz_Final64,sz_Ri,32);
	memcpy(sz_Final64 + 32,sz_Li,32);

	//~IP
	for(int j=0;j<64;j++)
	{
		szCiphertextRaw[j] = sz_Final64[IPR_Table[j]-1];
	}
	Bits2Bytes(szCiphertextInBytes,szCiphertextRaw,64);
	if(1 == m_iMode)//cbc
	{
		memcpy(sziv,szCiphertextInBytes,8);
	}
}
Exemplo n.º 10
0
bool CClientState::ProcessEntityMessage(SVC_EntityMessage *msg)
{
	// Look up entity
	IClientNetworkable *entity = entitylist->GetClientNetworkable( msg->m_nEntityIndex );

	if ( !entity )
	{
		// message was send to use, even we don't have this entity TODO change that on server side
		return true;
	}

	// route to entity 
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	// buffer for incoming user message
	byte entityData[ MAX_ENTITY_MSG_DATA ] = { 0 };
	bf_read entMsg( "EntityMessage(read)", entityData, sizeof( entityData ) );
	msg->m_DataIn.ReadBits( entityData, msg->m_nLength );
	entMsg.StartReading( entityData, Bits2Bytes( msg->m_nLength ) );

	entity->ReceiveMessage( msg->m_nClassID, entMsg );

	return true;
}
Exemplo n.º 11
0
void CHLTVClientState::CopyNewEntity( 
	CEntityReadInfo &u,
	int iClass,
	int iSerialNum
	)
{
	ServerClass *pServerClass = SV_FindServerClass( iClass );
	Assert( pServerClass );
	
	ClientClass *pClientClass = GetClientClass( iClass );
	Assert( pClientClass );

	const int ent = u.m_nNewEntity;

	// copy class & serial
	CFrameSnapshot *pSnapshot = u.m_pTo->GetSnapshot();
	pSnapshot->m_pEntities[ent].m_nSerialNumber = iSerialNum;
	pSnapshot->m_pEntities[ent].m_pClass = pServerClass;

	// Get either the static or instance baseline.
	const void *pFromData = NULL;
	int nFromBits = 0;
	int nFromTick = 0;	// MOTODO get tick when baseline last changed

	PackedEntity *baseline = u.m_bAsDelta ? GetEntityBaseline( u.m_nBaseline, ent ) : NULL;

	if ( baseline && baseline->m_pClientClass == pClientClass )
	{
		Assert( !baseline->IsCompressed() );
		pFromData = baseline->GetData();
		nFromBits = baseline->GetNumBits();
	}
	else
	{
		// Every entity must have a static or an instance baseline when we get here.
		ErrorIfNot(
			GetClassBaseline( iClass, &pFromData, &nFromBits ),
			("HLTV_CopyNewEntity: GetDynamicBaseline(%d) failed.", iClass)
		);
		nFromBits *= 8; // convert to bits
	}

	// create new ChangeFrameList containing all properties set as changed
	int nFlatProps = SendTable_GetNumFlatProps( pServerClass->m_pTable );
	IChangeFrameList *pChangeFrame = NULL;
	
	if ( !m_bSaveMemory )
	{
		pChangeFrame = AllocChangeFrameList( nFlatProps, nFromTick );
	}

	// Now make a PackedEntity and store the new packed data in there.
	PackedEntity *pPackedEntity = framesnapshotmanager->CreatePackedEntity( pSnapshot, ent );
	pPackedEntity->SetChangeFrameList( pChangeFrame );
	pPackedEntity->SetServerAndClientClass( pServerClass, pClientClass );

	// Make space for the baseline data.
	char packedData[MAX_PACKEDENTITY_DATA];
	bf_read fromBuf( "HLTV_ReadEnterPVS1", pFromData, Bits2Bytes( nFromBits ), nFromBits );
	bf_write writeBuf( "HLTV_ReadEnterPVS2", packedData, sizeof( packedData ) );

	int changedProps[MAX_DATATABLE_PROPS];
	
	// decode basline, is compressed against zero values 
	int nChangedProps = RecvTable_MergeDeltas( pClientClass->m_pRecvTable, &fromBuf, 
		u.m_pBuf, &writeBuf, -1, false, changedProps );

	// update change tick in ChangeFrameList
	if ( pChangeFrame )
	{
		pChangeFrame->SetChangeTick( changedProps, nChangedProps, pSnapshot->m_nTickCount );
	}

	if ( u.m_bUpdateBaselines )
	{
		SetEntityBaseline( (u.m_nBaseline==0)?1:0, pClientClass, u.m_nNewEntity, packedData, writeBuf.GetNumBytesWritten() );
	}

	pPackedEntity->AllocAndCopyPadded( packedData, writeBuf.GetNumBytesWritten() );

	// If ent doesn't think it's in PVS, signal that it is
	Assert( u.m_pTo->last_entity <= ent );
	u.m_pTo->last_entity = ent;
	u.m_pTo->transmit_entity.Set( ent );
}
Exemplo n.º 12
0
void CHLTVClientState::ReadDeltaEnt( CEntityReadInfo &u )
{
	const int i = u.m_nNewEntity;
	CFrameSnapshot *pFromSnapshot =	u.m_pFrom->GetSnapshot();

	CFrameSnapshot *pSnapshot = u.m_pTo->GetSnapshot();

	Assert( i < pFromSnapshot->m_nNumEntities );
	pSnapshot->m_pEntities[i] = pFromSnapshot->m_pEntities[i];
	
	PackedEntity *pToPackedEntity = framesnapshotmanager->CreatePackedEntity( pSnapshot, i );

	// WARNING! get pFromPackedEntity after new pPackedEntity has been created, otherwise pointer may be wrong
	PackedEntity *pFromPackedEntity = framesnapshotmanager->GetPackedEntity( pFromSnapshot, i );

	pToPackedEntity->SetServerAndClientClass( pFromPackedEntity->m_pServerClass, pFromPackedEntity->m_pClientClass );

	// create a copy of the pFromSnapshot ChangeFrameList
	IChangeFrameList* pChangeFrame = NULL;
 
	if ( !m_bSaveMemory )
	{
		pChangeFrame = pFromPackedEntity->GetChangeFrameList()->Copy();
		pToPackedEntity->SetChangeFrameList( pChangeFrame );
	}

	// Make space for the baseline data.
	char packedData[MAX_PACKEDENTITY_DATA];
	const void *pFromData;
	int nFromBits;

	if ( pFromPackedEntity->IsCompressed() )
	{
		pFromData = m_pHLTV->UncompressPackedEntity( pFromPackedEntity, nFromBits );
	}
	else
	{
		pFromData = pFromPackedEntity->GetData();
		nFromBits = pFromPackedEntity->GetNumBits();
	}

	bf_read fromBuf( "HLTV_ReadEnterPVS1", pFromData, Bits2Bytes( nFromBits ), nFromBits );
	bf_write writeBuf( "HLTV_ReadEnterPVS2", packedData, sizeof( packedData ) );

	int changedProps[MAX_DATATABLE_PROPS];
	
	// decode baseline, is compressed against zero values 
	int nChangedProps = RecvTable_MergeDeltas( pToPackedEntity->m_pClientClass->m_pRecvTable,
		&fromBuf, u.m_pBuf, &writeBuf, -1, false, changedProps );

	// update change tick in ChangeFrameList
	if ( pChangeFrame )
	{
		pChangeFrame->SetChangeTick( changedProps, nChangedProps, pSnapshot->m_nTickCount );
	}

	if ( m_bSaveMemory )
	{
		int bits = writeBuf.GetNumBitsWritten();

		const char *compressedData = m_pHLTV->CompressPackedEntity( 
			pToPackedEntity->m_pServerClass,
			(char*)writeBuf.GetData(),
			bits );

		// store as compressed data and don't use mem pools
		pToPackedEntity->AllocAndCopyPadded( compressedData, Bits2Bytes(bits) );
		pToPackedEntity->SetCompressed();
	}
	else
	{
		// store as normal
		pToPackedEntity->AllocAndCopyPadded( packedData, writeBuf.GetNumBytesWritten() );
	}

	u.m_pTo->last_entity = u.m_nNewEntity;
	u.m_pTo->transmit_entity.Set( u.m_nNewEntity );

	u.NextOldEntity();
}
Exemplo n.º 13
0
void SendTable_WritePropList(
	const SendTable *pTable,
	const void *pState,
	const int nBits,
	bf_write *pOut,
	const int objectID,
	const int *pCheckProps,
	const int nCheckProps )
{
	if ( nCheckProps == 0 )
	{
		// Write single final zero bit, signifying that there no changed properties
		pOut->WriteOneBit( 0 );
		return;
	}

	bool bDebugWatch = Sendprop_UsingDebugWatch();

	s_debug_info_shown = false;
	s_debug_bits_start = pOut->GetNumBitsWritten();
	
	CSendTablePrecalc *pPrecalc = pTable->m_pPrecalc;
	CDeltaBitsWriter deltaBitsWriter( pOut );
	
	bf_read inputBuffer( "SendTable_WritePropList->inputBuffer", pState, BitByte( nBits ), nBits );
	CDeltaBitsReader inputBitsReader( &inputBuffer );

	// Ok, they want to specify a small list of properties to check.
	int iToProp = NextProp( &inputBitsReader );
	int i = 0;
	while ( i < nCheckProps )
	{
		// Seek the 'to' state to the current property we want to check.
		while ( iToProp < pCheckProps[i] )
		{
			SkipPropData( &inputBuffer, pPrecalc->GetProp( iToProp ) );
			iToProp = NextProp( &inputBitsReader );
		}

		if ( iToProp == PROP_SENTINEL )
		{
			break;
		}
		else if ( iToProp == pCheckProps[i] )
		{
			const SendProp *pProp = pPrecalc->GetProp( iToProp );

			// Show debug stuff.
			if ( bDebugWatch )
			{
				ShowEncodeDeltaWatchInfo( pTable, pProp, inputBuffer, objectID, iToProp );
			}

			// See how many bits the data for this property takes up.
			int iStartBit = inputBuffer.GetNumBitsRead();
			SkipPropData( &inputBuffer, pProp );
			int nToStateBits = inputBuffer.GetNumBitsRead() - iStartBit;

			TRACE_PACKET( ( "    Send Field (%s) = %d (%d bytes)\n", pProp->GetName(), nToStateBits, ( nToStateBits + 7 ) / 8 ) );

			// Write the data into the output.
			deltaBitsWriter.WritePropIndex( iToProp );
			inputBuffer.Seek( iStartBit );
			pOut->WriteBitsFromBuffer( &inputBuffer, nToStateBits );

			// Seek to the next prop.
			iToProp = NextProp( &inputBitsReader );
		}

		++i;
	}

	if ( s_debug_info_shown )
	{
		int  bits = pOut->GetNumBitsWritten() - s_debug_bits_start;
		ConDMsg( "= %i bits (%i bytes)\n", bits, Bits2Bytes(bits) );
	}

	inputBitsReader.ForceFinished(); // avoid a benign assert
}
Exemplo n.º 14
0
bool CClientState::ProcessTempEntities( SVC_TempEntities *msg )
{
	bool bReliable = false;

	float fire_time = cl.GetTime();

#ifndef _XBOX
	// delay firing temp ents by cl_interp in multiplayer or demoplayback
	if ( cl.m_nMaxClients > 1 || demoplayer->IsPlayingBack() )
	{
		float flInterpAmount = GetClientInterpAmount();
		fire_time += flInterpAmount;
	}
#endif

	if ( msg->m_nNumEntries == 0 )
	{
		bReliable = true;
		msg->m_nNumEntries = 1;
	}

	int flags = bReliable ? FEV_RELIABLE : 0;

	// Don't actually queue unreliable events if playing a demo and skipping ahead
#ifndef _XBOX
	if ( !bReliable && demoplayer->IsSkipping() )
	{
		return true;
	}
#endif
	bf_read &buffer = msg->m_DataIn; // shortcut

	int classID = -1;
	void *from = NULL;
	C_ServerClassInfo *pServerClass = NULL;
	ClientClass *pClientClass = NULL;
	unsigned char data[CEventInfo::MAX_EVENT_DATA];
	bf_write toBuf( data, sizeof(data) );
	CEventInfo *ei = NULL;
	
	for (int i = 0; i < msg->m_nNumEntries; i++ )
	{
		float delay = 0.0f;

		if ( buffer.ReadOneBit() )
		{
			delay = (float)buffer.ReadSBitLong( 8 ) / 100.0f;
		}

		toBuf.Reset();

		if ( buffer.ReadOneBit() )
		{
			from = NULL; // full update

			classID = buffer.ReadUBitLong( m_nServerClassBits ); // classID 
		
			// Look up the client class, etc.
	
			// Match the server classes to the client classes.
			pServerClass = m_pServerClasses ? &m_pServerClasses[ classID - 1 ] : NULL;

			if ( !pServerClass )
			{
				DevMsg("CL_QueueEvent: missing server class info for %i.\n", classID - 1 );
				return false;
			}

			// See if the client .dll has a handler for this class
			pClientClass = FindClientClass( pServerClass->m_ClassName );
		
			if ( !pClientClass || !pClientClass->m_pRecvTable )
			{
				DevMsg("CL_QueueEvent: missing client receive table for %s.\n", pServerClass->m_ClassName );
				return false;
			}

			RecvTable_MergeDeltas( pClientClass->m_pRecvTable, NULL, &buffer, &toBuf );
		}
		else
		{
			Assert( ei );

			bf_read fromBuf( ei->pData, Bits2Bytes(ei->bits) );
		
			RecvTable_MergeDeltas( pClientClass->m_pRecvTable, &fromBuf, &buffer, &toBuf );
		}

		// Add a slot
		ei = &cl.events[ cl.events.AddToTail() ];

		Assert( ei );

		int size = Bits2Bytes(toBuf.GetNumBitsWritten() );
		
		ei->classID			= classID;
		ei->fire_delay		= fire_time + delay;
		ei->flags			= flags;
		ei->pClientClass	= pClientClass;
		ei->bits			= toBuf.GetNumBitsWritten();
		
		ei->pData			= new byte[size]; // copy raw data
		Q_memcpy( ei->pData, data, size );
	}

	return true;
}
Exemplo n.º 15
0
bool CClientState::ProcessVoiceData( SVC_VoiceData *msg )
{
	char chReceived[4096];
	int nBytes = Bits2Bytes( msg->m_nLength );
	nBytes = min( nBytes, sizeof( chReceived ) );
	msg->m_DataIn.ReadBits( chReceived, msg->m_nLength );

#if defined ( _X360 )
	DWORD dwLength = msg->m_nLength;
	XUID xuid = msg->m_xuid;
	Audio_GetXVoice()->PlayIncomingVoiceData( xuid, (byte*)chReceived, dwLength );

	if ( voice_debugfeedback.GetBool() )
	{
		Msg( "Received voice from: %d\n", msg->m_nFromClient + 1 );
	}

	return true;
#endif

#if !defined( NO_VOICE )//#ifndef _XBOX
	int iEntity = msg->m_nFromClient + 1;
	if ( iEntity == (m_nPlayerSlot + 1) )
	{ 
		Voice_LocalPlayerTalkingAck();
	}

	player_info_t playerinfo;
	engineClient->GetPlayerInfo( iEntity, &playerinfo );

	if ( Q_strlen( cl_voice_filter.GetString() ) > 0 && Q_strstr( playerinfo.name, cl_voice_filter.GetString() ) == NULL )
		return true;

	// Data length can be zero when the server is just acking a client's voice data.
	if ( nBytes == 0 )
		return true;

	if ( !Voice_Enabled() )
	{
		return true;
	}

	// Have we already initialized the channels for this guy?
	int nChannel = Voice_GetChannel( iEntity );
	if ( nChannel == VOICE_CHANNEL_ERROR )
	{
		// Create a channel in the voice engine and a channel in the sound engine for this guy.
		nChannel = Voice_AssignChannel( iEntity, msg->m_bProximity );
		if ( nChannel == VOICE_CHANNEL_ERROR )
		{
			// If they used -nosound, then it's not a problem.
			if ( S_IsInitted() )
				ConDMsg("ProcessVoiceData: Voice_AssignChannel failed for client %d!\n", iEntity-1);
			
			return true;
		}
	}

	// Give the voice engine the data (it in turn gives it to the mixer for the sound engine).
	Voice_AddIncomingData( nChannel, chReceived, nBytes, m_nCurrentSequence );
#endif
	return true;
};