Skip to content

Commit 9927ad4

Browse files
Fix the protocol abstraction so different protocols can be supported (#48)
1 parent f8ab4df commit 9927ad4

29 files changed

+612
-178
lines changed

include/signalrclient/connection.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "trace_level.h"
1212
#include "log_writer.h"
1313
#include "signalr_client_config.h"
14+
#include "transfer_format.h"
1415

1516
namespace signalr
1617
{
@@ -31,7 +32,7 @@ namespace signalr
3132

3233
SIGNALRCLIENT_API void __cdecl start(std::function<void(std::exception_ptr)> callback) noexcept;
3334

34-
SIGNALRCLIENT_API void __cdecl send(const std::string& data, std::function<void(std::exception_ptr)> callback) noexcept;
35+
SIGNALRCLIENT_API void __cdecl send(const std::string& data, transfer_format transfer_format, std::function<void(std::exception_ptr)> callback) noexcept;
3536

3637
SIGNALRCLIENT_API void __cdecl set_message_received(const message_received_handler& message_received_callback);
3738
SIGNALRCLIENT_API void __cdecl set_disconnected(const std::function<void __cdecl()>& disconnected_callback);

include/signalrclient/signalr_value.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <string>
88
#include <vector>
99
#include <map>
10+
#include <cstddef>
1011

1112
namespace signalr
1213
{
@@ -34,6 +35,11 @@ namespace signalr
3435
*/
3536
value();
3637

38+
/**
39+
* Create an object representing a value_type::null value.
40+
*/
41+
value(std::nullptr_t);
42+
3743
/**
3844
* Create an object representing a default value for the given value_type.
3945
*/
@@ -64,6 +70,11 @@ namespace signalr
6470
*/
6571
value(const char* val);
6672

73+
/**
74+
* Create an object representing a value_type::string with the given string value.
75+
*/
76+
value(const char* val, size_t length);
77+
6778
/**
6879
* Create an object representing a value_type::array with the given vector of value's.
6980
*/

include/signalrclient/websocket_client.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ namespace signalr
1414
public:
1515
virtual ~websocket_client() {};
1616

17-
virtual void start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback) = 0;
17+
virtual void start(const std::string& url, std::function<void(std::exception_ptr)> callback) = 0;
1818

1919
virtual void stop(std::function<void(std::exception_ptr)> callback) = 0;
2020

21-
virtual void send(const std::string& payload, std::function<void(std::exception_ptr)> callback) = 0;
21+
virtual void send(const std::string& payload, transfer_format transfer_format, std::function<void(std::exception_ptr)> callback) = 0;
2222

2323
virtual void receive(std::function<void(const std::string&, std::exception_ptr)> callback) = 0;
2424
};

src/signalrclient/callback_manager.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ namespace signalr
1010
{
1111
// dtor_clear_arguments will be passed when closing any pending callbacks when the `callback_manager` is
1212
// destroyed (i.e. in the dtor)
13-
callback_manager::callback_manager(const signalr::value& dtor_clear_arguments)
13+
callback_manager::callback_manager(const char* dtor_clear_arguments)
1414
: m_dtor_clear_arguments(dtor_clear_arguments)
1515
{ }
1616

1717
callback_manager::~callback_manager()
1818
{
19-
clear(m_dtor_clear_arguments);
19+
clear(m_dtor_clear_arguments.data());
2020
}
2121

2222
// note: callback must not throw except for the `on_progress` callback which will never be invoked from the dtor
23-
std::string callback_manager::register_callback(const std::function<void(const signalr::value&)>& callback)
23+
std::string callback_manager::register_callback(const std::function<void(const char*, const signalr::value&)>& callback)
2424
{
2525
auto callback_id = get_callback_id();
2626

@@ -35,9 +35,9 @@ namespace signalr
3535

3636

3737
// invokes a callback and stops tracking it if remove callback set to true
38-
bool callback_manager::invoke_callback(const std::string& callback_id, const signalr::value& arguments, bool remove_callback)
38+
bool callback_manager::invoke_callback(const std::string& callback_id, const char* error, const signalr::value& arguments, bool remove_callback)
3939
{
40-
std::function<void(const signalr::value& arguments)> callback;
40+
std::function<void(const char*, const signalr::value& arguments)> callback;
4141

4242
{
4343
std::lock_guard<std::mutex> lock(m_map_lock);
@@ -56,7 +56,7 @@ namespace signalr
5656
}
5757
}
5858

59-
callback(arguments);
59+
callback(error, arguments);
6060
return true;
6161
}
6262

@@ -69,14 +69,14 @@ namespace signalr
6969
}
7070
}
7171

