Ejemplo n.º 1
0
void ClientTCP()
{
    TcpClient client;
    Packet data;
    data.SetByteOrder(CX_PACKET_BIG_ENDIAN);
    if(!client.InitializeSocket(HOSTNAME, PORT)) 
    {
        cout << "Unable to connect to host " << HOSTNAME << endl;
        return;
    }
    cout << "Initialized TCP Client Socket\n";
    char key = 0;
    while(key != 27) 
    {

        if((key = GetChar()) > 0) 
        {
            data.Clear();       //  Clear packet and encode data.
            data.Write(key);
            client.Send(data);  //  Send data (could send character array also if desired
            /* Alternative way to send:
               client.Send(&key, 1);    //  Send buffer/array.
            */
            data.Clear();
            if(client.Recv(data, 50, 0))
            {
                cout << *data.Ptr() << endl;
            }
            //cout << key;
        }
    }
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
void MulticastClientUDP()
{
    UdpClient client;
    IP4Address::List hosts;
    client.GetHostAddresses(hosts);
    cout << "IP Address for Host Machine\n";
    for(int i = 0; i < (int)hosts.size(); i++ ) 
    {
        cout << hosts[i].mString << endl;
    }

    Packet data;
    data.SetByteOrder(CX_PACKET_BIG_ENDIAN);
    if(!client.InitializeMulticastSocket(MULTICAST_GROUP, PORT, 1)) 
    {
        cout << "Unable to connect to host " << HOSTNAME << endl;
        return;
    }
    cout << "Initialized UDP Client Socket on port " << PORT << endl;
    char key = 0;
    while(key != 27) 
    {
        if((key = GetChar()) > 0) 
        {
            data.Write(key);
            cout << key;
            client.Send(data);  //  Send data (could send character array also if desired
            data.Clear();       //  Clear packet and encode data.
            /*  Alternative way to send:
                client.Send(&key, 1);    //  Send buffer/array.
            */
        }
    }
}
Ejemplo n.º 4
0
Socket::Status TcpSocket::Receive(Packet& packet)
{
    // First clear the variables to fill
    packet.Clear();

    // We start by getting the size of the incoming packet
    Uint32 packetSize = 0;
    std::size_t received = 0;
    if (myPendingPacket.SizeReceived < sizeof(myPendingPacket.Size))
    {
        // Loop until we've received the entire size of the packet
        // (even a 4 bytes variable may be received in more than one call)
        while (myPendingPacket.SizeReceived < sizeof(myPendingPacket.Size))
        {
            char* data = reinterpret_cast<char*>(&myPendingPacket.Size) + myPendingPacket.SizeReceived;
            Status status = Receive(data, sizeof(myPendingPacket.Size) - myPendingPacket.SizeReceived, received);
            myPendingPacket.SizeReceived += received;

            if (status != Done)
                return status;
        }

        // The packet size has been fully received
        packetSize = ntohl(myPendingPacket.Size);
    }
    else
    {
        // The packet size has already been received in a previous call
        packetSize = ntohl(myPendingPacket.Size);
    }

    // Loop until we receive all the packet data
    char buffer[1024];
    while (myPendingPacket.Data.size() < packetSize)
    {
        // Receive a chunk of data
        std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - myPendingPacket.Data.size()), sizeof(buffer));
        Status status = Receive(buffer, sizeToGet, received);
        if (status != Done)
            return status;

        // Append it into the packet
        if (received > 0)
        {
            myPendingPacket.Data.resize(myPendingPacket.Data.size() + received);
            char* begin = &myPendingPacket.Data[0] + myPendingPacket.Data.size() - received;
            std::memcpy(begin, buffer, received);
        }
    }

    // We have received all the packet data: we can copy it to the user packet
    if (!myPendingPacket.Data.empty())
        packet.OnReceive(&myPendingPacket.Data[0], myPendingPacket.Data.size());

    // Clear the pending packet data
    myPendingPacket = PendingPacket();

    return Done;
}
Ejemplo n.º 5
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Reads a message out of the message box.
///
///   This method will read the first message that has not been read yet by this
///   instance of the MappedMessageBox.
///
///   \param[in] message Packet data to read from message box.
///
///   \return True on success, false on failure.
///
////////////////////////////////////////////////////////////////////////////////////
bool MappedMessageBox::ReadMessage(Packet& message) const
{
    bool result = false;
    message.Clear();
    if(mMessageBox.IsOpen())
    {
        Header header;
        if(mMessageBox.Lock() == 0)
        {
            return result;
        }
        header = ReadHeader();
        
        if(header.mCount > 0 && header.mStartBytePos < header.mEndBytePos)
        {
            // Advance to the position of the next message we want to read.
            unsigned int messageSize = 0;
            unsigned int messagePosition = header.mStartBytePos;
            
            // Read the message size in the box.
            mMessageBox->Read(messageSize, messagePosition); 
            
            if(messageSize + MessageHeaderSize + messagePosition <= header.mEndBytePos)
            {
                if(mMessageBox->Read(message, messageSize, messagePosition + MessageHeaderSize) == (int)messageSize)
                {
                     (*( (unsigned *)(&mMessagesRead) ))++;
                    // Advance the start byte position in the array.
                    header.mStartBytePos = messagePosition + MessageHeaderSize + messageSize;
                    // Decrease the number of messages in the box.
                    header.mCount--;
                    result = true;
                }
            }
            if(messageSize + MessageHeaderSize > mMessageBox->Length())
            {
                assert("Corrupted Shared Memory Message Box" && 0);
            }
        }
        // Reset position values.
        if(header.mCount == 0)
        {
            header.mStartBytePos = header.mEndBytePos = Header::Size;
        }
        // Update the read time (shows we are actively checking for messages).
        header.mReadTimeMs = GetTimeMs();
        // Save updated header data.
        WriteHeader(header);
        // Release critical section.
        mMessageBox.Unlock();
    }
        
    return result;
}
Ejemplo n.º 6
0
////////////////////////////////////////////////////////////
/// Receive a packet from the host (must be connected first).
/// This function will block if the socket is blocking
////////////////////////////////////////////////////////////
Socket::Status SocketTCP::Receive(Packet& PacketToReceive)
{
    // We start by getting the size of the incoming packet
    Uint32      PacketSize = 0;
    std::size_t Received   = 0;
    if (myPendingPacketSize < 0)
    {
        Socket::Status Status = Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received);
        if (Status != Socket::Done)
            return Status;

        PacketSize = ntohl(PacketSize);
    }
    else
    {
        // There is a pending packet : we already know its size
        PacketSize = myPendingPacketSize;
    }

    // Then loop until we receive all the packet data
    char Buffer[1024];
    while (myPendingPacket.size() < PacketSize)
    {
        // Receive a chunk of data
        std::size_t SizeToGet = std::min(static_cast<std::size_t>(PacketSize - myPendingPacket.size()), sizeof(Buffer));
        Socket::Status Status = Receive(Buffer, SizeToGet, Received);
        if (Status != Socket::Done)
        {
            // We must save the size of the pending packet until we can receive its content
            if (Status == Socket::NotReady)
                myPendingPacketSize = PacketSize;
            return Status;
        }

        // Append it into the packet
        if (Received > 0)
        {
            myPendingPacket.resize(myPendingPacket.size() + Received);
            char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received;
            memcpy(Begin, Buffer, Received);
        }
    }

    // We have received all the datas : we can copy it to the user packet, and clear our internal packet
    PacketToReceive.Clear();
    if (!myPendingPacket.empty())
        PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
    myPendingPacket.clear();
    myPendingPacketSize = -1;

    return Socket::Done;
}
Ejemplo n.º 7
0
////////////////////////////////////////////////////////////
/// Receive a packet from the host (must be connected first).
/// This function will block if the socket is blocking
////////////////////////////////////////////////////////////
Socket::Status SocketTCP::Receive(Packet& PacketToReceive)
{
    // We start by getting the size of the incoming packet
    Uint32      PacketSize = 0;
    std::size_t Received   = 0;
    if (myPendingPacketSize < 0)
    {
        Socket::Status Status = Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received);
        if (Status != Socket::Done)
            return Status;

        PacketSize = ntohl(PacketSize);
    }
    else
    {
        // There is a pending packet : we already know its size
        PacketSize = myPendingPacketSize;
    }

    // Clear the user packet
    PacketToReceive.Clear();

    // Then loop until we receive all the packet data
    char Buffer[1024];
    while (myPendingPacket.GetDataSize() < PacketSize)
    {
        // Receive a chunk of data
        Uint32 SizeToGet = std::min(PacketSize - myPendingPacket.GetDataSize(), static_cast<Uint32>(sizeof(Buffer)));
        Socket::Status Status = Receive(Buffer, SizeToGet, Received);
        if (Status != Socket::Done)
        {
            // We must save the size of the pending packet until we can receive its content
            if (Status == Socket::NotReady)
                myPendingPacketSize = PacketSize;
            return Status;
        }

        // Append it into the packet
        myPendingPacket.Append(Buffer, Received);
    }

    // We have received all the datas : we can copy it to the user packet, and clear our internal packet
    PacketToReceive = myPendingPacket;
    myPendingPacket.Clear();
    myPendingPacketSize = -1;

    // Let the packet do custom stuff after data reception
    PacketToReceive.OnReceive();

    return Socket::Done;
}
Ejemplo n.º 8
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Thread used by the primary server (the active socket) to receive
///   UDP datagrams and share to clients.
///
////////////////////////////////////////////////////////////////////////////////////
void UdpSharedServer::UdpSocketThread(void* udpSharedServer)
{
    UdpSharedServer* server = (UdpSharedServer*)udpSharedServer;
    Packet udpMessage;
    IP4Address sourceAddress;
    unsigned short sourcePort = 0;
#ifdef WIN32
    unsigned int loopCounter = 0;
#endif

    while(server && 
          (server->mUdpSocketThread.QuitThreadFlag() == false ||
           server->mQuitServerFlag == false))
    {
        // Try and read a new incomming message.
        udpMessage.Clear(false);
        sourcePort = 0;
        if(server->mpSocket->Recv(udpMessage, 5000, 100, &sourceAddress, &sourcePort) > 0)
        {
            // Add the IP address to the end of the message for shared memory clients.
            udpMessage.Write(sourceAddress.mData, 4, udpMessage.Length());
            udpMessage.Write(sourcePort, udpMessage.Length());
            // Send to non-primary UdpSharedServer instances.
            server->mpMessageServer->SendToAllClients(udpMessage);
            // Now process the data internally.  This will add to the
            // queue of received messages, and generate callbacks.
            UdpSharedServer::ProcessUdpMessage(udpMessage, server);
        }
        server->mDelayMutex.Lock();
        if(server->mUpdateDelayMs == 0)
        {
#ifdef WIN32
            // Only sleep every N loops
            if( loopCounter++ == 250)
            {
                loopCounter = 0;
                SleepMs(1);
            }
#else
            usleep(500);
#endif
        }
        else
        {
            CxUtils::SleepMs(server->mUpdateDelayMs);
        }
        server->mDelayMutex.Unlock();
    }
    server->mConnectedFlag = false;
}
Ejemplo n.º 9
0
	void Connection::Update() {
		while (true) {
			this->RecvMutex.lock();
			if (this->ToRecv.Count == 0) {
				this->RecvMutex.unlock();
				break;
			}

			byte* buff = this->ToRecv.RemoveAt(0);
			this->RecvMutex.unlock();

			Packet p;
			p.InBuffer = buff + 4;
			p.InSize = *(int*)buff;

			int pid;
			switch (this->PIDType) {
				case ConnectionPacketIDType::Byte: pid = p.ReadByte(); break;
				case ConnectionPacketIDType::Short: pid = p.ReadShort(); break;
				case ConnectionPacketIDType::Int: pid = p.ReadInt(); break;
			}

			if (pid < this->CallbacksSize && pid >= 0 && this->Callbacks[pid] != nullptr) {
				bool ret = this->Callbacks[pid](this->m_pTag, p);
				if (!ret) {
					this->Disconnect();
					this->RecvMutex.lock();
					while (this->ToRecv.Count > 0) delete this->ToRecv.RemoveAt(this->ToRecv.Count - 1);
					this->RecvMutex.unlock();
				}

				if (p.InPos != p.InSize) {
					Utilities::Print("[col=%s]WARNING: Packet 0x%.4X(%d) was only read till %d, while the size is %d", Color::Orange.ToString().c_str(), pid, pid, p.InPos, p.InSize);
				}
			} else {
				Utilities::Print("[col=%s]Unknown packet: 0x%.4X(%d), size %d", Color::Red.ToString().c_str(), pid,  pid, p.InSize);
			}

			this->LastReceivedPacket = time(nullptr);

			p.InBuffer = nullptr;
			p.InSize = 0;
			p.Clear();

			delete[] buff;
		}
	}
