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 ),
157 template <
typename InnerProtocol >
163 template <
typename InnerProtocol >
179 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
181 tpreamble* lPreambles = & mPreambles.back();
183 aBuffers->send ( mDeviceIPaddress );
184 aBuffers->send ( mDevicePort );
185 lPreambles->
mSendWordCountPtr = ( uint16_t* ) ( aBuffers->send ( ( uint16_t ) ( 0 ) ) );
192 InnerProtocol::preamble ( aBuffers );
197 template <
typename InnerProtocol >
200 return InnerProtocol::getPreambleSize() + 2;
204 template <
typename InnerProtocol >
207 InnerProtocol::predispatch ( aBuffers );
208 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
209 tpreamble& lPreambles = mPreambles.back();
210 uint32_t lByteCount ( aBuffers->sendCounter() );
215 template <
typename InnerProtocol >
217 uint8_t* aSendBufferEnd ,
218 std::deque< std::pair< uint8_t* , uint32_t > >::iterator aReplyStartIt ,
219 std::deque< std::pair< uint8_t* , uint32_t > >::iterator aReplyEndIt )
222 uint32_t lReplyIPaddress ( * ( ( uint32_t* ) ( aReplyStartIt->first ) ) );
224 if ( lReplyIPaddress != mDeviceIPaddress )
226 uhal::exception::ControlHubReturnedWrongAddress* lExc =
new uhal::exception::ControlHubReturnedWrongAddress();
229 " for device with URI: " , this->
uri() );
230 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
231 mPreambles.pop_front();
236 uint16_t lReplyPort ( * ( ( uint16_t* ) ( aReplyStartIt->first ) ) );
238 if ( lReplyPort != mDevicePort )
240 uhal::exception::ControlHubReturnedWrongAddress* lExc =
new uhal::exception::ControlHubReturnedWrongAddress();
241 log ( *lExc ,
"Returned Port number " ,
Integer ( lReplyPort ) ,
242 " does not match that sent " ,
Integer ( mDevicePort ) ,
243 " for device with URI: " , this->
uri() );
244 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
245 mPreambles.pop_front();
250 uint16_t lErrorCode ( ntohs ( * ( ( uint16_t* ) ( aReplyStartIt->first ) ) ) );
252 if ( lErrorCode != 0 )
254 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
255 mPreambles.pop_front();
257 if ( lErrorCode == 1 || lErrorCode == 3 || lErrorCode == 4 )
259 uhal::exception::ControlHubTargetTimeout* lExc =
new uhal::exception::ControlHubTargetTimeout();
260 log ( *lExc ,
"The ControlHub did not receive any response from the target with URI ",
Quote(this->
uri()) );
265 uhal::exception::ControlHubErrorCodeSet* lExc =
new uhal::exception::ControlHubErrorCodeSet();
268 " for target with URI " ,
Quote(this->
uri()) );
273 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
274 mPreambles.pop_front();
276 return InnerProtocol::validate ( ( aSendBufferStart+=8 ) , aSendBufferEnd , ( ++aReplyStartIt ) , aReplyEndIt );
280 template <
typename InnerProtocol >
287 template <
typename InnerProtocol >
291 boost::lock_guard<boost::mutex> lPreamblesLock ( mPreamblesMutex );
294 InnerProtocol::dispatchExceptionHandler();
298 template <
typename InnerProtocol >
301 switch (aErrorCode) {
303 aStream <<
"success";
306 aStream <<
"no reply to control packet";
309 aStream <<
"internal timeout within ControlHub";
312 aStream <<
"no reply to status packet";
315 aStream <<
"no reply to resend request";
318 aStream <<
"malformed status packet received";
321 aStream <<
"request uses incorrect protocol version";
324 aStream <<
"UNKNOWN";