aboutsummaryrefslogtreecommitdiff
path: root/src/device_trezor/trezor
diff options
context:
space:
mode:
authorDusan Klinec <dusan.klinec@gmail.com>2018-11-20 14:40:51 +0100
committerDusan Klinec <dusan.klinec@gmail.com>2019-03-05 14:02:45 +0100
commit5ea17909caec3ca9f96e3dbd360ee952528de43c (patch)
tree93743fabffa0cfe5678395d11003600b45ddb629 /src/device_trezor/trezor
parentMerge pull request #4988 (diff)
downloadmonero-5ea17909caec3ca9f96e3dbd360ee952528de43c.tar.xz
device/trezor: debugging features, trezor tests
Diffstat (limited to 'src/device_trezor/trezor')
-rw-r--r--src/device_trezor/trezor/debug_link.cpp90
-rw-r--r--src/device_trezor/trezor/debug_link.hpp93
-rw-r--r--src/device_trezor/trezor/messages_map.cpp11
-rw-r--r--src/device_trezor/trezor/messages_map.hpp6
-rw-r--r--src/device_trezor/trezor/tools/build_protob.py10
-rw-r--r--src/device_trezor/trezor/transport.cpp150
-rw-r--r--src/device_trezor/trezor/transport.hpp19
7 files changed, 338 insertions, 41 deletions
diff --git a/src/device_trezor/trezor/debug_link.cpp b/src/device_trezor/trezor/debug_link.cpp
new file mode 100644
index 000000000..c7ee59afe
--- /dev/null
+++ b/src/device_trezor/trezor/debug_link.cpp
@@ -0,0 +1,90 @@
+// Copyright (c) 2017-2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "debug_link.hpp"
+
+namespace hw{
+namespace trezor{
+
+ DebugLink::DebugLink(){
+
+ }
+
+ DebugLink::~DebugLink(){
+ if (m_transport){
+ close();
+ }
+ }
+
+ void DebugLink::init(std::shared_ptr<Transport> & transport){
+ CHECK_AND_ASSERT_THROW_MES(!m_transport, "Already initialized");
+ m_transport = transport;
+ m_transport->open();
+ }
+
+ void DebugLink::close(){
+ CHECK_AND_ASSERT_THROW_MES(m_transport, "Not initialized");
+ if (m_transport) m_transport->close();
+ }
+
+ std::shared_ptr<messages::debug::DebugLinkState> DebugLink::state(){
+ return call<messages::debug::DebugLinkState>(
+ messages::debug::DebugLinkGetState(),
+ boost::make_optional(messages::MessageType_DebugLinkGetState));
+ }
+
+ void DebugLink::input_word(const std::string & word){
+ messages::debug::DebugLinkDecision decision;
+ decision.set_input(word);
+ call(decision, boost::none, true);
+ }
+
+ void DebugLink::input_button(bool button){
+ messages::debug::DebugLinkDecision decision;
+ decision.set_yes_no(button);
+ call(decision, boost::none, true);
+ }
+
+ void DebugLink::input_swipe(bool swipe){
+ messages::debug::DebugLinkDecision decision;
+ decision.set_up_down(swipe);
+ call(decision, boost::none, true);
+ }
+
+ void DebugLink::stop(){
+ messages::debug::DebugLinkStop msg;
+ call(msg, boost::none, true);
+ }
+
+
+
+
+
+}
+} \ No newline at end of file
diff --git a/src/device_trezor/trezor/debug_link.hpp b/src/device_trezor/trezor/debug_link.hpp
new file mode 100644
index 000000000..adf5f1d8f
--- /dev/null
+++ b/src/device_trezor/trezor/debug_link.hpp
@@ -0,0 +1,93 @@
+// Copyright (c) 2017-2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef MONERO_DEBUG_LINK_H
+#define MONERO_DEBUG_LINK_H
+
+#include "transport.hpp"
+#include "messages/messages-debug.pb.h"
+
+
+namespace hw {
+namespace trezor {
+
+ class DebugLink {
+ public:
+
+ DebugLink();
+ virtual ~DebugLink();
+
+ void init(std::shared_ptr<Transport> & transport);
+ void close();
+
+ std::shared_ptr<messages::debug::DebugLinkState> state();
+ void input_word(const std::string & word);
+ void input_button(bool button);
+ void input_swipe(bool swipe);
+ void press_yes() { input_button(true); }
+ void press_no() { input_button(false); }
+ void stop();
+
+ template<class t_message=messages::debug::DebugLinkState>
+ std::shared_ptr<t_message> call(
+ const google::protobuf::Message & req,
+ const boost::optional<messages::MessageType> &resp_type = boost::none,
+ bool no_wait = false)
+ {
+ BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
+
+ m_transport->write(req);
+ if (no_wait){
+ return nullptr;
+ }
+
+ // Read the response
+ std::shared_ptr<google::protobuf::Message> msg_resp;
+ hw::trezor::messages::MessageType msg_resp_type;
+ m_transport->read(msg_resp, &msg_resp_type);
+
+ messages::MessageType required_type = resp_type ? resp_type.get() : MessageMapper::get_message_wire_number<t_message>();
+ if (msg_resp_type == required_type) {
+ return message_ptr_retype<t_message>(msg_resp);
+ } else if (msg_resp_type == messages::MessageType_Failure){
+ throw_failure_exception(dynamic_cast<messages::common::Failure*>(msg_resp.get()));
+ } else {
+ throw exc::UnexpectedMessageException(msg_resp_type, msg_resp);
+ }
+ };
+
+ private:
+ std::shared_ptr<Transport> m_transport;
+
+ };
+
+}
+}
+
+#endif //MONERO_DEBUG_LINK_H
diff --git a/src/device_trezor/trezor/messages_map.cpp b/src/device_trezor/trezor/messages_map.cpp
index b0d1aa254..f4e01f860 100644
--- a/src/device_trezor/trezor/messages_map.cpp
+++ b/src/device_trezor/trezor/messages_map.cpp
@@ -33,6 +33,10 @@
#include "messages/messages-management.pb.h"
#include "messages/messages-monero.pb.h"
+#ifdef WITH_TREZOR_DEBUGGING
+#include "messages/messages-debug.pb.h"
+#endif
+
using namespace std;
using namespace hw::trezor;
@@ -45,6 +49,9 @@ namespace trezor
"hw.trezor.messages.",
"hw.trezor.messages.common.",
"hw.trezor.messages.management.",
+#ifdef WITH_TREZOR_DEBUGGING
+ "hw.trezor.messages.debug.",
+#endif
"hw.trezor.messages.monero."
};
@@ -68,6 +75,10 @@ namespace trezor
hw::trezor::messages::management::Cancel::default_instance();
hw::trezor::messages::monero::MoneroGetAddress::default_instance();
+#ifdef WITH_TREZOR_DEBUGGING
+ hw::trezor::messages::debug::DebugLinkDecision::default_instance();
+#endif
+
google::protobuf::Descriptor const * desc = nullptr;
for(const string &text : PACKAGES){
desc = google::protobuf::DescriptorPool::generated_pool()
diff --git a/src/device_trezor/trezor/messages_map.hpp b/src/device_trezor/trezor/messages_map.hpp
index f61338f09..24a3182f9 100644
--- a/src/device_trezor/trezor/messages_map.hpp
+++ b/src/device_trezor/trezor/messages_map.hpp
@@ -62,14 +62,14 @@ namespace trezor {
static messages::MessageType get_message_wire_number(const google::protobuf::Message & msg);
static messages::MessageType get_message_wire_number(const std::string & msg_name);
- template<class t_message>
+ template<class t_message=google::protobuf::Message>
static messages::MessageType get_message_wire_number() {
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
return get_message_wire_number(t_message::default_instance().GetDescriptor()->name());
}
};
- template<class t_message>
+ template<class t_message=google::protobuf::Message>
std::shared_ptr<t_message> message_ptr_retype(std::shared_ptr<google::protobuf::Message> & in){
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
if (!in){
@@ -79,7 +79,7 @@ namespace trezor {
return std::dynamic_pointer_cast<t_message>(in);
}
- template<class t_message>
+ template<class t_message=google::protobuf::Message>
std::shared_ptr<t_message> message_ptr_retype_static(std::shared_ptr<google::protobuf::Message> & in){
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
if (!in){
diff --git a/src/device_trezor/trezor/tools/build_protob.py b/src/device_trezor/trezor/tools/build_protob.py
index 2611f3296..eb32f6b4d 100644
--- a/src/device_trezor/trezor/tools/build_protob.py
+++ b/src/device_trezor/trezor/tools/build_protob.py
@@ -2,6 +2,12 @@
import os
import subprocess
import sys
+import argparse
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-d", "--debug-msg", default=False, action="store_const", const=True, help="Build debug messages")
+args = parser.parse_args()
CWD = os.path.dirname(os.path.realpath(__file__))
ROOT_DIR = os.path.abspath(os.path.join(CWD, "..", "..", "..", ".."))
@@ -24,6 +30,10 @@ try:
"messages-management.proto",
"messages-monero.proto",
]
+
+ if args.debug_msg:
+ selected += ["messages-debug.proto"]
+
proto_srcs = [os.path.join(TREZOR_COMMON, "protob", x) for x in selected]
exec_args = [
sys.executable,
diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp
index cd66e59e8..9149e0168 100644
--- a/src/device_trezor/trezor/transport.cpp
+++ b/src/device_trezor/trezor/transport.cpp
@@ -84,6 +84,17 @@ namespace trezor{
return std::string(in.GetString());
}
+ uint64_t pack_version(uint32_t major, uint32_t minor, uint32_t patch)
+ {
+ // packing (major, minor, patch) to 64 B: 16 B | 24 B | 24 B
+ const unsigned bits_1 = 16;
+ const unsigned bits_2 = 24;
+ const uint32_t mask_1 = (1 << bits_1) - 1;
+ const uint32_t mask_2 = (1 << bits_2) - 1;
+ CHECK_AND_ASSERT_THROW_MES(major <= mask_1 && minor <= mask_2 && patch <= mask_2, "Version numbers overflow packing scheme");
+ return patch | (((uint64_t)minor) << bits_2) | (((uint64_t)major) << (bits_1 + bits_2));
+ }
+
//
// Helpers
//
@@ -212,6 +223,40 @@ namespace trezor{
msg = msg_wrap;
}
+ Transport::Transport(): m_open_counter(0) {
+
+ }
+
+ bool Transport::pre_open(){
+ if (m_open_counter > 0){
+ MTRACE("Already opened, count: " << m_open_counter);
+ m_open_counter += 1;
+ return false;
+
+ } else if (m_open_counter < 0){
+ MTRACE("Negative open value: " << m_open_counter);
+
+ }
+
+ // Caller should set m_open_counter to 1 after open
+ m_open_counter = 0;
+ return true;
+ }
+
+ bool Transport::pre_close(){
+ m_open_counter -= 1;
+
+ if (m_open_counter < 0){
+ MDEBUG("Already closed. Counter " << m_open_counter);
+
+ } else if (m_open_counter == 0) {
+ return true;
+
+ }
+
+ return false;
+ }
+
//
// Bridge transport
//
@@ -246,6 +291,10 @@ namespace trezor{
}
void BridgeTransport::open() {
+ if (!pre_open()){
+ return;
+ }
+
if (!m_device_path){
throw exc::CommunicationException("Coud not open, empty device path");
}
@@ -259,9 +308,15 @@ namespace trezor{
}
m_session = boost::make_optional(json_get_string(bridge_res["session"]));
+ m_open_counter = 1;
}
void BridgeTransport::close() {
+ if (!pre_close()){
+ return;
+ }
+
+ MTRACE("Closing Trezor:BridgeTransport");
if (!m_device_path || !m_session){
throw exc::CommunicationException("Device not open");
}
@@ -423,6 +478,10 @@ namespace trezor{
}
void UdpTransport::open() {
+ if (!pre_open()){
+ return;
+ }
+
udp::resolver resolver(m_io_service);
udp::resolver::query query(udp::v4(), m_device_host, std::to_string(m_device_port));
m_endpoint = *resolver.resolve(query);
@@ -434,10 +493,16 @@ namespace trezor{
check_deadline();
m_proto->session_begin(*this);
+ m_open_counter = 1;
}
void UdpTransport::close() {
- if (!m_socket){
+ if (!pre_close()){
+ return;
+ }
+
+ MTRACE("Closing Trezor:UdpTransport");
+ if (!m_socket) {
throw exc::CommunicationException("Socket is already closed");
}
@@ -446,6 +511,19 @@ namespace trezor{
m_socket = nullptr;
}
+ std::shared_ptr<Transport> UdpTransport::find_debug() {
+#ifdef WITH_TREZOR_DEBUGGING
+ std::shared_ptr<UdpTransport> t = std::make_shared<UdpTransport>();
+ t->m_proto = std::make_shared<ProtocolV1>();
+ t->m_device_host = m_device_host;
+ t->m_device_port = m_device_port + 1;
+ return t;
+#else
+ MINFO("Debug link is disabled in production");
+ return nullptr;
+#endif
+ }
+
void UdpTransport::write_chunk(const void * buff, size_t size){
require_socket();
@@ -660,8 +738,7 @@ namespace trezor{
WebUsbTransport::WebUsbTransport(
boost::optional<libusb_device_descriptor*> descriptor,
boost::optional<std::shared_ptr<Protocol>> proto
- ): m_conn_count(0),
- m_usb_session(nullptr), m_usb_device(nullptr), m_usb_device_handle(nullptr),
+ ): m_usb_session(nullptr), m_usb_device(nullptr), m_usb_device_handle(nullptr),
m_bus_id(-1), m_device_addr(-1)
{
if (descriptor){
@@ -672,7 +749,7 @@ namespace trezor{
m_proto = proto ? proto.get() : std::make_shared<ProtocolV1>();
-#ifdef WITH_TREZOR_DEBUG
+#ifdef WITH_TREZOR_DEBUGGING
m_debug_mode = false;
#endif
}
@@ -757,12 +834,10 @@ namespace trezor{
};
void WebUsbTransport::open() {
- const int interface = get_interface();
- if (m_conn_count > 0){
- MTRACE("Already opened, count: " << m_conn_count);
- m_conn_count += 1;
+ if (!pre_open()){
return;
}
+ const int interface = get_interface();
#define TREZOR_DESTROY_SESSION() do { libusb_exit(m_usb_session); m_usb_session = nullptr; } while(0)
@@ -840,45 +915,55 @@ namespace trezor{
throw exc::DeviceAcquireException("Unable to claim libusb device");
}
- m_conn_count = 1;
+ m_open_counter = 1;
m_proto->session_begin(*this);
#undef TREZOR_DESTROY_SESSION
};
void WebUsbTransport::close() {
- m_conn_count -= 1;
-
- if (m_conn_count < 0){
- MERROR("Close counter is negative: " << m_conn_count);
-
- } else if (m_conn_count == 0){
- MTRACE("Closing webusb device");
+ if (!pre_close()){
+ return;
+ }
- m_proto->session_end(*this);
+ MTRACE("Closing Trezor:WebUsbTransport");
+ m_proto->session_end(*this);
- int r = libusb_release_interface(m_usb_device_handle, get_interface());
- if (r != 0){
- MERROR("Could not release libusb interface: " << r);
- }
+ int r = libusb_release_interface(m_usb_device_handle, get_interface());
+ if (r != 0){
+ MERROR("Could not release libusb interface: " << r);
+ }
- m_usb_device = nullptr;
- if (m_usb_device_handle) {
- libusb_close(m_usb_device_handle);
- m_usb_device_handle = nullptr;
- }
+ m_usb_device = nullptr;
+ if (m_usb_device_handle) {
+ libusb_close(m_usb_device_handle);
+ m_usb_device_handle = nullptr;
+ }
- if (m_usb_session) {
- libusb_exit(m_usb_session);
- m_usb_session = nullptr;
- }
+ if (m_usb_session) {
+ libusb_exit(m_usb_session);
+ m_usb_session = nullptr;
}
};
+ std::shared_ptr<Transport> WebUsbTransport::find_debug() {
+#ifdef WITH_TREZOR_DEBUGGING
+ require_device();
+ auto t = std::make_shared<WebUsbTransport>(boost::make_optional(m_usb_device_desc.get()));
+ t->m_bus_id = m_bus_id;
+ t->m_device_addr = m_device_addr;
+ t->m_port_numbers = m_port_numbers;
+ t->m_debug_mode = true;
+ return t;
+#else
+ MINFO("Debug link is disabled in production");
+ return nullptr;
+#endif
+ }
int WebUsbTransport::get_interface() const{
const int INTERFACE_NORMAL = 0;
-#ifdef WITH_TREZOR_DEBUG
+#ifdef WITH_TREZOR_DEBUGGING
const int INTERFACE_DEBUG = 1;
return m_debug_mode ? INTERFACE_DEBUG : INTERFACE_NORMAL;
#else
@@ -888,7 +973,7 @@ namespace trezor{
unsigned char WebUsbTransport::get_endpoint() const{
const unsigned char ENDPOINT_NORMAL = 1;
-#ifdef WITH_TREZOR_DEBUG
+#ifdef WITH_TREZOR_DEBUGGING
const unsigned char ENDPOINT_DEBUG = 2;
return m_debug_mode ? ENDPOINT_DEBUG : ENDPOINT_NORMAL;
#else
@@ -1047,4 +1132,3 @@ namespace trezor{
}
}
-
diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp
index 50c31cf73..e2e602728 100644
--- a/src/device_trezor/trezor/transport.hpp
+++ b/src/device_trezor/trezor/transport.hpp
@@ -62,6 +62,8 @@ namespace trezor {
const std::string DEFAULT_BRIDGE = "127.0.0.1:21325";
+ uint64_t pack_version(uint32_t major, uint32_t minor=0, uint32_t patch=0);
+
// Base HTTP comm serialization.
bool t_serialize(const std::string & in, std::string & out);
bool t_serialize(const json_val & in, std::string & out);
@@ -134,7 +136,7 @@ namespace trezor {
class Transport {
public:
- Transport() = default;
+ Transport();
virtual ~Transport() = default;
virtual bool ping() { return false; };
@@ -144,10 +146,16 @@ namespace trezor {
virtual void close(){};
virtual void write(const google::protobuf::Message & req) =0;
virtual void read(std::shared_ptr<google::protobuf::Message> & msg, messages::MessageType * msg_type=nullptr) =0;
+ virtual std::shared_ptr<Transport> find_debug() { return nullptr; };
virtual void write_chunk(const void * buff, size_t size) { };
virtual size_t read_chunk(void * buff, size_t size) { return 0; };
virtual std::ostream& dump(std::ostream& o) const { return o << "Transport<>"; }
+ protected:
+ long m_open_counter;
+
+ virtual bool pre_open();
+ virtual bool pre_close();
};
// Bridge transport
@@ -212,6 +220,7 @@ namespace trezor {
void open() override;
void close() override;
+ std::shared_ptr<Transport> find_debug() override;
void write(const google::protobuf::Message &req) override;
void read(std::shared_ptr<google::protobuf::Message> & msg, messages::MessageType * msg_type=nullptr) override;
@@ -259,6 +268,7 @@ namespace trezor {
void open() override;
void close() override;
+ std::shared_ptr<Transport> find_debug() override;
void write(const google::protobuf::Message &req) override;
void read(std::shared_ptr<google::protobuf::Message> & msg, messages::MessageType * msg_type=nullptr) override;
@@ -274,7 +284,6 @@ namespace trezor {
int get_interface() const;
unsigned char get_endpoint() const;
- int m_conn_count;
std::shared_ptr<Protocol> m_proto;
libusb_context *m_usb_session;
@@ -285,7 +294,7 @@ namespace trezor {
int m_bus_id;
int m_device_addr;
-#ifdef WITH_TREZOR_DEBUG
+#ifdef WITH_TREZOR_DEBUGGING
bool m_debug_mode;
#endif
};
@@ -309,7 +318,7 @@ namespace trezor {
/**
* Transforms path to the particular transport
*/
- template<class t_transport>
+ template<class t_transport=Transport>
std::shared_ptr<t_transport> transport_typed(const std::string & path){
auto t = transport(path);
if (!t){
@@ -362,7 +371,7 @@ namespace trezor {
* @throws UnexpectedMessageException if the response message type is different than expected.
* Exception contains message type and the message itself.
*/
- template<class t_message>
+ template<class t_message=google::protobuf::Message>
std::shared_ptr<t_message>
exchange_message(Transport & transport, const google::protobuf::Message & req,
boost::optional<messages::MessageType> resp_type = boost::none)