40#include <boost/asio.hpp> 
   41#include <boost/fusion/adapted/std_pair.hpp> 
   42#include <boost/spirit/include/qi.hpp> 
   43#include <boost/spirit/include/qi_eps.hpp> 
   53    NameValuePairVectorType::const_iterator lIt = aUri.
mArguments.begin();
 
   57      if ( lIt->first == 
"target" )
 
   65      exception::XMLfileMissingRequiredParameters lExc;
 
   66      log ( lExc , 
"Expected URI arguments of the form " , 
Quote ( 
"target=192.168.200.200:50001" ) ,
". It appears that this is missing in URI " , aUri );
 
   70    std::pair< std::string , std::string > lIP;
 
   74      boost::spirit::qi::phrase_parse ( lIt->second.begin() ,
 
   76                                        ( boost::spirit::qi::eps >
 
   77                                          * ( boost::spirit::qi::char_ - boost::spirit::qi::lit ( 
":" ) ) >
 
   78                                          boost::spirit::qi::lit ( 
":" ) >
 
   79                                          *boost::spirit::qi::char_
 
   81                                        boost::spirit::ascii::space ,
 
   85    catch ( 
const std::exception& aExc )
 
   87      exception::ParsingTargetURLfailed lExc;
 
   88      log ( lExc , 
"Expected a string of the form " , 
Quote ( 
"hostIP:port" ) , 
" or " , 
Quote ( 
"hostname:port" ) , 
" but received " , 
Quote ( lIt->second ) , 
"." );
 
   97      boost::asio::io_service lService;
 
   98      boost::asio::ip::udp::endpoint lEndpoint (
 
   99        *boost::asio::ip::udp::resolver::iterator (
 
  100          boost::asio::ip::udp::resolver ( lService ).resolve (
 
  101            boost::asio::ip::udp::resolver::query ( boost::asio::ip::udp::v4() , lIP.first , lIP.second )
 
  105      lAddr = lEndpoint.address().to_string();
 
  106      lPort = lEndpoint.port();
 
  108    catch ( 
const std::exception& aExc )
 
  110      exception::HostnameToIPlookupFailed lExc;
 
  111      log ( lExc , 
"Hostname to IP look up failed for hostname=" , lIP.first , 
", port=" , lIP.second );
 
  112      log ( lExc , 
"ASIO threw exception with what returning: ", 
Quote ( aExc.what() ) );
 
  116    std::vector< uint32_t > lIPAddr;
 
  120      boost::spirit::qi::phrase_parse ( lAddr.begin() ,
 
  122                                        ( boost::spirit::qi::eps >
 
  123                                          boost::spirit::qi::uint_ > boost::spirit::qi::lit ( 
"." ) >
 
  124                                          boost::spirit::qi::uint_ > boost::spirit::qi::lit ( 
"." ) >
 
  125                                          boost::spirit::qi::uint_ > boost::spirit::qi::lit ( 
"." ) >
 
  126                                          boost::spirit::qi::uint_ ),
 
  127                                        boost::spirit::ascii::space ,
 
  131    catch ( 
const std::exception& aExc )
 
  133      exception::ParsingTargetURLfailed lExc;
 
  134      log ( lExc , 
"Boost::ASIO returned address " , 
Quote ( lAddr ) , 
" for hostname " , 
Quote (lIP.first) ,  
" which could not be parsed as " , 
Quote ( 
"aaa.bbb.ccc.ddd" ) );
 
  138    uint32_t lIPaddress = ( lIPAddr[0] <<24 ) | ( lIPAddr[1] <<16 ) | ( lIPAddr[2] <<8 ) | ( lIPAddr[3] );
 
  139    log ( 
Info() , 
"Converted IP address string " ,  
Quote ( lIt->second ) , 
" to " ,
 
  142    return std::make_pair ( lIPaddress , lPort );
 
  146  template < 
typename InnerProtocol >
 
  148    InnerProtocol ( aId , aUri ),
 
  149    mDeviceIPaddress ( 0 ),
 
  158  template < 
typename InnerProtocol >
 
  164  template < 
typename InnerProtocol >
 
  180      std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  182      tpreamble* lPreambles = & mPreambles.back();
 
  184      aBuffers->send ( mDeviceIPaddress );
 
  185      aBuffers->send ( mDevicePort );
 
  186      lPreambles->
mSendWordCountPtr = ( uint16_t* ) ( aBuffers->send ( ( uint16_t ) ( 0 ) ) );
 
  193    InnerProtocol::preamble ( aBuffers );
 
  198  template < 
typename InnerProtocol >
 
  201    return InnerProtocol::getPreambleSize() + 2;
 
  205  template < 
typename InnerProtocol >
 
  208    InnerProtocol::predispatch ( aBuffers );
 
  209    std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  210    tpreamble& lPreambles = mPreambles.back();
 
  211    uint32_t lByteCount ( aBuffers->sendCounter() );
 
  216  template < 
typename InnerProtocol >
 
  218      uint8_t* aSendBufferEnd ,
 
  219      std::deque< std::pair< uint8_t* , uint32_t > >
::iterator aReplyStartIt ,
 
  220      std::deque< std::pair< uint8_t* , uint32_t > >
::iterator aReplyEndIt )
 
  223    uint32_t lReplyIPaddress ( * ( ( uint32_t* ) ( aReplyStartIt->first ) ) );
 
  225    if ( lReplyIPaddress != mDeviceIPaddress )
 
  227      uhal::exception::ControlHubReturnedWrongAddress* lExc = 
new uhal::exception::ControlHubReturnedWrongAddress();
 
  230            " for device with URI: " , this->uri() );
 
  231      std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  232      mPreambles.pop_front();
 
  237    uint16_t lReplyPort ( * ( ( uint16_t* ) ( aReplyStartIt->first ) ) );
 
  239    if ( lReplyPort != mDevicePort )
 
  241      uhal::exception::ControlHubReturnedWrongAddress* lExc = 
new uhal::exception::ControlHubReturnedWrongAddress();
 
  242      log ( *lExc , 
"Returned Port number " , 
Integer ( lReplyPort ) ,
 
  243            " does not match that sent " , 
Integer ( mDevicePort ) ,
 
  244            " for device with URI: " , this->uri() );
 
  245      std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  246      mPreambles.pop_front();
 
  251    uint16_t lErrorCode ( ntohs ( * ( ( uint16_t* ) ( aReplyStartIt->first ) ) ) );
 
  253    if ( lErrorCode != 0 )
 
  255      std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  256      mPreambles.pop_front();
 
  258      if ( lErrorCode == 1 || lErrorCode == 3 || lErrorCode == 4 )
 
  260        uhal::exception::ControlHubTargetTimeout* lExc = 
new uhal::exception::ControlHubTargetTimeout();
 
  261        log ( *lExc , 
"The ControlHub did not receive any response from the target with URI ", 
Quote(this->uri()) );
 
  266      uhal::exception::ControlHubErrorCodeSet* lExc = 
new uhal::exception::ControlHubErrorCodeSet();
 
  269            " for target with URI " , 
Quote(this->uri()) );
 
  274      std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  275      mPreambles.pop_front();
 
  277    return InnerProtocol::validate ( ( aSendBufferStart+=8 ) , aSendBufferEnd , ( ++aReplyStartIt ) , aReplyEndIt );
 
  281  template < 
typename InnerProtocol >
 
  288  template < 
typename InnerProtocol >
 
  292      std::lock_guard<std::mutex> lPreamblesLock ( mPreamblesMutex );
 
  295    InnerProtocol::dispatchExceptionHandler();
 
  299  template < 
typename InnerProtocol >
 
  302    switch (aErrorCode) {
 
  304        aStream << 
"success";
 
  307        aStream << 
"no reply to control packet";
 
  310        aStream << 
"internal timeout within ControlHub";
 
  313        aStream << 
"no reply to status packet";
 
  316        aStream << 
"no reply to resend request";
 
  319        aStream << 
"malformed status packet received";
 
  322        aStream << 
"request uses incorrect protocol version";
 
  325        aStream << 
"device is not in the ControlHub's allowlist";
 
  328        aStream << 
"UNKNOWN";
 
\rst Wraps a Python iterator so that it can also be used as a C++ input iterator
 
Transport protocol to transfer an IPbus buffer via ControlHub.
 
virtual void preamble(std::shared_ptr< Buffers > aBuffers)
Add a preamble to an IPbus buffer.
 
ControlHub(const std::string &aId, const URI &aUri)
Constructor.
 
uint32_t mDeviceIPaddress
The IP address of the target device that is connected to the Control Hub.
 
static void translateErrorCode(std::ostream &aStream, const uint16_t &aErrorCode)
 
virtual exception::exception * validate(uint8_t *aSendBufferStart, uint8_t *aSendBufferEnd, std::deque< std::pair< uint8_t *, uint32_t > >::iterator aReplyStartIt, std::deque< std::pair< uint8_t *, uint32_t > >::iterator aReplyEndIt)
Function which the dispatch calls when the reply is received to check that the headers are as expecte...
 
virtual void predispatch(std::shared_ptr< Buffers > aBuffers)
Finalize an IPbus buffer before it is transmitted.
 
virtual void dispatchExceptionHandler()
Function which tidies up this protocol layer in the event of an exception.
 
virtual uint32_t getPreambleSize()
Get the size of the preamble added by this protocol layer.
 
virtual uint32_t getMaxNumberOfBuffers()
Returns the maximum number of buffers that should be in-flight from the uHAL client at any given time...
 
uint16_t mDevicePort
The port number of the target device that is connected to the Control Hub.
 
virtual ~ControlHub()
Destructor.
 
An abstract base exception class, including an interface to throw as the derived type (for passing ex...
 
_Quote< T > Quote(const T &aT)
 
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
 
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
 
std::pair< uint32_t, uint16_t > ExtractTargetID(const URI &aUri)
Extract an IP-address and port number from a URI object.
 
A struct representing the preamble which will be prepended to an IPbus buffer for the benefit of the ...
 
uint16_t * mSendWordCountPtr
The number of 32-bit words in the IPbus packet (legacy and could be removed)
 
uint32_t mReplyChunkByteCounter
A legacy counter.
 
uint16_t mReplyDevicePort
The returned target device ID (port number)
 
uint16_t mReplyErrorCode
An error code returned describing the status of the control hub.
 
uint32_t mReplyDeviceIPaddress
The returned target device ID (IP address)
 
Empty struct which acts as a dummy variable for passing the formatting information around.
 
Struct to store a URI when parsed by boost spirit.
 
NameValuePairVectorType mArguments
The "key1=val1&key2=val2&key3=val3" part of a URI of the form "protocol://host:port/patha/pathb/blah....