void wamp_dealer::process_call_message(const wamp_session_id& session_id, wamp_call_message* call_message) { auto session_itr = m_sessions.find(session_id); if (session_itr == m_sessions.end()) { throw std::logic_error("dealer session does not exist"); } BONEFISH_TRACE("%1%, %2%", *session_itr->second % *call_message); // If the session placing the call does not support the caller role // than do not allow the call to be processed and send an error. if (!session_itr->second->get_role(wamp_role_type::CALLER)) { send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.role_violation"); return; } const auto procedure = call_message->get_procedure(); if (!is_valid_uri(procedure)) { send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.invalid_uri"); return; } auto procedure_registrations_itr = m_procedure_registrations.find(procedure); if (procedure_registrations_itr == m_procedure_registrations.end()) { send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.no_such_procedure"); return; } std::shared_ptr<wamp_session> session = procedure_registrations_itr->second->get_session(); const wamp_request_id request_id = m_request_id_generator.generate(); const wamp_registration_id& registration_id = procedure_registrations_itr->second->get_registration_id(); wamp_call_options call_options; call_options.unmarshal(call_message->get_options()); // You can't rely on simply assigning the call options to the invocation // details. Some call options may only be applicable to the dealer and // not the callee. Likewise, some invocation details may be in addition // to whatever is provided in the call options. As a result, we only copy // specific options over to the invocation details. wamp_invocation_details invocation_details; if (call_options.get_option_or("receive_progress", false)) { invocation_details.set_detail("receive_progress", true); } std::unique_ptr<wamp_invocation_message> invocation_message( new wamp_invocation_message(call_message->release_zone())); invocation_message->set_request_id(request_id); invocation_message->set_registration_id(registration_id); invocation_message->set_details(invocation_details.marshal(invocation_message->get_zone())); invocation_message->set_arguments(call_message->get_arguments()); invocation_message->set_arguments_kw(call_message->get_arguments_kw()); BONEFISH_TRACE("%1%, %2%", *session_itr->second % *invocation_message); if (!session->get_transport()->send_message(std::move(*invocation_message))) { BONEFISH_TRACE("sending invocation message to callee failed: network failure"); send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.network_failure"); return; } unsigned timeout_ms = call_options.get_option_or<unsigned>("timeout", 0); // We only setup the invocation state after sending the message is successful. // This saves us from having to cleanup any state if the send fails. std::unique_ptr<wamp_dealer_invocation> dealer_invocation( new wamp_dealer_invocation(m_io_service)); dealer_invocation->set_session(session_itr->second); dealer_invocation->set_request_id(call_message->get_request_id()); dealer_invocation->set_timeout( std::bind(&wamp_dealer::invocation_timeout_handler, this, request_id, std::placeholders::_1), timeout_ms); m_pending_invocations.insert(std::make_pair(request_id, std::move(dealer_invocation))); m_pending_callee_invocations[session->get_session_id()].insert(request_id); m_pending_caller_invocations[session_id].insert(request_id); }
void wamp_dealer::process_call_message(const wamp_session_id& session_id, wamp_call_message* call_message) { auto session_itr = m_sessions.find(session_id); if (session_itr == m_sessions.end()) { throw std::logic_error("dealer session does not exist"); } BONEFISH_TRACE("%1%, %2%", *session_itr->second % *call_message); // If the session placing the call does not support the caller role // than do not allow the call to be processed and send an error. if (!session_itr->second->get_role(wamp_role_type::CALLER)) { send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.role_violation"); return; } const auto procedure = call_message->get_procedure(); if (!is_valid_uri(procedure)) { send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.invalid_uri"); return; } auto procedure_registrations_itr = m_procedure_registrations.find(procedure); if (procedure_registrations_itr == m_procedure_registrations.end()) { send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.no_such_procedure"); return; } std::shared_ptr<wamp_session> session = procedure_registrations_itr->second->get_session(); const wamp_request_id request_id = m_request_id_generator.generate(); const wamp_registration_id& registration_id = procedure_registrations_itr->second->get_registration_id(); std::unique_ptr<wamp_invocation_message> invocation_message( new wamp_invocation_message(std::move(call_message->release_zone()))); invocation_message->set_request_id(request_id); invocation_message->set_registration_id(registration_id); invocation_message->set_arguments(call_message->get_arguments()); invocation_message->set_arguments_kw(call_message->get_arguments_kw()); BONEFISH_TRACE("%1%, %2%", *session_itr->second % *invocation_message); if (!session->get_transport()->send_message(std::move(*invocation_message))) { BONEFISH_TRACE("sending invocation message to callee failed: network failure"); send_error(session_itr->second->get_transport(), call_message->get_type(), call_message->get_request_id(), "wamp.error.network_failure"); return; } else { wamp_call_options options; options.unmarshal(call_message->get_options()); unsigned timeout_ms = options.get_option_or<unsigned>("timeout", 0); // We only setup the invocation state after sending the message is successful. // This saves us from having to cleanup any state if the send fails. std::unique_ptr<wamp_dealer_invocation> dealer_invocation( new wamp_dealer_invocation(m_io_service)); dealer_invocation->set_session(session_itr->second); dealer_invocation->set_request_id(call_message->get_request_id()); dealer_invocation->set_timeout( std::bind(&wamp_dealer::invocation_timeout_handler, this, request_id, std::placeholders::_1), timeout_ms); m_pending_invocations.insert(std::make_pair(request_id, std::move(dealer_invocation))); m_pending_callee_invocations[session->get_session_id()].insert(request_id); m_pending_caller_invocations[session_id].insert(request_id); } }