Example #1
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief If the IsLargeDataSet method returns true, then this method is used
///          to convert message payload data into a multi-packet stream
///          according to rules defined by the JAUS standards documents.
///
///   This method should only be overloaded if your message contains data
///   larger than Header::MaxSize - Header::MinSize (e.g. image data) and you wish
///   to optimize how data is written.  By default, this method calls the
///   WriteMessageBody method to generate a single large byte array, which is then
///   broken up into a Packet::List for the transport layer.
///
///   \param[out] stream Multi-packet stream containing serialized message 
///                      following rules of large data sets.
///   \param[out] streamHeaders Headers for packet in the stream.
///   \param[in] maxPayloadSize This is the maximum packet size including 
///                             payload, does not include transport, General
///                             Transport Header, or Message Code (USHORT).
///   \param[in] transportHeader Additional transport header data to precede
///                              the general transport header of each packet.
///   \param[in] startingSequenceNumber Sequence number to use for packets.
///   \param[in] broadcastFlags Values to use to signify if message should be
///                             sent using any broadcast options (e.g. 
///                             multicast). 0 = no options, 1 = local broadcast,
///                             2 = global broadcast.
///
///   \return FAILURE on error, otherwise number of packets written.
///
////////////////////////////////////////////////////////////////////////////////////
int Message::WriteLargeDataSet(Packet::List& stream,
                               Header::List& streamHeaders,
                               const UShort maxPayloadSize,
                               const Packet* transportHeader,
                               const UShort startingSequenceNumber,
                               const Byte broadcastFlags) const
{
    Header header;
    header.mDestinationID = mDestinationID;
    header.mSourceID = mSourceID;
    header.mPriorityFlag = mPriority;
    header.mBroadcastFlag = broadcastFlags;

    stream.clear();
    streamHeaders.clear();
    Packet* temp = ((Packet *)(&mStreamPayload));
    temp->Clear();
    if(IsLargeDataSet() && WriteMessageBody(*temp) >= 0)
    {
        LargeDataSet::CreateLargeDataSet(header, 
                                         mMessageCode, 
                                         *temp, 
                                         stream, 
                                         streamHeaders, 
                                         transportHeader, 
                                         maxPayloadSize,
                                         startingSequenceNumber);
        return (int)stream.size();
    }
    return FAILURE;
}
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Tests large data set creation and merging.
///
////////////////////////////////////////////////////////////////////////////////////
void TestLargeDataSets()
{
    Packet payload;                         // Large data set payload.
    Header header;                          // Message header data.
    UShort messageCode = 50;                // Random message type.
    Packet::List stream;                    // Multi-packet stream sequence.
    Header::List streamHeaders;             // Mutli-packet stream sequence headers.
    unsigned int payloadSize = 60000;       // Payload data size to create.
    
    header.mSourceID(50, 1, 1);
    header.mDestinationID(51, 1, 1);
    for(unsigned int i = 0; i < payloadSize/UINT_SIZE; i++)
    {
        payload.Write(i);
    }
    
    LargeDataSet::CreateLargeDataSet(header, messageCode, payload, stream, streamHeaders, NULL, 1437, 30);
    payload.Destroy();
    messageCode = 0;
    header = Header();
    LargeDataSet::MergeLargeDataSet(header, messageCode, payload, stream, NULL);
    
    unsigned int data;
    for(unsigned int i = 0; i < payloadSize/UINT_SIZE; i++)
    {
        payload.Read(data);
        if(data != i)
        {
            std::cout << "Large Data Sets Error: Data Does Not Match!\n";
            return;
        }
    }

    std::random_shuffle(stream.begin(), stream.end());

    LargeDataSet dataSet;
    for(unsigned int i = 0; i < (unsigned int)stream.size(); i++)
    {
        Header header;
        UShort messageCode;
        stream[i].SetReadPos(0);
        header.Read(stream[i]);
        stream[i].Read(messageCode);
        if(dataSet.AddPacket(header, messageCode, stream[i]) == false)
        {
            std::cout << "Large Data Sets Error: Could Not Collect Stream.\n";
        }
    }
    // Now merge the data.
    LargeDataSet::MergeLargeDataSet(header, messageCode, payload, dataSet.mStream, NULL);
    for(unsigned int i = 0; i < payloadSize/UINT_SIZE; i++)
    {
        payload.Read(data);
        if(data != i)
        {
            std::cout << "Large Data Sets Error: Data Does Not Match!\n";
            return;
        }
    }
}
Example #3
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Converts the message data into JUDP packets for transmission.
///
///   \param[in] message Message to convert/serialize.
///   \param[out] stream Packets to send.
///   \param[out] streamHeaders Header info for packets.
///   \param[in] startingSequenceNumber Sequence number to use for packets.
///   \param[in] broadcastFlags Values to use to signify if message should be
///                             sent using any broadcast options (e.g. 
///                             multicast). 0 = no options, 1 = local broadcast,
///                             2 = global broadcast.
///
///   \return True on success, false on failure.
///
////////////////////////////////////////////////////////////////////////////////////
bool JUDP::SerializeMessage(const Message* message,
                            Packet::List& stream,
                            Header::List& streamHeaders,
                            const UShort startingSequenceNumber,
                            const int broadcastFlags) const
{
    Packet packet;
    Header header;

    // Pre-allocate memory.
    packet.Reserve(mMaxPayloadSize + OverheadSizeBytes);

    // Clear stream/headers.
    stream.clear();
    streamHeaders.clear();

    // If the message is a large data set, create a multi-packet stream.
    if(message->IsLargeDataSet(mMaxPayloadSize))
    {
        return message->WriteLargeDataSet(stream, 
                                          streamHeaders, 
                                          mMaxPayloadSize, 
                                          &mTransportHeader,
                                          startingSequenceNumber) > 0;
    }
    // Single packet.
    else if(message->Write(packet, header, &mTransportHeader, true, startingSequenceNumber) > 0)
    {
        stream.push_back(packet);
        streamHeaders.push_back(header);
        return true;
    }
    return false;
}
Example #4
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief If the Transport services of a component receive a multi-packet
///          stream for a message, this method is used to read the contents.
///
///   This method should only be overloaded if you wish to optimize the
///   de-serialization of mutli-packet streams for your message (e.g. video data).
///   By default, this method converts the stream to a larger continuous packet
///   to be used by the ReadMessageBody method.
///
///   \param[in] stream Multi-packet stream containing serialized message 
///                     following rules of large data sets.
///   \param[in] transportHeader Additional transport header data that precedes
///                              the general transport header of each packet.
///
///   \return FAILURE on error, otherwise number of packets read.
///
////////////////////////////////////////////////////////////////////////////////////
int Message::ReadLargeDataSet(const Packet::List& stream,
                              const Packet* transportHeader)
{
    Header header;
    UShort messageCode;
    if(LargeDataSet::MergeLargeDataSet(header, messageCode, mStreamPayload, stream, transportHeader))
    {
        if(ReadMessageBody(mStreamPayload))
        {
            mSourceID = header.mSourceID;
            mDestinationID = header.mDestinationID;
            mPriority = header.mPriorityFlag;
            return (int)stream.size();
        }
    }
    return FAILURE;
}
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Test method to verify ability to read/write message data from
///   an example wireshark log provided for testing systems for the JAUS
///   Interoperability Challenge hosted at several AUVSI competitions.
///
////////////////////////////////////////////////////////////////////////////////////
void VerifyAgainstLog()
{
    Packet::List packets;
    Packet::List::iterator packet;

    Component component;
    component.DiscoveryService()->SetSubsystemIdentification(Subsystem::OCU, "OCP");
    component.AddService(new LocalPoseSensor());
    component.AddService(new VelocityStateSensor());
    component.AddService(new ListManager());    
    component.AddService(new TestLocalWaypointListDriver());

    Packet::LoadWiresharkCapturePacketExport("logs/example-capture.txt", packets);
    Address cop(42, 1, 1);
    Address sim(6000, 1, 1);
    //Packet::LoadWiresharkCapturePacketExport("logs/example_capture-2.txt", packets);

    Message::List messages;
    Message::List::iterator message;
    
    // Delete UDP header data to get to just the JAUS message.
    for(packet = packets.begin(); packet != packets.end();)
    {
        // Delete UDP header data.
        packet->Delete(43);
        // Read message header data.
        Header jausHeader;
        if(jausHeader.Read(*packet))
        {
            UShort messageCode = 0;
            packet->Read(messageCode, Header::PayloadOffset);
            Message* jausMessage = component.TransportService()->CreateMessage(messageCode);
            if(jausMessage)
            {
                packet->SetReadPos(0);
                if(jausMessage->Read(*packet))
                {
                    messages.push_back(jausMessage);
                    if(jausMessage->GetMessageCode() == SET_ELEMENT)
                    {
                        Element::List::iterator m;
                        SetElement* setElement = (SetElement *)jausMessage;
                        for(m = setElement->GetElementList()->begin();
                            m != setElement->GetElementList()->end();
                            m++)
                        {
                            UShort code = 0;
                            m->mPayload.SetReadPos(0);
                            m->mPayload.Read(code);
                            Message* element = component.TransportService()->CreateMessage(code);
                            if(element)
                            {
                                element->CopyHeaderData(jausMessage);
                                if(element->ReadMessageBody(m->mPayload))
                                {
                                    messages.push_back(element);
                                }
                                else
                                {
                                    std::cout << "Failed to Read Message Data [" << std::hex << element->GetMessageCode() << "]:\n";
                                    delete element;
                                }
                            }
                        }
                    }
                }
                else
                {
                    std::cout << "Failed to Read Message Data [" << std::hex << jausMessage->GetMessageCode() << "]:\n";
                }
            }
            else
            {
                std::cout << "Unknown Message Type [" << std::hex << messageCode << "]:\n";
            }
        }
        else
        {
            std::cout << "Bad Header!\n";
        }
        packet++;
    }

    component.Initialize(cop);

    message = messages.begin();
    for(message = messages.begin(); 
        message != messages.end(); 
        message++)
    {
        //(*message)->Print();
        if((*message)->GetSourceID() == cop)
        {
            (*message)->SetDestinationID(sim);
            component.Send((*message));
        }
        CxUtils::SleepMs(1);
        delete (*message);
    }
}