/*----------------------------------------------------------------------------- Module: CANoeFDX Interfaces: FDXDispatcher ------------------------------------------------------------------------------- Datagram dispatcher class for CANoe FDX protocol ------------------------------------------------------------------------------- Copyright (c) Vector Informatik GmbH. All rights reserved. -----------------------------------------------------------------------------*/ #include "stdafx.h" #include "FDXDispatcher.h" FDXDispatcher::FDXDispatcher() : mNextExpectedSeqNr (CANoeFDX::kSequenceNumberSessionStart) {} void FDXDispatcher::DispatchDatagram(FDXDatagram& datagram) { // // A) Check datagram header // CANoeFDX::DatagramHeader* header = reinterpret_cast(datagram.Buffer()); { if (datagram.Size()fdxSignature != CANoeFDX::kFdxSignature ) { OnFormatError(); return; // different value for magic cookie } if (header->fdxMajorVersion != CANoeFDX::kFdxMajorVersion) // major version does not fit { OnFormatError(); return; // version error } if ((header->fdxProtocolFlags & CANoeFDX::kByteOrderMask) == CANoeFDX::kByteOrderBigEndian) { OnFormatError(); return; // This client only supports little endian } // Check Sequence Number if (header->sequenceNumber == CANoeFDX::kSequenceNumberUnused) { // sequence numbering unused => check nothing } else { if ( (header->sequenceNumber&0x7FFF) != mNextExpectedSeqNr) { OnSequenceNumberError(header, mNextExpectedSeqNr); } if (header->sequenceNumber&CANoeFDX::kSequenceNumberSessionEndFlag) { mNextExpectedSeqNr = CANoeFDX::kSequenceNumberSessionStart; } else { mNextExpectedSeqNr = IncrementSequenceNumber(header->sequenceNumber); } } } // // B) Check The memory structure of the following commands. // Do this check for the whole datagram before any request is processed { DWORD offset = sizeof(CANoeFDX::DatagramHeader); DWORD remainingBytes = datagram.Size() - offset; for (DWORD i=0; i < header->numberOfCommands; i++) { if (remainingBytes((char*)datagram.Buffer()+offset); if (remainingBytescommandSize) { OnFormatError(); return; // datagram is to small for this command } offset += command->commandSize; remainingBytes -= command->commandSize; } if (remainingBytes != 0) { OnFormatError(); return; // there are some unused data bytes at the end of the datagram } } // // C) Check the internal structure of the commands // { DWORD offset = sizeof(CANoeFDX::DatagramHeader); for (DWORD i=0; i < header->numberOfCommands; i++) { CANoeFDX::CommandHeader* command = reinterpret_cast((char*)datagram.Buffer()+offset); switch(command->commandCode) { case CANoeFDX::kCommandCode_DataExchange: if (command->commandSize < CANoeFDX::kDataExchangeBaseSize) { OnFormatError(); return; // invalid size for DataExchange command, command is to small } if (command->commandSize < CANoeFDX::kDataExchangeBaseSize+ static_cast(command)->dataSize ) { OnFormatError(); return; // invalid size for DataExchange command, payload does not fit into command } break; case CANoeFDX::kCommandCode_Status: if (command->commandSizecommandSizecommandSizecommandSizecommandSizecommandSizecommandSizecommandSizecommandSizecommandSize; } } // // Dispatch command // { DWORD offset = sizeof(CANoeFDX::DatagramHeader); for (DWORD i=0; i < header->numberOfCommands; i++) { CANoeFDX::CommandHeader* command = reinterpret_cast((char*)datagram.Buffer()+offset); switch(command->commandCode) { case CANoeFDX::kCommandCode_DataExchange: OnDataExchange(header, static_cast(command)); break; case CANoeFDX::kCommandCode_Status: OnStatus(header, static_cast(command)); break; case CANoeFDX::kCommandCode_DataError: OnDataError(header, static_cast(command)); break; default: // ignore any other command break; } offset += command->commandSize; } } }