8 #define DRIPLINE_API_EXPORTS
21 #include "pybind11/pybind11.h"
22 #include "pybind11/pytypes.h"
25 LOGGER(
dlog,
"endpoint" );
40 if( f_service ==
nullptr )
throw dripline_error() <<
"Parent service pointer for endpoint <" << f_name <<
"> is null";
46 if( f_service ==
nullptr )
throw dripline_error() <<
"Parent service pointer for endpoint <" << f_name <<
"> is null";
71 auto t_replier = [&t_reply, &a_request,
this](){
73 if( a_request->reply_to().empty() )
75 LWARN(
dlog,
"Not sending reply (reply-to empty)\n" <<
76 " Return code: " << t_reply->get_return_code() <<
'\n' <<
77 " Return message: " << t_reply->return_message() <<
'\n' <<
78 " Payload:\n" << t_reply->payload() );
88 if( ! a_request->get_is_valid() )
90 std::string t_message(
"Request message was not valid" );
92 if( a_request->payload().is_node() )
94 const scarab::param_node& t_payload = a_request->payload().as_node();
95 if( t_payload.has(
"error") ) t_message +=
"; " + t_payload[
"error"]().as_string();
101 if( ! a_request->get_lockout_key_valid() )
106 switch( a_request->get_message_operation() )
145 catch(
const pybind11::error_already_set& e )
149 if( std::string(e.what()).substr(0, throw_reply::py_throw_reply_keyword().size()) == throw_reply::py_throw_reply_keyword() )
151 reply_cache* t_reply_cache = reply_cache::get_instance();
168 LERROR(
dlog,
"Caught exception from Python: " << e.what() );
175 catch(
const std::exception& e )
177 LERROR(
dlog,
"Caught exception: " << e.what() );
191 if( a_message->is_request() )
195 else if( a_message->is_alert() )
199 else if( a_message->is_reply() )
213 LWARN(
dlog,
"Cannot send reply because the service pointer is not set" );
217 LDEBUG(
dlog,
"Sending reply message to <" << a_reply->routing_key() <<
">:\n" <<
218 " Return code: " << a_reply->get_return_code() <<
'\n' <<
219 " Return message: " << a_reply->return_message() <<
'\n' <<
220 " Payload:\n" << a_reply->payload() );
225 t_receive_reply = f_service->send( a_reply );
229 LWARN(
dlog,
"Operating in offline mode; message not sent" );
234 LERROR(
dlog,
"Unable to connect to the broker:\n" << e.what() );
239 LERROR(
dlog,
"Dripline error while sending reply:\n" << e.what() );
243 if( ! t_receive_reply->f_successful_send )
245 LERROR(
dlog,
"Failed to send reply:\n" + t_receive_reply->f_send_error_message );
254 throw dripline_error() <<
"Base endpoint does not handle reply messages";
259 throw dripline_error() <<
"Base endpoint does not handle alert messages";
264 LDEBUG(
dlog,
"Run operation request received" );
268 std::stringstream t_conv;
269 t_conv << a_request->lockout_key();
270 std::string t_message(
"Request denied due to lockout (key used: " + t_conv.str() +
")" );
271 LINFO(
dlog, t_message );
280 LDEBUG(
dlog,
"Get operation request received" );
282 std::string t_query_type;
283 if( ! a_request->parsed_specifier().empty() )
285 t_query_type = a_request->parsed_specifier().front();
288 if( t_query_type ==
"is-locked" )
290 a_request->parsed_specifier().pop_front();
299 LDEBUG(
dlog,
"Set request received" );
303 std::stringstream t_conv;
304 t_conv << a_request->lockout_key();
305 std::string t_message(
"Request denied due to lockout (key used: " + t_conv.str() +
")" );
306 LINFO(
dlog, t_message );
315 LDEBUG(
dlog,
"Cmd request received" );
317 std::string t_instruction;
318 if( ! a_request->parsed_specifier().empty() )
320 t_instruction = a_request->parsed_specifier().front();
326 if( !
authenticate( a_request->lockout_key() ) && t_instruction !=
"unlock" && t_instruction !=
"ping" && t_instruction !=
"set_condition" )
328 std::stringstream t_conv;
329 t_conv << a_request->lockout_key();
330 std::string t_message(
"Request denied due to lockout (key used: " + t_conv.str() +
")" );
331 LINFO(
dlog, t_message );
335 if( t_instruction ==
"lock" )
337 a_request->parsed_specifier().pop_front();
340 else if( t_instruction ==
"unlock" )
342 a_request->parsed_specifier().pop_front();
345 else if( t_instruction ==
"ping" )
347 a_request->parsed_specifier().pop_front();
350 else if( t_instruction ==
"set_condition" )
352 a_request->parsed_specifier().pop_front();
363 else f_lockout_key = a_key;
364 f_lockout_tag = a_tag;
365 return f_lockout_key;
371 if( ! a_force && a_key != f_lockout_key )
return false;
373 f_lockout_tag.clear();
379 LDEBUG(
dlog,
"Authenticating with key <" << a_key <<
">" );
387 if( t_new_key.is_nil() )
392 scarab::param_ptr_t t_payload_ptr(
new scarab::param_node() );
393 scarab::param_node& t_payload_node = t_payload_ptr->as_node();
395 return a_request->reply(
dl_success(),
"Server is now locked", std::move(t_payload_ptr) );
405 bool t_force = a_request->payload().get_value(
"force",
false );
409 return a_request->reply(
dl_success(),
"Server unlocked" );
422 scarab::param_ptr_t t_reply_payload(
new scarab::param_node() );
423 scarab::param_node& t_reply_node = t_reply_payload->as_node();
424 t_reply_node.add(
"is_locked", t_is_locked );
425 if( t_is_locked ) t_reply_node.add(
"tag", f_lockout_tag );
426 return a_request->reply(
dl_success(),
"Checked lock status", std::move(t_reply_payload) );
431 return a_request->reply(
dl_success(),
"Hello, " + a_request->sender_exe() );
Error indicating a problem with the connection to the broker.
Dripline-specific errors.
virtual reply_ptr_t on_request_message(const request_ptr_t a_request)
Default request handler; passes request to initial request functions.
bool disable_lockout(const uuid_t &a_key, bool a_force=false)
reply_ptr_t handle_lock_request(const request_ptr_t a_request)
reply_ptr_t handle_ping_request(const request_ptr_t a_request)
reply_ptr_t __do_get_request(const request_ptr_t a_request)
virtual reply_ptr_t __do_handle_set_condition_request(const request_ptr_t a_request)
Default set-condition: no action taken; override for different behavior.
endpoint(const std::string &a_name)
virtual void send_reply(reply_ptr_t a_reply) const
reply_ptr_t handle_unlock_request(const request_ptr_t a_request)
virtual reply_ptr_t do_cmd_request(const request_ptr_t a_request)
virtual void on_alert_message(const alert_ptr_t a_alert)
reply_ptr_t __do_set_request(const request_ptr_t a_request)
reply_ptr_t handle_set_condition_request(const request_ptr_t a_request)
void sort_message(const message_ptr_t a_request)
bool authenticate(const uuid_t &a_key) const
Returns true if the server is unlocked or if it's locked and the key matches the lockout key; returns...
void submit_reply_message(const reply_ptr_t a_reply)
Directly submit a reply message to this endpoint.
virtual reply_ptr_t do_get_request(const request_ptr_t a_request)
reply_ptr_t __do_run_request(const request_ptr_t a_request)
bool check_key(const uuid_t &a_key) const
reply_ptr_t __do_cmd_request(const request_ptr_t a_request)
void submit_alert_message(const alert_ptr_t a_alert)
Directly submit an alert message to this endpoint.
uuid_t enable_lockout(const scarab::param_node &a_tag)
enable lockout with randomly-generated key
virtual reply_ptr_t do_run_request(const request_ptr_t a_request)
reply_ptr_t submit_request_message(const request_ptr_t a_request)
Directly submit a request message to this endpoint.
virtual void on_reply_message(const reply_ptr_t a_reply)
reply_ptr_t handle_is_locked_request(const request_ptr_t a_request)
virtual reply_ptr_t do_set_request(const request_ptr_t a_request)
A singleton throw_reply object used to transfer throw_reply information to C++ from other implementat...
Primary unit of software that connects to a broker and typically provides an interface with an instru...
Object that can be thrown while processing a request to send a reply.
const return_code & ret_code() const noexcept
const scarab::param_ptr_t & get_payload_ptr() const noexcept
const std::string & return_message() const noexcept
static ::scarab::logger_type< ::scarab::spd_initializer_async_stdout_color_mt > dlog("endpoint", __FILE_NAME__, __LINE__)
std::string string_from_uuid(const uuid_t &a_id)
Generates a string representation of the provided UUID.
std::shared_ptr< msg_alert > alert_ptr_t
std::shared_ptr< message > message_ptr_t
std::shared_ptr< sent_msg_pkg > sent_msg_pkg_ptr
std::shared_ptr< msg_reply > reply_ptr_t
uuid_t generate_random_uuid()
Generates a UUID containing random numbers (RNG is a Mersenne Twister)
static ::scarab::logger_type< ::scarab::spd_initializer_async_stdout_color_mt > dlog("agent", __FILE_NAME__, __LINE__)
std::shared_ptr< msg_request > request_ptr_t
uuid_t generate_nil_uuid()
Generates a UUID containing all 0s.
boost::uuids::uuid uuid_t
Universally-unique-identifier type containing 16 hexadecimal characters.
virtual unsigned rc_value() const =0