From 2ed809cb4765306b7af9b6968e2ec609d143979b Mon Sep 17 00:00:00 2001 From: Finn Williams Date: Mon, 20 Apr 2020 21:21:07 +0100 Subject: IVGCVSW-4594 Refactor the GatordMockService and GatordMockMain to extract a BasePipeServer Signed-off-by: Finn Williams Change-Id: I03c1b46104dadc491dba6075865e486f78aa60fa --- tests/profiling/gatordmock/GatordMockService.cpp | 357 ++--------------------- 1 file changed, 30 insertions(+), 327 deletions(-) (limited to 'tests/profiling/gatordmock/GatordMockService.cpp') diff --git a/tests/profiling/gatordmock/GatordMockService.cpp b/tests/profiling/gatordmock/GatordMockService.cpp index dbe4fb3b99..13f688225b 100644 --- a/tests/profiling/gatordmock/GatordMockService.cpp +++ b/tests/profiling/gatordmock/GatordMockService.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -26,97 +25,6 @@ namespace armnn namespace gatordmock { -bool GatordMockService::OpenListeningSocket(armnnUtils::Sockets::Socket listeningSocket, - const std::string udsNamespace, - const int numOfConnections) -{ - if (-1 == listeningSocket) - { - std::cerr << ": Socket construction failed: " << strerror(errno) << std::endl; - return false; - } - - sockaddr_un udsAddress; - memset(&udsAddress, 0, sizeof(sockaddr_un)); - // We've set the first element of sun_path to be 0, skip over it and copy the namespace after it. - memcpy(udsAddress.sun_path + 1, udsNamespace.c_str(), strlen(udsNamespace.c_str())); - udsAddress.sun_family = AF_UNIX; - - // Bind the socket to the UDS namespace. - if (-1 == bind(listeningSocket, reinterpret_cast(&udsAddress), sizeof(sockaddr_un))) - { - std::cerr << ": Binding on socket failed: " << strerror(errno) << std::endl; - return false; - } - // Listen for 10 connections. - if (-1 == listen(listeningSocket, numOfConnections)) - { - std::cerr << ": Listen call on socket failed: " << strerror(errno) << std::endl; - return false; - } - return true; -} - -bool GatordMockService::WaitForStreamMetaData() -{ - if (m_EchoPackets) - { - std::cout << "Waiting for stream meta data..." << std::endl; - } - // The start of the stream metadata is 2x32bit words, 0 and packet length. - uint8_t header[8]; - if (!ReadFromSocket(header, 8)) - { - return false; - } - EchoPacket(PacketDirection::ReceivedHeader, header, 8); - // The first word, stream_metadata_identifer, should always be 0. - if (ToUint32(&header[0], TargetEndianness::BeWire) != 0) - { - std::cerr << ": Protocol error. The stream_metadata_identifer was not 0." << std::endl; - return false; - } - - uint8_t pipeMagic[4]; - if (!ReadFromSocket(pipeMagic, 4)) - { - return false; - } - EchoPacket(PacketDirection::ReceivedData, pipeMagic, 4); - - // Before we interpret the length we need to read the pipe_magic word to determine endianness. - if (ToUint32(&pipeMagic[0], TargetEndianness::BeWire) == PIPE_MAGIC) - { - m_Endianness = TargetEndianness::BeWire; - } - else if (ToUint32(&pipeMagic[0], TargetEndianness::LeWire) == PIPE_MAGIC) - { - m_Endianness = TargetEndianness::LeWire; - } - else - { - std::cerr << ": Protocol read error. Unable to read PIPE_MAGIC value." << std::endl; - return false; - } - // Now we know the endianness we can get the length from the header. - // Remember we already read the pipe magic 4 bytes. - uint32_t metaDataLength = ToUint32(&header[4], m_Endianness) - 4; - // Read the entire packet. - std::vector packetData(metaDataLength); - if (metaDataLength != - boost::numeric_cast(Sockets::Read(m_ClientConnection, packetData.data(), metaDataLength))) - { - std::cerr << ": Protocol read error. Data length mismatch." << std::endl; - return false; - } - EchoPacket(PacketDirection::ReceivedData, packetData.data(), metaDataLength); - m_StreamMetaDataVersion = ToUint32(&packetData[0], m_Endianness); - m_StreamMetaDataMaxDataLen = ToUint32(&packetData[4], m_Endianness); - m_StreamMetaDataPid = ToUint32(&packetData[8], m_Endianness); - - return true; -} - void GatordMockService::SendConnectionAck() { if (m_EchoPackets) @@ -124,7 +32,7 @@ void GatordMockService::SendConnectionAck() std::cout << "Sending connection acknowledgement." << std::endl; } // The connection ack packet is an empty data packet with packetId == 1. - SendPacket(0, 1, nullptr, 0); + m_BasePipeServer.get()->SendPacket(0, 1, nullptr, 0); } void GatordMockService::SendRequestCounterDir() @@ -134,7 +42,7 @@ void GatordMockService::SendRequestCounterDir() std::cout << "Sending connection acknowledgement." << std::endl; } // The request counter directory packet is an empty data packet with packetId == 3. - SendPacket(0, 3, nullptr, 0); + m_BasePipeServer.get()->SendPacket(0, 3, nullptr, 0); } void GatordMockService::SendActivateTimelinePacket() @@ -144,7 +52,7 @@ void GatordMockService::SendActivateTimelinePacket() std::cout << "Sending activate timeline packet." << std::endl; } // The activate timeline packet is an empty data packet with packetId == 6. - SendPacket(0, 6, nullptr, 0); + m_BasePipeServer.get()->SendPacket(0, 6, nullptr, 0); } void GatordMockService::SendDeactivateTimelinePacket() @@ -154,7 +62,7 @@ void GatordMockService::SendDeactivateTimelinePacket() std::cout << "Sending deactivate timeline packet." << std::endl; } // The deactivate timeline packet is an empty data packet with packetId == 7. - SendPacket(0, 7, nullptr, 0); + m_BasePipeServer.get()->SendPacket(0, 7, nullptr, 0); } bool GatordMockService::LaunchReceivingThread() @@ -164,13 +72,13 @@ bool GatordMockService::LaunchReceivingThread() std::cout << "Launching receiving thread." << std::endl; } // At this point we want to make the socket non blocking. - if (!Sockets::SetNonBlocking(m_ClientConnection)) + if (!m_BasePipeServer.get()->SetNonBlocking()) { - Sockets::Close(m_ClientConnection); + m_BasePipeServer.get()->Close(); std::cerr << "Failed to set socket as non blocking: " << strerror(errno) << std::endl; return false; } - m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this, std::ref(*this)); + m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this); return true; } @@ -194,6 +102,11 @@ void GatordMockService::WaitForReceivingThread() } } +bool GatordMockService::WaitForStreamMetaData() +{ + return m_BasePipeServer->WaitForStreamMetaData(); +} + void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::vector counters) { // The packet body consists of a UINT32 representing the period following by zero or more @@ -204,7 +117,6 @@ void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::v { std::cout << "SendPeriodicCounterSelectionList: Period=" << std::dec << period << "uSec" << std::endl; std::cout << "List length=" << counters.size() << std::endl; - ; } // Start by calculating the length of the packet body in bytes. This will be at least 4. uint32_t dataLength = static_cast(4 + (counters.size() * 2)); @@ -222,7 +134,7 @@ void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::v } // Send the packet. - SendPacket(0, 4, data, dataLength); + m_BasePipeServer.get()->SendPacket(0, 4, data, dataLength); // There will be an echo response packet sitting in the receive thread. PeriodicCounterSelectionResponseHandler // should deal with it. } @@ -245,14 +157,29 @@ void GatordMockService::WaitCommand(uint32_t timeout) } } -void GatordMockService::ReceiveLoop(GatordMockService& mockService) +void GatordMockService::ReceiveLoop() { m_CloseReceivingThread.store(false); while (!m_CloseReceivingThread.load()) { try { - armnn::profiling::Packet packet = mockService.WaitForPacket(500); + profiling::Packet packet = m_BasePipeServer.get()->WaitForPacket(500); + + profiling::PacketVersionResolver packetVersionResolver; + + profiling::Version version = + packetVersionResolver.ResolvePacketVersion(packet.GetPacketFamily(), packet.GetPacketId()); + + profiling::CommandHandlerFunctor* commandHandlerFunctor = m_HandlerRegistry.GetFunctor( + packet.GetPacketFamily(), + packet.GetPacketId(), + version.GetEncodedValue()); + + + + ARMNN_ASSERT(commandHandlerFunctor); + commandHandlerFunctor->operator()(packet); } catch (const armnn::TimeoutException&) { @@ -272,230 +199,6 @@ void GatordMockService::ReceiveLoop(GatordMockService& mockService) } } -armnn::profiling::Packet GatordMockService::WaitForPacket(uint32_t timeoutMs) -{ - // Is there currently more than a headers worth of data waiting to be read? - int bytes_available; - Sockets::Ioctl(m_ClientConnection, FIONREAD, &bytes_available); - if (bytes_available > 8) - { - // Yes there is. Read it: - return ReceivePacket(); - } - else - { - // No there's not. Poll for more data. - struct pollfd pollingFd[1]{}; - pollingFd[0].fd = m_ClientConnection; - int pollResult = Sockets::Poll(pollingFd, 1, static_cast(timeoutMs)); - - switch (pollResult) - { - // Error - case -1: - throw armnn::RuntimeException(std::string("File descriptor reported an error during polling: ") + - strerror(errno)); - - // Timeout - case 0: - throw armnn::TimeoutException("Timeout while waiting to receive packet."); - - // Normal poll return. It could still contain an error signal - default: - // Check if the socket reported an error - if (pollingFd[0].revents & (POLLNVAL | POLLERR | POLLHUP)) - { - if (pollingFd[0].revents == POLLNVAL) - { - throw armnn::RuntimeException(std::string("Error while polling receiving socket: POLLNVAL")); - } - if (pollingFd[0].revents == POLLERR) - { - throw armnn::RuntimeException(std::string("Error while polling receiving socket: POLLERR: ") + - strerror(errno)); - } - if (pollingFd[0].revents == POLLHUP) - { - throw armnn::RuntimeException(std::string("Connection closed by remote client: POLLHUP")); - } - } - - // Check if there is data to read - if (!(pollingFd[0].revents & (POLLIN))) - { - // This is a corner case. The socket as been woken up but not with any data. - // We'll throw a timeout exception to loop around again. - throw armnn::TimeoutException("File descriptor was polled but no data was available to receive."); - } - return ReceivePacket(); - } - } -} - -armnn::profiling::Packet GatordMockService::ReceivePacket() -{ - uint32_t header[2]; - if (!ReadHeader(header)) - { - return armnn::profiling::Packet(); - } - // Read data_length bytes from the socket. - std::unique_ptr uniquePacketData = std::make_unique(header[1]); - unsigned char* packetData = reinterpret_cast(uniquePacketData.get()); - - if (!ReadFromSocket(packetData, header[1])) - { - return armnn::profiling::Packet(); - } - - EchoPacket(PacketDirection::ReceivedData, packetData, header[1]); - - // Construct received packet - armnn::profiling::PacketVersionResolver packetVersionResolver; - armnn::profiling::Packet packetRx = armnn::profiling::Packet(header[0], header[1], uniquePacketData); - if (m_EchoPackets) - { - std::cout << "Processing packet ID= " << packetRx.GetPacketId() << " Length=" << packetRx.GetLength() - << std::endl; - } - - profiling::Version version = - packetVersionResolver.ResolvePacketVersion(packetRx.GetPacketFamily(), packetRx.GetPacketId()); - - profiling::CommandHandlerFunctor* commandHandlerFunctor = - m_HandlerRegistry.GetFunctor(packetRx.GetPacketFamily(), packetRx.GetPacketId(), version.GetEncodedValue()); - ARMNN_ASSERT(commandHandlerFunctor); - commandHandlerFunctor->operator()(packetRx); - return packetRx; -} - -bool GatordMockService::SendPacket(uint32_t packetFamily, uint32_t packetId, const uint8_t* data, uint32_t dataLength) -{ - // Construct a packet from the id and data given and send it to the client. - // Encode the header. - uint32_t header[2]; - header[0] = packetFamily << 26 | packetId << 16; - header[1] = dataLength; - // Add the header to the packet. - std::vector packet(8 + dataLength); - InsertU32(header[0], packet.data(), m_Endianness); - InsertU32(header[1], packet.data() + 4, m_Endianness); - // And the rest of the data if there is any. - if (dataLength > 0) - { - memcpy((packet.data() + 8), data, dataLength); - } - EchoPacket(PacketDirection::Sending, packet.data(), packet.size()); - if (-1 == Sockets::Write(m_ClientConnection, packet.data(), packet.size())) - { - std::cerr << ": Failure when writing to client socket: " << strerror(errno) << std::endl; - return false; - } - return true; -} - -bool GatordMockService::ReadHeader(uint32_t headerAsWords[2]) -{ - // The header will always be 2x32bit words. - uint8_t header[8]; - if (!ReadFromSocket(header, 8)) - { - return false; - } - EchoPacket(PacketDirection::ReceivedHeader, header, 8); - headerAsWords[0] = ToUint32(&header[0], m_Endianness); - headerAsWords[1] = ToUint32(&header[4], m_Endianness); - return true; -} - -bool GatordMockService::ReadFromSocket(uint8_t* packetData, uint32_t expectedLength) -{ - // This is a blocking read until either expectedLength has been received or an error is detected. - long totalBytesRead = 0; - while (boost::numeric_cast(totalBytesRead) < expectedLength) - { - long bytesRead = Sockets::Read(m_ClientConnection, packetData, expectedLength); - if (bytesRead < 0) - { - std::cerr << ": Failure when reading from client socket: " << strerror(errno) << std::endl; - return false; - } - if (bytesRead == 0) - { - std::cerr << ": EOF while reading from client socket." << std::endl; - return false; - } - totalBytesRead += bytesRead; - } - return true; -}; - -void GatordMockService::EchoPacket(PacketDirection direction, uint8_t* packet, size_t lengthInBytes) -{ - // If enabled print the contents of the data packet to the console. - if (m_EchoPackets) - { - if (direction == PacketDirection::Sending) - { - std::cout << "TX " << std::dec << lengthInBytes << " bytes : "; - } - else if (direction == PacketDirection::ReceivedHeader) - { - std::cout << "RX Header " << std::dec << lengthInBytes << " bytes : "; - } - else - { - std::cout << "RX Data " << std::dec << lengthInBytes << " bytes : "; - } - for (unsigned int i = 0; i < lengthInBytes; i++) - { - if ((i % 10) == 0) - { - std::cout << std::endl; - } - std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << static_cast(packet[i]) - << " "; - } - std::cout << std::endl; - } -} - -uint32_t GatordMockService::ToUint32(uint8_t* data, TargetEndianness endianness) -{ - // Extract the first 4 bytes starting at data and push them into a 32bit integer based on the - // specified endianness. - if (endianness == TargetEndianness::BeWire) - { - return static_cast(data[0]) << 24 | static_cast(data[1]) << 16 | - static_cast(data[2]) << 8 | static_cast(data[3]); - } - else - { - return static_cast(data[3]) << 24 | static_cast(data[2]) << 16 | - static_cast(data[1]) << 8 | static_cast(data[0]); - } -} - -void GatordMockService::InsertU32(uint32_t value, uint8_t* data, TargetEndianness endianness) -{ - // Take the bytes of a 32bit integer and copy them into char array starting at data considering - // the endianness value. - if (endianness == TargetEndianness::BeWire) - { - *data = static_cast((value >> 24) & 0xFF); - *(data + 1) = static_cast((value >> 16) & 0xFF); - *(data + 2) = static_cast((value >> 8) & 0xFF); - *(data + 3) = static_cast(value & 0xFF); - } - else - { - *(data + 3) = static_cast((value >> 24) & 0xFF); - *(data + 2) = static_cast((value >> 16) & 0xFF); - *(data + 1) = static_cast((value >> 8) & 0xFF); - *data = static_cast(value & 0xFF); - } -} - } // namespace gatordmock } // namespace armnn -- cgit v1.2.1