#include "VANetMessage.h" #include "VANetNetworkProtocol.h" #include #include #include #include #include #include #include #include static int S_nMessageIds = 0; CVANetMessage::CVANetMessage( VistaSerializingToolset::ByteOrderSwapBehavior bSwapBuffers ) : m_vecIncomingBuffer( 2048 ) , m_oOutgoing( 2048 ) , m_pConnection( NULL ) { m_oOutgoing.SetByteorderSwapFlag( bSwapBuffers ); m_oIncoming.SetByteorderSwapFlag( bSwapBuffers ); ResetMessage(); } void CVANetMessage::ResetMessage() { if( m_oIncoming.GetTailSize() > 0 ) vstr::err() << "CVANetMessage::ResetMessage() called before message was fully processed!" << std::endl; // wait till sending is complete -> this prevents us // from deleting the buffer while it is still being read // by the connection if( m_pConnection ) m_pConnection->WaitForSendFinish(); m_nMessageId = S_nMessageIds++; m_oOutgoing.ClearBuffer(); m_oOutgoing.WriteInt32( 0 ); // size dummy m_oOutgoing.WriteInt32( 0 ); // type dummy m_oOutgoing.WriteInt32( 0 ); // exceptmode dummy m_oOutgoing.WriteInt32( 0 ); // ID m_oIncoming.SetBuffer( NULL, 0 ); m_nExceptionMode = CVANetNetworkProtocol::VA_NP_INVALID; m_nMessageType = CVANetNetworkProtocol::VA_NP_INVALID; m_nAnswerType = CVANetNetworkProtocol::VA_NP_INVALID; m_pConnection = NULL; } void CVANetMessage::SetConnection( VistaConnectionIP* pConn ) { m_pConnection = pConn; } void CVANetMessage::WriteMessage() { VANetCompat::byte* pBuffer = ( VANetCompat::byte* )m_oOutgoing.GetBuffer(); VANetCompat::sint32 iSwapDummy; // rewrite size dummy iSwapDummy = m_oOutgoing.GetBufferSize() - sizeof( VANetCompat::sint32 ); if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); pBuffer += sizeof( VANetCompat::sint32 ); // rewrite type dummy iSwapDummy = m_nMessageType; if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); pBuffer += sizeof( VANetCompat::sint32 ); // rewrite exceptmode dummy iSwapDummy = m_nExceptionMode; if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); pBuffer += sizeof( VANetCompat::sint32 ); // rewrite messageid dummy iSwapDummy = m_nMessageId; if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); try { // It appears to be safe to transmit an entire buffer of arbitrary size on sender side int nRet = m_pConnection->WriteRawBuffer( m_oOutgoing.GetBuffer(), m_oOutgoing.GetBufferSize() ); m_pConnection->WaitForSendFinish(); if( nRet != m_oOutgoing.GetBufferSize() ) VISTA_THROW( "Could not write the expected number of bytes", 255 ); } catch( VistaExceptionBase& ex ) { VA_EXCEPT2( NETWORK_ERROR, ex.GetExceptionText() ); } } void CVANetMessage::ReadMessage() { try { VANetCompat::sint32 nMessageSize; int nReturn = m_pConnection->ReadInt32( nMessageSize ); if( nReturn != sizeof( VANetCompat::sint32 ) ) VA_EXCEPT2( NETWORK_ERROR, "Received less bytes than expected" ); // we need at least the three protocol ints assert( nMessageSize >= 3 * sizeof( VANetCompat::sint32 ) ); if( nMessageSize > ( int ) m_vecIncomingBuffer.size() ) m_vecIncomingBuffer.resize( nMessageSize ); int iBytesReceivedTotal = 0; while( nMessageSize != iBytesReceivedTotal ) { int iIncommingBytes = m_pConnection->WaitForIncomingData( 0 ); int iBytesReceived = m_pConnection->ReadRawBuffer( &m_vecIncomingBuffer[ iBytesReceivedTotal ], iIncommingBytes ); iBytesReceivedTotal += iBytesReceived; } if( iBytesReceivedTotal != nMessageSize ) VA_EXCEPT2( NETWORK_ERROR, "Reading message, but received less bytes than expected." ); m_oIncoming.SetBuffer( ( VistaType::byte* ) &m_vecIncomingBuffer[ 0 ], nMessageSize, false ); } catch( VistaExceptionBase& ex ) { VA_EXCEPT2( NETWORK_ERROR, ex.GetExceptionText() ); } m_nMessageType = ReadInt(); m_nExceptionMode = ReadInt(); m_nMessageId = ReadInt(); } void CVANetMessage::WriteAnswer() { VANetCompat::byte* pBuffer = ( VANetCompat::byte* )m_oOutgoing.GetBuffer(); VANetCompat::sint32 iSwapDummy; // rewrite size dummy iSwapDummy = m_oOutgoing.GetBufferSize() - sizeof( VANetCompat::sint32 ); if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); pBuffer += sizeof( VANetCompat::sint32 ); // rewrite type dummy iSwapDummy = m_nAnswerType; if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); pBuffer += sizeof( VANetCompat::sint32 ); // rewrite exceptmode dummy iSwapDummy = m_nExceptionMode; if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); pBuffer += sizeof( VANetCompat::sint32 ); // rewrite message dummy iSwapDummy = m_nMessageId; if( m_oOutgoing.GetByteorderSwapFlag() ) VistaSerializingToolset::Swap4( &iSwapDummy ); memcpy( pBuffer, &iSwapDummy, sizeof( VANetCompat::sint32 ) ); try { // It appears to be safe to transmit an entire buffer of arbitrary size on sender side int nRet = m_pConnection->WriteRawBuffer( m_oOutgoing.GetBuffer(), m_oOutgoing.GetBufferSize() ); m_pConnection->WaitForSendFinish(); if( nRet != m_oOutgoing.GetBufferSize() ) VISTA_THROW( "Could not write the expected number of bytes", 255 ); } catch( VistaExceptionBase& ex ) { VA_EXCEPT2( NETWORK_ERROR, ex.GetExceptionText() ); } } void CVANetMessage::ReadAnswer() { try { VANetCompat::sint32 nMessageSize; int nReturn = m_pConnection->ReadInt32( nMessageSize ); assert( nReturn == sizeof( VANetCompat::sint32 ) ); // we need at least the three protocol types assert( nMessageSize >= 3 * sizeof( VANetCompat::sint32 ) ); if( nMessageSize > ( int ) m_vecIncomingBuffer.size() ) m_vecIncomingBuffer.resize( nMessageSize ); int iBytesReceivedTotal = 0; while( nMessageSize != iBytesReceivedTotal ) { int iIncommingBytes = m_pConnection->WaitForIncomingData( 0 ); int iBytesReceived = m_pConnection->ReadRawBuffer( &m_vecIncomingBuffer[ iBytesReceivedTotal ], iIncommingBytes ); iBytesReceivedTotal += iBytesReceived; } if( iBytesReceivedTotal != nMessageSize ) VA_EXCEPT2( NETWORK_ERROR, "Reading message, but received less bytes than expected." ); m_oIncoming.SetBuffer( ( VistaType::byte* ) &m_vecIncomingBuffer[ 0 ], nMessageSize, false ); } catch( VistaExceptionBase& ex ) { VA_EXCEPT2( NETWORK_ERROR, ex.GetExceptionText() ); } m_nAnswerType = ReadInt(); ReadInt(); // protocol overhead - just read and ignore int nMessageID = ReadInt(); assert( nMessageID == m_nMessageId ); m_nMessageId = nMessageID; } int CVANetMessage::GetExceptionMode() const { return m_nExceptionMode; } int CVANetMessage::GetMessageType() const { return m_nMessageType; } int CVANetMessage::GetAnswerType() const { return m_nAnswerType; } void CVANetMessage::SetExceptionMode( int nMode ) { m_nExceptionMode = nMode; } void CVANetMessage::SetMessageType( int nType ) { m_nMessageType = nType; } void CVANetMessage::SetAnswerType( int nType ) { m_nAnswerType = nType; } int CVANetMessage::GetIncomingMessageSize() const { return m_oIncoming.GetTailSize(); } int CVANetMessage::GetOutgoingMessageSize() const { return m_oOutgoing.GetBufferSize(); } bool CVANetMessage::GetOutgoingMessageHasData() const { return ( m_oOutgoing.GetBufferSize() > 4 * sizeof( VANetCompat::sint32 ) ); } void CVANetMessage::WriteString( const std::string& sValue ) { m_oOutgoing.WriteInt32( ( VANetCompat::sint32 )sValue.size() ); if( !sValue.empty() ) m_oOutgoing.WriteString( sValue ); } void CVANetMessage::WriteInt( const int iValue ) { m_oOutgoing.WriteInt32( ( VANetCompat::sint32 )iValue ); } void CVANetMessage::WriteUInt64( const uint64_t iValue ) { m_oOutgoing.WriteUInt64( ( VANetCompat::uint64 )iValue ); } void CVANetMessage::WriteBool( const bool bValue ) { m_oOutgoing.WriteBool( bValue ); } void CVANetMessage::WriteFloat( const float fValue ) { m_oOutgoing.WriteFloat32( fValue ); } void CVANetMessage::WriteDouble( const double dValue ) { m_oOutgoing.WriteFloat64( dValue ); } void CVANetMessage::WriteVec3( const VAVec3& oVec ) { WriteDouble( oVec.x ); WriteDouble( oVec.y ); WriteDouble( oVec.z ); } void CVANetMessage::WriteOrient( const VAOrientYPR& oOrient ) { WriteDouble( oOrient.yaw ); WriteDouble( oOrient.pitch ); WriteDouble( oOrient.roll ); } std::string CVANetMessage::ReadString() { VANetCompat::sint32 nSize; int nReturn = m_oIncoming.ReadInt32( nSize ); assert( nReturn == sizeof( VANetCompat::sint32 ) ); // Empty string? if( nSize == 0 ) return ""; std::string sValue; nReturn = m_oIncoming.ReadString( sValue, nSize ); assert( nReturn == nSize ); return sValue; } int CVANetMessage::ReadInt() { VANetCompat::sint32 nValue; int nReturn = m_oIncoming.ReadInt32( nValue ); assert( nReturn == sizeof( VANetCompat::sint32 ) ); return nValue; } uint64_t CVANetMessage::ReadUInt64() { VANetCompat::uint64 nValue; int nReturn = m_oIncoming.ReadUInt64( nValue ); assert( nReturn == sizeof( VANetCompat::uint64 ) ); return nValue; } bool CVANetMessage::ReadBool() { bool bValue; int nReturn = m_oIncoming.ReadBool( bValue ); assert( nReturn == sizeof( bool ) ); return bValue; } float CVANetMessage::ReadFloat() { float fValue; int nReturn = m_oIncoming.ReadFloat32( fValue ); assert( nReturn == sizeof( float ) ); return fValue; } double CVANetMessage::ReadDouble() { double dValue; int nReturn = m_oIncoming.ReadFloat64( dValue ); assert( nReturn == sizeof( double ) ); return dValue; } VAVec3 CVANetMessage::ReadVec3() { double x = ReadDouble(); double y = ReadDouble(); double z = ReadDouble(); return VAVec3( x, y, z ); } VAOrientYPR CVANetMessage::ReadOrient() { double yaw = ReadDouble(); double pitch = ReadDouble(); double roll = ReadDouble(); return VAOrientYPR( yaw, pitch, roll ); } void CVANetMessage::WriteCoreEvent( const CVACoreEvent& oEvent ) { WriteInt( oEvent.iEventID ); WriteUInt64( oEvent.iEventType ); WriteInt( oEvent.iObjectID ); WriteString( oEvent.sObjectID ); WriteInt( oEvent.iParamID ); WriteString( oEvent.sParam ); WriteInt( oEvent.iIndex ); WriteInt( oEvent.iAuralizationMode ); WriteDouble( oEvent.dVolume ); WriteDouble( oEvent.dState ); WriteBool( oEvent.bMuted ); WriteString( oEvent.sName ); WriteString( oEvent.sFilename ); WriteVec3( oEvent.vPos ); WriteVec3( oEvent.vView ); WriteVec3( oEvent.vUp ); WriteOrient( oEvent.oOrientation ); WriteVec3( oEvent.vVelocity ); WriteInt( ( int ) oEvent.vfInputPeaks.size() ); for( size_t i = 0; i < oEvent.vfInputPeaks.size(); i++ ) WriteFloat( oEvent.vfInputPeaks[ i ] ); WriteInt( ( int ) oEvent.vfOutputPeaks.size() ); for( size_t i = 0; i < oEvent.vfOutputPeaks.size(); i++ ) WriteFloat( oEvent.vfOutputPeaks[ i ] ); WriteFloat( oEvent.fSysLoad ); WriteFloat( oEvent.fDSPLoad ); WriteDouble( oEvent.dCoreClock ); } CVACoreEvent CVANetMessage::ReadCoreEvent() { CVACoreEvent oEvent; oEvent.iEventID = ReadInt(); oEvent.iEventType = ReadUInt64(); oEvent.iObjectID = ReadInt(); oEvent.sObjectID = ReadString(); oEvent.iParamID = ReadInt(); oEvent.sParam = ReadString(); oEvent.iIndex = ReadInt(); oEvent.iAuralizationMode = ReadInt(); oEvent.dVolume = ReadDouble(); oEvent.dState = ReadDouble(); oEvent.bMuted = ReadBool(); oEvent.sName = ReadString(); oEvent.sFilename = ReadString(); oEvent.vPos = ReadVec3(); oEvent.vView = ReadVec3(); oEvent.vUp = ReadVec3(); oEvent.oOrientation = ReadOrient(); oEvent.vVelocity = ReadVec3(); int n = ReadInt(); for( int i = 0; i < n; i++ ) oEvent.vfInputPeaks.push_back( ReadFloat() ); n = ReadInt(); for( int i = 0; i < n; i++ ) oEvent.vfOutputPeaks.push_back( ReadFloat() ); oEvent.fSysLoad = ReadFloat(); oEvent.fDSPLoad = ReadFloat(); oEvent.dCoreClock = ReadDouble(); return oEvent; } void CVANetMessage::WriteException( const CVAException& oException ) { WriteInt( oException.GetErrorCode() ); WriteString( oException.GetErrorMessage() ); } // Deserialize a VAException instance from a byte buffer (returns number of bytes read) // (returns number of bytes read if successfull, otherwise -1) CVAException CVANetMessage::ReadException() { int nType = ReadInt(); return CVAException( nType, ReadString() ); } void CVANetMessage::WriteCoreVersionInfo( const CVACoreVersionInfo& oInfo ) { WriteString( oInfo.sVersion ); WriteString( oInfo.sFlags ); WriteString( oInfo.sDate ); WriteString( oInfo.sComments ); } CVACoreVersionInfo CVANetMessage::ReadCoreVersionInfo() { CVACoreVersionInfo oInfo; oInfo.sVersion = ReadString(); oInfo.sFlags = ReadString(); oInfo.sDate = ReadString(); oInfo.sComments = ReadString(); return oInfo; } void CVANetMessage::WriteDirectivityInfo( const CVADirectivityInfo& oInfo ) { WriteString( oInfo.sName ); WriteString( oInfo.sFilename ); WriteInt( oInfo.iID ); WriteInt( oInfo.iReferences ); WriteString( oInfo.sDesc ); } CVADirectivityInfo CVANetMessage::ReadDirectivityInfo() { CVADirectivityInfo oInfo; oInfo.sName = ReadString(); oInfo.sFilename = ReadString(); oInfo.iID = ReadInt(); oInfo.iReferences = ReadInt(); oInfo.sDesc = ReadString(); return oInfo; } void CVANetMessage::WriteHRIRInfo( const CVAHRIRInfo& oInfo ) { WriteString( oInfo.sName ); WriteString( oInfo.sFilename ); WriteInt( oInfo.iID ); WriteInt( oInfo.iReferences ); WriteString( oInfo.sDesc ); } CVAHRIRInfo CVANetMessage::ReadHRIRInfo() { CVAHRIRInfo oInfo; oInfo.sName = ReadString(); oInfo.sFilename = ReadString(); oInfo.iID = ReadInt(); oInfo.iReferences = ReadInt(); oInfo.sDesc = ReadString(); return oInfo; } void CVANetMessage::WriteSoundInfo( const CVASoundInfo& oInfo ) { WriteString( oInfo.sName ); WriteString( oInfo.sFilename ); WriteInt( oInfo.iLength ); WriteInt( oInfo.iID ); WriteDouble( oInfo.dDuration ); } CVASoundInfo CVANetMessage::ReadSoundInfo() { CVASoundInfo oInfo; oInfo.sName = ReadString(); oInfo.sFilename = ReadString(); oInfo.iLength = ReadInt(); oInfo.iID = ReadInt(); oInfo.dDuration = ReadDouble(); return oInfo; } void CVANetMessage::WriteSignalSourceInfo( const CVASignalSourceInfo& oInfo ) { WriteString( oInfo.sName ); WriteString( oInfo.sType ); WriteString( oInfo.sState ); WriteString( oInfo.sID ); WriteString( oInfo.sDesc ); WriteInt( oInfo.iReferences ); } CVASignalSourceInfo CVANetMessage::ReadSignalSourceInfo() { CVASignalSourceInfo oInfo; oInfo.sName = ReadString(); oInfo.sType = ReadString(); oInfo.sState = ReadString(); oInfo.sID = ReadString(); oInfo.sDesc = ReadString(); oInfo.iReferences = ReadInt(); return oInfo; } void CVANetMessage::WriteSceneInfo( const CVASceneInfo& ) { // TODO: Add field when CVASceneInfo gets designed } CVASceneInfo CVANetMessage::ReadSceneInfo() { CVASceneInfo oInfo; // TODO: Add field when CVASceneInfo gets designed return oInfo; } void CVANetMessage::WriteModuleInfo( const CVAModuleInfo& oInfo ) { WriteString( oInfo.sName ); WriteString( oInfo.sDesc ); } void CVANetMessage::ReadModuleInfo( CVAModuleInfo& oInfo ) { oInfo.sName = ReadString(); oInfo.sDesc = ReadString(); } void CVANetMessage::WriteBlob( const void* pBuf, int nBytes ) { m_oOutgoing.WriteRawBuffer( pBuf, nBytes ); } void CVANetMessage::ReadBlob( void* pBuf, int nBytes ) { int nReturn = m_oIncoming.ReadRawBuffer( pBuf, nBytes ); assert( nReturn == nBytes ); } void CVANetMessage::WriteVAStruct( const CVAStruct& oStruct ) { // Anzahl der Keys schreiben WriteInt( oStruct.Size() ); int nBytes; for( CVAStruct::const_iterator cit = oStruct.Begin(); cit != oStruct.End(); ++cit ) { // Schlüsselnamen WriteString( cit->first ); // Wert-Typ int iDatatype = cit->second.GetDatatype(); WriteInt( iDatatype ); // Wert switch( iDatatype ) { case CVAStructValue::UNASSIGNED: // Keinen Wert => Nichts schreiben break; case CVAStructValue::BOOL: WriteBool( cit->second ); break; case CVAStructValue::INT: WriteInt( cit->second ); break; case CVAStructValue::DOUBLE: WriteDouble( cit->second ); break; case CVAStructValue::STRING: WriteString( cit->second ); break; case CVAStructValue::STRUCT: WriteVAStruct( cit->second.GetStruct() ); break; case CVAStructValue::DATA: nBytes = cit->second.GetDataSize(); WriteInt( nBytes ); WriteBlob( cit->second.GetData(), nBytes ); break; case CVAStructValue::SAMPLEBUFFER: { const CVASampleBuffer& oSampleBuffer( cit->second ); WriteInt( oSampleBuffer.GetNumSamples() ); for( int i = 0; i < oSampleBuffer.GetNumSamples(); i++ ) WriteFloat( oSampleBuffer.vfSamples[ i ] ); } break; default: // Implementierung vergessen? Oder neuer Datentyp? VA_EXCEPT2( PROTOCOL_ERROR, "Unsupported key datatype" ); } } } void CVANetMessage::ReadVAStruct( CVAStruct& oStruct ) { oStruct.Clear(); // Anzahl der Keys lesen int nKeys = ReadInt(); for( int i = 0; i < nKeys; i++ ) { // Schlüsselnamen std::string sKeyName = ReadString(); // Wert-Typ int iDatatype = ReadInt(); // Wert switch( iDatatype ) { case CVAStructValue::UNASSIGNED: // Keinen Wert => Leeren Schüssel oStruct[ sKeyName ]; break; case CVAStructValue::BOOL: oStruct[ sKeyName ] = ReadBool(); break; case CVAStructValue::INT: oStruct[ sKeyName ] = ReadInt(); break; case CVAStructValue::DOUBLE: oStruct[ sKeyName ] = ReadDouble(); break; case CVAStructValue::STRING: oStruct[ sKeyName ] = ReadString(); break; case CVAStructValue::STRUCT: { CVAStruct oSubstruct; ReadVAStruct( oSubstruct ); oStruct[ sKeyName ] = oSubstruct; } break; case CVAStructValue::DATA: { int iDataSize = ReadInt(); void* pData = ( void* ) new char[ iDataSize ]; try { ReadBlob( pData, iDataSize ); } catch( ... ) { delete[] pData; throw; } oStruct[ sKeyName ] = CVAStructValue( pData, iDataSize ); } break; case CVAStructValue::SAMPLEBUFFER: { int iNumSamples = ReadInt(); oStruct[ sKeyName ] = CVASampleBuffer( iNumSamples, false ); CVASampleBuffer& oSampleBuffer( oStruct[ sKeyName ] ); for( int i = 0; i < iNumSamples; i++ ) oSampleBuffer.vfSamples[ i ] = ReadFloat(); } break; default: // Implementierung vergessen? Oder neuer Datentyp? VA_EXCEPT2( PROTOCOL_ERROR, "Structure contains unknown key datatype" ); } } } VistaConnectionIP* CVANetMessage::GetConnection() const { return m_pConnection; } void CVANetMessage::ClearConnection() { m_pConnection = NULL; } void CVANetMessage::WriteAudioRenderingModuleInfo( const CVAAudioRendererInfo& oRenderer ) { WriteString( oRenderer.sID ); WriteString( oRenderer.sClass ); WriteBool( oRenderer.bEnabled ); WriteString( oRenderer.sDescription ); } void CVANetMessage::WriteAudioReproductionModuleInfo( const CVAAudioReproductionInfo& oRepro ) { WriteString( oRepro.sID ); WriteString( oRepro.sClass ); WriteBool( oRepro.bEnabled ); WriteString( oRepro.sDescription ); } CVAAudioRendererInfo CVANetMessage::ReadAudioRenderingModuleInfo() { CVAAudioRendererInfo oRenderer; oRenderer.sID = ReadString(); oRenderer.sClass = ReadString(); oRenderer.bEnabled = ReadBool(); oRenderer.sDescription = ReadString(); return oRenderer; } CVAAudioReproductionInfo CVANetMessage::ReadAudioReproductionModuleInfo() { CVAAudioReproductionInfo oRepro; oRepro.sID = ReadString(); oRepro.sClass = ReadString(); oRepro.bEnabled = ReadBool(); oRepro.sDescription = ReadString(); return oRepro; }