39 #include <boost/asio.hpp> 40 #include <boost/fusion/adapted/std_pair.hpp> 41 #include <boost/spirit/include/qi.hpp> 42 #include <boost/spirit/include/qi_eps.hpp> 52 NameValuePairVectorType::const_iterator lIt = aUri.
mArguments.begin();
56 if ( lIt->first ==
"target" )
64 exception::XMLfileMissingRequiredParameters lExc;
65 log ( lExc ,
"Expected URI arguments of the form " ,
Quote (
"target=192.168.200.200:50001" ) ,
". It appears that this is missing in URI " , aUri );
69 std::pair< std::string , std::string > lIP;
73 boost::spirit::qi::phrase_parse ( lIt->second.begin() ,
75 ( boost::spirit::qi::eps >
76 * ( boost::spirit::qi::char_ - boost::spirit::qi::lit (
":" ) ) >
77 boost::spirit::qi::lit (
":" ) >
78 *boost::spirit::qi::char_
80 boost::spirit::ascii::space ,
84 catch (
const std::exception& aExc )
86 exception::ParsingTargetURLfailed lExc;
87 log ( lExc ,
"Expected a string of the form " ,
Quote (
"hostIP:port" ) ,
" or " ,
Quote (
"hostname:port" ) ,
" but received " ,
Quote ( lIt->second ) ,
"." );
96 boost::asio::io_service lService;
97 boost::asio::ip::udp::endpoint lEndpoint (
98 *boost::asio::ip::udp::resolver::iterator (
99 boost::asio::ip::udp::resolver ( lService ).resolve (
100 boost::asio::ip::udp::resolver::query ( boost::asio::ip::udp::v4() , lIP.first , lIP.second )
104 lAddr = lEndpoint.address().to_string();
105 lPort = lEndpoint.port();
107 catch (
const std::exception& aExc )
109 exception::HostnameToIPlookupFailed lExc;
110 log ( lExc ,
"Hostname to IP look up failed for hostname=" , lIP.first ,
", port=" , lIP.second );
111 log ( lExc ,
"ASIO threw exception with what returning: ",
Quote ( aExc.what() ) );
115 std::vector< uint32_t > lIPAddr;
119 boost::spirit::qi::phrase_parse ( lAddr.begin() ,
121 ( boost::spirit::qi::eps >
122 boost::spirit::qi::uint_ > boost::spirit::qi::lit (
"." ) >
123 boost::spirit::qi::uint_ > boost::spirit::qi::lit (
"." ) >
124 boost::spirit::qi::uint_ > boost::spirit::qi::lit (
"." ) >
125 boost::spirit::qi::uint_ ),
126 boost::spirit::ascii::space ,
130 catch (
const std::exception& aExc )
132 exception::ParsingTargetURLfailed lExc;
133 log ( lExc ,
"Boost::ASIO returned address " ,
Quote ( lAddr ) ,
" for hostname " ,
Quote (lIP.first) ,
" which could not be parsed as " ,
Quote (
"aaa.bbb.ccc.ddd" ) );
137 uint32_t lIPaddress = ( lIPAddr[0] <<24 ) | ( lIPAddr[1] <<16 ) | ( lIPAddr[2] <<8 ) | ( lIPAddr[3] );
138 log (
Info() ,
"Converted IP address string " ,
Quote ( lIt->second ) ,
" to " ,
141 return std::make_pair ( lIPaddress , lPort );
145 template <
typename InnerProtocol >
147 InnerProtocol ( aId , aUri ),
148 mDeviceIPaddress ( 0 ),
158 template <
typename InnerProtocol >
165 template <
typename InnerProtocol >
188 lPreambles->
mSendWordCountPtr = ( uint16_t* ) ( aBuffers->send ( ( uint16_t ) ( 0 ) ) );
195 InnerProtocol::preamble ( aBuffers );
200 template <
typename InnerProtocol >
203 return InnerProtocol::getPreambleSize() +2;
207 template <
typename InnerProtocol >
210 InnerProtocol::predispatch ( aBuffers );
214 uint32_t lByteCount ( aBuffers->sendCounter() );
220 template <
typename InnerProtocol >
222 uint8_t* aSendBufferEnd ,
223 std::deque< std::pair< uint8_t* , uint32_t > >::iterator aReplyStartIt ,
224 std::deque< std::pair< uint8_t* , uint32_t > >::iterator aReplyEndIt )
228 uint32_t lReplyIPaddress ( * ( ( uint32_t* ) ( aReplyStartIt->first ) ) );
232 uhal::exception::ControlHubReturnedWrongAddress* lExc =
new uhal::exception::ControlHubReturnedWrongAddress();
235 " for device with URI: " , this->
uri() );
242 uint16_t lReplyPort ( * ( ( uint16_t* ) ( aReplyStartIt->first ) ) );
246 uhal::exception::ControlHubReturnedWrongAddress* lExc =
new uhal::exception::ControlHubReturnedWrongAddress();
247 log ( *lExc ,
"Returned Port number " ,
Integer ( lReplyPort ) ,
249 " for device with URI: " , this->
uri() );
256 uint16_t lErrorCode ( ntohs ( * ( ( uint16_t* ) ( aReplyStartIt->first ) ) ) );
258 if ( lErrorCode != 0 )
263 if ( lErrorCode == 1 || lErrorCode == 3 || lErrorCode == 4 )
265 uhal::exception::ControlHubTargetTimeout* lExc =
new uhal::exception::ControlHubTargetTimeout();
266 log ( *lExc ,
"The ControlHub did not receive any response from the target with URI ",
Quote(this->
uri()) );
271 uhal::exception::ControlHubErrorCodeSet* lExc =
new uhal::exception::ControlHubErrorCodeSet();
274 " for target with URI " ,
Quote(this->
uri()) );
284 return InnerProtocol::validate ( ( aSendBufferStart+=8 ) , aSendBufferEnd , ( ++aReplyStartIt ) , aReplyEndIt );
289 template <
typename InnerProtocol >
297 InnerProtocol::dispatchExceptionHandler();
301 template <
typename InnerProtocol >
304 switch (aErrorCode) {
306 aStream <<
"success";
309 aStream <<
"no reply to control packet";
312 aStream <<
"internal timeout within ControlHub";
315 aStream <<
"no reply to status packet";
318 aStream <<
"no reply to resend request";
321 aStream <<
"malformed status packet received";
324 aStream <<
"request uses incorrect protocol version";
327 aStream <<
"UNKNOWN";
virtual uint32_t getPreambleSize()
Get the size of the preamble added by this protocol layer.
uint32_t mDeviceIPaddress
The IP address of the target device that is connected to the Control Hub.
virtual void dispatchExceptionHandler()
Function which tidies up this protocol layer in the event of an exception.
uint32_t mReplyChunkByteCounter
A legacy counter.
ControlHub(const std::string &aId, const URI &aUri)
Constructor.
uint32_t mReplyDeviceIPaddress
The returned target device ID (IP address)
uint16_t * mSendWordCountPtr
The number of 32-bit words in the IPbus packet (legacy and could be removed)
boost::mutex mPreamblesMutex
Mutex to be used when accessing mPreambles.
An abstract base exception class providing an interface to a throw/ThrowAsDerivedType mechanism which...
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 preamble(boost::shared_ptr< Buffers > aBuffers)
Add a preamble to an IPbus buffer.
std::deque< tpreamble > mPreambles
A queue of preample structs making the memory used by the preambles persistent during the dispatch...
A struct representing the preamble which will be prepended to an IPbus buffer for the benefit of the ...
std::pair< uint32_t, uint16_t > ExtractTargetID(const URI &aUri)
Extract an IP-address and port number from a URI object.
Transport protocol to transfer an IPbus buffer via ControlHub.
NameValuePairVectorType mArguments
The "key1=val1&key2=val2&key3=val3" part of a URI of the form "protocol://host:port/patha/pathb/blah...
Empty struct which acts as a dummy variable for passing the formatting information around...
_Quote< T > Quote(const T &aT)
static void translateErrorCode(std::ostream &aStream, const uint16_t &aErrorCode)
virtual void predispatch(boost::shared_ptr< Buffers > aBuffers)
Finalize an IPbus buffer before it is transmitted.
uint16_t mReplyErrorCode
An error code returned describing the status of the control hub.
virtual ~ControlHub()
Destructor.
uint16_t mReplyDevicePort
The returned target device ID (port number)
uint16_t mDevicePort
The port number of the target device that is connected to the Control Hub.
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
Struct to store a URI when parsed by boost spirit.