72-
void callback_manager::clear(const signalr::value& arguments)
72+
void callback_manager::clear(const char* error)
7373
{
7474
{
7575
std::lock_guard<std::mutex> lock(m_map_lock);
7676

7777
for (auto& kvp : m_callbacks)
7878
{
79-
kvp.second(arguments);
79+
kvp.second(error, signalr::value());
8080
}
8181

8282
m_callbacks.clear();

src/signalrclient/callback_manager.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,22 @@ namespace signalr
1515
class callback_manager
1616
{
1717
public:
18-
explicit callback_manager(const signalr::value& dtor_error);
18+
explicit callback_manager(const char* dtor_error);
1919
~callback_manager();
2020

2121
callback_manager(const callback_manager&) = delete;
2222
callback_manager& operator=(const callback_manager&) = delete;
2323

24-
std::string register_callback(const std::function<void(const signalr::value&)>& callback);
25-
bool invoke_callback(const std::string& callback_id, const signalr::value& arguments, bool remove_callback);
24+
std::string register_callback(const std::function<void(const char*, const signalr::value&)>& callback);
25+
bool invoke_callback(const std::string& callback_id, const char* error, const signalr::value& arguments, bool remove_callback);
2626
bool remove_callback(const std::string& callback_id);
27-
void clear(const signalr::value& arguments);
27+
void clear(const char* error);
2828

2929
private:
3030
std::atomic<int> m_id { 0 };
31-
std::unordered_map<std::string, std::function<void(const signalr::value&)>> m_callbacks;
31+
std::unordered_map<std::string, std::function<void(const char*, const signalr::value&)>> m_callbacks;
3232
std::mutex m_map_lock;
33-
const signalr::value m_dtor_clear_arguments;
33+
std::string m_dtor_clear_arguments;
3434

3535
std::string get_callback_id();
3636
};

src/signalrclient/connection.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ namespace signalr
2222
m_pImpl->start(callback);
2323
}
2424

25-
void connection::send(const std::string& data, std::function<void(std::exception_ptr)> callback) noexcept
25+
void connection::send(const std::string& data, transfer_format transfer_format, std::function<void(std::exception_ptr)> callback) noexcept
2626
{
27-
m_pImpl->send(data, callback);
27+
m_pImpl->send(data, transfer_format, callback);
2828
}
2929

3030
void connection::set_message_received(const message_received_handler& message_received_callback)

src/signalrclient/connection_impl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ namespace signalr
455455
auto query_string = "id=" + m_connection_token;
456456
auto connect_url = url_builder::build_connect(url, transport->get_transport_type(), query_string);
457457

458-
transport->start(connect_url, transfer_format::text, [callback, logger](std::exception_ptr exception)
458+
transport->start(connect_url, [callback, logger](std::exception_ptr exception)
459459
mutable {
460460
try
461461
{
@@ -479,6 +479,7 @@ namespace signalr
479479

480480
void connection_impl::process_response(std::string&& response)
481481
{
482+
// TODO: log binary data better
482483
m_logger.log(trace_level::messages,
483484
std::string("processing message: ").append(response));
484485

@@ -504,7 +505,7 @@ namespace signalr
504505
}
505506
}
506507

507-
void connection_impl::send(const std::string& data, std::function<void(std::exception_ptr)> callback) noexcept
508+
void connection_impl::send(const std::string& data, transfer_format transfer_format, std::function<void(std::exception_ptr)> callback) noexcept
508509
{
509510
// To prevent an (unlikely) condition where the transport is nulled out after we checked the connection_state
510511
// and before sending data we store the pointer in the local variable. In this case `send()` will throw but
@@ -524,7 +525,7 @@ namespace signalr
524525

525526
logger.log(trace_level::info, std::string("sending data: ").append(data));
526527

527-
transport->send(data, [logger, callback](std::exception_ptr exception)
528+
transport->send(data, transfer_format, [logger, callback](std::exception_ptr exception)
528529
mutable {
529530
try
530531
{

src/signalrclient/connection_impl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace signalr
3939
~connection_impl();
4040

4141
void start(std::function<void(std::exception_ptr)> callback) noexcept;
42-
void send(const std::string &data, std::function<void(std::exception_ptr)> callback) noexcept;
42+
void send(const std::string &data, transfer_format transfer_format, std::function<void(std::exception_ptr)> callback) noexcept;
4343
void stop(std::function<void(std::exception_ptr)> callback) noexcept;
4444

4545
connection_state get_connection_state() const noexcept;

src/signalrclient/default_websocket_client.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#ifdef USE_CPPRESTSDK
88
#include "default_websocket_client.h"
9+
#include <signalrclient/signalr_exception.h>
910

1011
namespace signalr
1112
{
@@ -28,7 +29,7 @@ namespace signalr
2829
: m_underlying_client(create_client_config(signalr_client_config))
2930
{ }
3031

31-
void default_websocket_client::start(const std::string& url, transfer_format, std::function<void(std::exception_ptr)> callback)
32+
void default_websocket_client::start(const std::string& url, std::function<void(std::exception_ptr)> callback)
3233
{
3334
m_underlying_client.connect(utility::conversions::to_string_t(url))
3435
.then([callback](pplx::task<void> task)
@@ -62,10 +63,18 @@ namespace signalr
6263
});
6364
}
6465

65-
void default_websocket_client::send(const std::string& payload, std::function<void(std::exception_ptr)> callback)
66+
void default_websocket_client::send(const std::string& payload, signalr::transfer_format transfer_format, std::function<void(std::exception_ptr)> callback)
6667
{
6768
web::websockets::client::websocket_outgoing_message msg;
68-
msg.set_utf8_message(payload);
69+
70+
if (transfer_format == signalr::transfer_format::binary)
71+
{
72+
throw signalr_exception("binary isn't supported currently");
73+
}
74+
else
75+
{
76+
msg.set_utf8_message(payload);
77+
}
6978
m_underlying_client.send(msg)
7079
.then([callback](pplx::task<void> task)
7180
{
@@ -88,8 +97,15 @@ namespace signalr
8897
{
8998
try
9099
{
100+
101+
std::string msg;
91102
auto response = task.get();
92-
auto msg = response.extract_string().get();
103+
if (response.message_type() == web::websockets::client::websocket_message_type::binary_message)
104+
{
105+
throw signalr_exception("binary isn't supported currently");
106+
}
107+
msg = response.extract_string().get();
108+
93109
callback(msg, nullptr);
94110
}
95111
catch (...)

src/signalrclient/default_websocket_client.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ namespace signalr
2020
public:
2121
explicit default_websocket_client(const signalr_client_config& signalr_client_config = {}) noexcept;
2222

23-
void start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback);
23+
void start(const std::string& url, std::function<void(std::exception_ptr)> callback);
2424
void stop(std::function<void(std::exception_ptr)> callback);
25-
void send(const std::string& payload, std::function<void(std::exception_ptr)> callback);
25+
void send(const std::string& payload, transfer_format transfer_format, std::function<void(std::exception_ptr)> callback);
2626
void receive(std::function<void(const std::string&, std::exception_ptr)> callback);
2727
private:
2828
web::websockets::client::websocket_client m_underlying_client;

0 commit comments

Comments
 (0)