Ejemplo n.º 10
0
////////////////////////////////////////////////////////////
/// Receive a packet.
/// This function will block if the socket is blocking
////////////////////////////////////////////////////////////
Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address, unsigned short& Port)
{
    // We start by getting the size of the incoming packet
    Uint32      PacketSize = 0;
    std::size_t Received   = 0;
    if (myPendingPacketSize < 0)
    {
        // Loop until we've received the entire size of the packet
        // (even a 4 bytes variable may be received in more than one call)
        while (myPendingHeaderSize < sizeof(myPendingHeader))
        {
            char* Data = reinterpret_cast<char*>(&myPendingHeader) + myPendingHeaderSize;
            Socket::Status Status = Receive(Data, sizeof(myPendingHeader) - myPendingHeaderSize, Received, Address, Port);
            myPendingHeaderSize += Received;

            if (Status != Socket::Done)
                return Status;
        }

        PacketSize = ntohl(myPendingHeader);
        myPendingHeaderSize = 0;
    }
    else
    {
        // There is a pending packet : we already know its size
        PacketSize = myPendingPacketSize;
    }

    // Use another address instance for receiving the packet data ;
    // chunks of data coming from a different sender will be discarded (and lost...)
    IPAddress Sender;
    unsigned short SenderPort;

    // Then loop until we receive all the packet data
    char Buffer[1024];
    while (myPendingPacket.size() < PacketSize)
    {
        // Receive a chunk of data
        std::size_t SizeToGet = std::min(static_cast<std::size_t>(PacketSize - myPendingPacket.size()), sizeof(Buffer));
        Socket::Status Status = Receive(Buffer, SizeToGet, Received, Sender, SenderPort);
        if (Status != Socket::Done)
        {
            // We must save the size of the pending packet until we can receive its content
            if (Status == Socket::NotReady)
                myPendingPacketSize = PacketSize;
            return Status;
        }

        // Append it into the packet
        if ((Sender == Address) && (SenderPort == Port) && (Received > 0))
        {
            myPendingPacket.resize(myPendingPacket.size() + Received);
            char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received;
            memcpy(Begin, Buffer, Received);
        }
    }

    // We have received all the datas : we can copy it to the user packet, and clear our internal packet
    PacketToReceive.Clear();
    if (!myPendingPacket.empty())
        PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
    myPendingPacket.clear();
    myPendingPacketSize = -1;

    return Socket::Done;
}
Ejemplo n.º 11
0
void SceneryManager::SendPageRequest(const SceneryPageRequest& request, std::list<PacketManager::PACKET_PAIR>& outgoingPackets)
{
	TimeObject to("SceneryManager::SendPageRequest");

	STRINGLIST queryRows;
	Packet data;
	int wpos = 0;
	char idBuf[32];

	GetThread("SceneryManager::HandlePageRequests[page]");

	SceneryPage *page = GetOrCreatePage(request.zone, request.x, request.y);

	if(page == NULL)
	{
		g_Log.AddMessageFormat("[ERROR] SendPageRequest retrieved NULL page");
		
		wpos = PrepExt_QueryResponseNull(prepBuf, request.queryID);
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));

		ReleaseThread();
		return;
	}

	SceneryPage::SCENERY_IT it;
	for(it = page->mSceneryList.begin(); it != page->mSceneryList.end(); ++it)
	{
		//Build the list of scenery ID strings to form the response to the scenery.list query.
		//No need to save row data unless the query is required.
		if(request.skipQuery == false)
		{
			sprintf(idBuf, "%d", it->second.ID);
			queryRows.push_back(idBuf);
		}
		
		wpos += PrepExt_UpdateScenery(&prepBuf[wpos], &it->second);
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Assign(prepBuf, wpos);
			outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
			wpos = 0;
		}
	}
	if(wpos > 0)
	{
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
	}

	//Done accessing the scenery data itself, no need to hold the thread any longer.
	//All the remaining stuff is using a resident list of query IDs to form into a response
	//packet.
	ReleaseThread();

	//Now build the query response if the client has requested it.
	if(request.skipQuery == true)
		return;

	//Reset the packet buffer and data.
	wpos = 0;
	data.Clear();

	//Get the size of the response
	int sizeReq = 6;  //Query ID (4 bytes) + row count (2 bytes)
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		sizeReq++;  //1 string per row
		sizeReq += PutStringReq(queryRows[s].c_str());
	}

	wpos += PutByte(&prepBuf[wpos], 1);         //_handleQueryResultMsg
	wpos += PutShort(&prepBuf[wpos], sizeReq);  //Message size

	wpos += PutInteger(&prepBuf[wpos], request.queryID);
	wpos += PutShort(&prepBuf[wpos], queryRows.size());
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		wpos += PutByte(&prepBuf[wpos], 1);
		wpos += PutStringUTF(&prepBuf[wpos], queryRows[s].c_str());
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Append(prepBuf, wpos);
			wpos = 0;
		}
	}
	if(wpos > 0)
		data.Append(prepBuf, wpos);

	outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
}
Ejemplo n.º 12
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Writes message contents to packet for the transport layer to
///          send.  Begins writing from current write position in packet.
///
///   Message contents are written to the packet following the JAUS standard.
///
///   \param[out] packet Packet to write header and payload data to.
///   \param[out] header Packet transport header data.
///   \param[in] transportHeader Optional parameter for transport header data to
///                              write before the general transport header.
///   \param[in] clearPacket If true, packet contents are cleared before
///                          writing takes place.
///   \param[in] startingSequenceNumber Sequence number to use for packets.
///   \param[in] broadcastFlag 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 bytes written.
///
////////////////////////////////////////////////////////////////////////////////////
int Message::Write(Packet& packet, 
                   Header& header,
                   const Packet* transportHeader, 
                   const bool clearPacket,
                   const UShort startingSequenceNumber,
                   const Byte broadcastFlag) const
{
    int total = 0;
    //  Build JAUS header data.
    header.mSourceID = mSourceID;
    header.mDestinationID = mDestinationID;
    header.mPriorityFlag = mPriority;
    header.mControlFlag = Header::DataControl::Single;
    header.mCompressionFlag = Header::Compression::None;
    header.mSequenceNumber = startingSequenceNumber;
    header.mBroadcastFlag = broadcastFlag;

    //  Clear out any previous message data.
    if(clearPacket)
    {
        packet.Clear();
        packet.Reserve(Header::MinSize + USHORT_SIZE + 1);
    }
    unsigned int writePos = packet.GetWritePos();
    
    if(transportHeader && transportHeader->Length() > 0)
    {
        writePos += (unsigned int)packet.Write(*transportHeader);
    }
    //  The first thing we must do is advance
    //  the write position to after the JAUS Header
    //  data.  The header is not written first because
    //  we do not know how large the message body will
    //  be yet.
    packet.SetLength(writePos + Header::PayloadOffset);
    packet.SetWritePos(writePos + Header::PayloadOffset);
    total += packet.Write(mMessageCode);
    int payloadSize = 0;
    if( (payloadSize = WriteMessageBody(packet)) >= 0)
    {
        total += payloadSize;
        // Check for large data set.
        if(total + Header::MinSize > Header::MaxPacketSize)
        {
            return FAILURE;
        }
        else
        {
            header.mSize = total + Header::MinSize;
            packet.SetWritePos(writePos);
            // Go back, and re-write the header since 
            // we now know the size of the message.
            if(header.Write(packet))
            {
                // Set the write position to the end of message we just wrote.
                packet.SetWritePos(writePos + header.mSize);
                //  Return the number of bytes written.
                if(transportHeader)
                {
                    return header.mSize + transportHeader->Length();
                }
                else
                {
                    return header.mSize;
                }
            }
        }
    }

    return FAILURE;
}
Ejemplo n.º 13
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \brief Method for receiving UDP messages in a continuous loop.
///
////////////////////////////////////////////////////////////////////////////////////
void JUDP::ReceiveThread(void* args)
{
    JUDP* transport = (JUDP*)args;
    Packet udpMessage;
    CxUtils::IP4Address sourceAddress;
    unsigned short sourcePort = 0;
    long int timeoutMs = 100;
    
#ifdef WIN32
    int loopCounter = 0;
#endif

    udpMessage.Reserve(5000);
    Thread* thread = NULL;
    bool primary = false;
    
    if(transport->mPrimaryThreadCreatedFlag == false)
    {
        primary = true;
        transport->mPrimaryThreadCreatedFlag = true;
        thread = &transport->mPrimaryThread;
    }
    else
    {
        thread = &transport->mSecondaryThread;
    }

    while(transport && 
          thread->QuitThreadFlag() == false &&
          transport->mShutdownServiceFlag == false)
    {
        udpMessage.Clear(false);
        sourcePort = 0;
        if(primary)
        {
            if(transport->mInput.Recv(udpMessage, 
                                      5000, 
                                      timeoutMs, 
                                      &sourceAddress, 
                                      &sourcePort) > 0)
            {
                transport->ProcessUDP(udpMessage, sourceAddress, sourcePort);
            }
        }
        else
        {
            if(transport->mMulticast.GetSourcePort() > 0 &&
               transport->mMulticast.Recv(udpMessage, 
                                          5000, 
                                          timeoutMs, 
                                          &sourceAddress, 
                                          &sourcePort) > 0)
            {
                transport->ProcessUDP(udpMessage, sourceAddress, sourcePort);
            }
        }
        
        if(transport->mShutdownServiceFlag)
        {
            break;
        }

        if(transport->mDelayTimeMs == 0)
        {
#ifdef WIN32
            // Only sleep every N loops
            if( loopCounter++ == 250)
            {
                loopCounter = 0;
                CxUtils::SleepMs(1);
            }
#else
            usleep(500);
#endif
        }
        else
        {
            CxUtils::SleepMs(transport->mDelayTimeMs);
        }
    }
    
    //std::cout << "EXIT!\n";
}