1 // 2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #pragma once 7 8 #include <common/include/NetworkSockets.hpp> 9 #include <common/include/Packet.hpp> 10 #include <common/include/SocketConnectionException.hpp> 11 12 #include <string> 13 #include <atomic> 14 15 namespace arm 16 { 17 18 namespace pipe 19 { 20 21 enum class TargetEndianness 22 { 23 BeWire, 24 LeWire 25 }; 26 27 enum class PacketDirection 28 { 29 Sending, 30 ReceivedHeader, 31 ReceivedData 32 }; 33 class ConnectionHandler; 34 35 class BasePipeServer 36 { 37 38 public: 39 BasePipeServer(arm::pipe::Socket clientConnection,bool echoPackets)40 BasePipeServer(arm::pipe::Socket clientConnection, bool echoPackets) 41 : m_ClientConnection(clientConnection) 42 , m_EchoPackets(echoPackets) 43 {} 44 ~BasePipeServer()45 ~BasePipeServer() 46 { 47 // We have set SOCK_CLOEXEC on this socket but we'll close it to be good citizens. 48 arm::pipe::Close(m_ClientConnection); 49 } 50 51 BasePipeServer(const BasePipeServer&) = delete; 52 BasePipeServer& operator=(const BasePipeServer&) = delete; 53 54 BasePipeServer(BasePipeServer&&) = delete; 55 BasePipeServer& operator=(BasePipeServer&&) = delete; 56 57 /// Close the client connection 58 /// @return 0 if successful Close()59 int Close() 60 { 61 return arm::pipe::Close(m_ClientConnection); 62 } 63 64 /// Send a packet to the client 65 /// @return true if a valid packet has been sent. 66 bool SendPacket(uint32_t packetFamily, uint32_t packetId, const uint8_t* data, uint32_t dataLength); 67 68 /// Set the client socket to nonblocking 69 /// @return true if successful. SetNonBlocking()70 bool SetNonBlocking() 71 { 72 return arm::pipe::SetNonBlocking(m_ClientConnection); 73 } 74 75 /// Block on the client connection until a complete packet has been received. 76 /// @return true if a valid packet has been received. 77 arm::pipe::Packet WaitForPacket(uint32_t timeoutMs); 78 79 /// Once the connection is open wait to receive the stream meta data packet from the client. Reading this 80 /// packet differs from others as we need to determine endianness. 81 /// @return true only if a valid stream meta data packet has been received. 82 bool WaitForStreamMetaData(); 83 GetStreamMetadataVersion()84 uint32_t GetStreamMetadataVersion() 85 { 86 return m_StreamMetaDataVersion; 87 } 88 GetStreamMetadataMaxDataLen()89 uint32_t GetStreamMetadataMaxDataLen() 90 { 91 return m_StreamMetaDataMaxDataLen; 92 } 93 GetStreamMetadataPid()94 uint32_t GetStreamMetadataPid() 95 { 96 return m_StreamMetaDataPid; 97 } 98 99 private: 100 101 void EchoPacket(PacketDirection direction, uint8_t* packet, size_t lengthInBytes); 102 bool ReadFromSocket(uint8_t* packetData, uint32_t expectedLength); 103 bool ReadHeader(uint32_t headerAsWords[2]); 104 105 arm::pipe::Packet ReceivePacket(); 106 107 uint32_t ToUint32(uint8_t* data, TargetEndianness endianness); 108 void InsertU32(uint32_t value, uint8_t* data, TargetEndianness endianness); 109 110 arm::pipe::Socket m_ClientConnection; 111 bool m_EchoPackets; 112 TargetEndianness m_Endianness; 113 114 uint32_t m_StreamMetaDataVersion; 115 uint32_t m_StreamMetaDataMaxDataLen; 116 uint32_t m_StreamMetaDataPid; 117 }; 118 119 } // namespace pipe 120 } // namespace arm 121