More C++ Client cleanup (#7551)
This commit is contained in:
parent
6ea3f27dbb
commit
bca85b92fc
|
|
@ -41,7 +41,7 @@ namespace signalr
|
||||||
|
|
||||||
SIGNALRCLIENT_API pplx::task<void> __cdecl stop();
|
SIGNALRCLIENT_API pplx::task<void> __cdecl stop();
|
||||||
|
|
||||||
SIGNALRCLIENT_API connection_state __cdecl get_connection_state() const;
|
SIGNALRCLIENT_API connection_state __cdecl get_connection_state() const noexcept;
|
||||||
SIGNALRCLIENT_API utility::string_t __cdecl get_connection_id() const;
|
SIGNALRCLIENT_API utility::string_t __cdecl get_connection_id() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -43,20 +43,11 @@ namespace signalr
|
||||||
|
|
||||||
SIGNALRCLIENT_API void __cdecl on(const utility::string_t& event_name, const method_invoked_handler& handler);
|
SIGNALRCLIENT_API void __cdecl on(const utility::string_t& event_name, const method_invoked_handler& handler);
|
||||||
|
|
||||||
pplx::task<web::json::value> invoke(const utility::string_t& method_name, const web::json::value& arguments = web::json::value::array())
|
SIGNALRCLIENT_API pplx::task<web::json::value> invoke(const utility::string_t& method_name, const web::json::value& arguments = web::json::value::array());
|
||||||
{
|
|
||||||
return invoke_json(method_name, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
pplx::task<void> send(const utility::string_t& method_name, const web::json::value& arguments = web::json::value::array())
|
SIGNALRCLIENT_API pplx::task<void> send(const utility::string_t& method_name, const web::json::value& arguments = web::json::value::array());
|
||||||
{
|
|
||||||
return invoke_void(method_name, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<hub_connection_impl> m_pImpl;
|
std::shared_ptr<hub_connection_impl> m_pImpl;
|
||||||
|
|
||||||
SIGNALRCLIENT_API pplx::task<web::json::value> __cdecl invoke_json(const utility::string_t& method_name, const web::json::value& arguments);
|
|
||||||
SIGNALRCLIENT_API pplx::task<void> __cdecl invoke_void(const utility::string_t& method_name, const web::json::value& arguments);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "cpprest/details/basic_types.h"
|
|
||||||
#include "cpprest/json.h"
|
|
||||||
#include "cpprest/asyncrt_utils.h"
|
|
||||||
#include "signalr_exception.h"
|
#include "signalr_exception.h"
|
||||||
|
#include "cpprest/details/basic_types.h"
|
||||||
|
|
||||||
namespace signalr
|
namespace signalr
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ namespace signalr
|
||||||
SIGNALRCLIENT_API web::http::client::http_client_config __cdecl get_http_client_config() const;
|
SIGNALRCLIENT_API web::http::client::http_client_config __cdecl get_http_client_config() const;
|
||||||
SIGNALRCLIENT_API void __cdecl set_http_client_config(const web::http::client::http_client_config& http_client_config);
|
SIGNALRCLIENT_API void __cdecl set_http_client_config(const web::http::client::http_client_config& http_client_config);
|
||||||
|
|
||||||
SIGNALRCLIENT_API web::websockets::client::websocket_client_config __cdecl get_websocket_client_config() const;
|
SIGNALRCLIENT_API web::websockets::client::websocket_client_config __cdecl get_websocket_client_config() const noexcept;
|
||||||
SIGNALRCLIENT_API void __cdecl set_websocket_client_config(const web::websockets::client::websocket_client_config& websocket_client_config);
|
SIGNALRCLIENT_API void __cdecl set_websocket_client_config(const web::websockets::client::websocket_client_config& websocket_client_config);
|
||||||
|
|
||||||
SIGNALRCLIENT_API web::http::http_headers __cdecl get_http_headers() const;
|
SIGNALRCLIENT_API web::http::http_headers __cdecl get_http_headers() const noexcept;
|
||||||
SIGNALRCLIENT_API void __cdecl set_http_headers(const web::http::http_headers& http_headers);
|
SIGNALRCLIENT_API void __cdecl set_http_headers(const web::http::http_headers& http_headers);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -33,4 +33,4 @@ namespace signalr
|
||||||
web::websockets::client::websocket_client_config m_websocket_client_config;
|
web::websockets::client::websocket_client_config m_websocket_client_config;
|
||||||
web::http::http_headers m_http_headers;
|
web::http::http_headers m_http_headers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ namespace signalr
|
||||||
all = messages | events | state_changes | errors | info
|
all = messages | events | state_changes | errors | info
|
||||||
};
|
};
|
||||||
|
|
||||||
inline trace_level operator|(trace_level lhs, trace_level rhs)
|
inline trace_level operator|(trace_level lhs, trace_level rhs) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<trace_level>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
return static_cast<trace_level>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline trace_level operator&(trace_level lhs, trace_level rhs)
|
inline trace_level operator&(trace_level lhs, trace_level rhs) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<trace_level>(static_cast<int>(lhs) & static_cast<int>(rhs));
|
return static_cast<trace_level>(static_cast<int>(lhs) & static_cast<int>(rhs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace signalr
|
||||||
: runtime_error(utility::conversions::to_utf8string(what)), m_status_code(status_code)
|
: runtime_error(utility::conversions::to_utf8string(what)), m_status_code(status_code)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
unsigned short status_code() const
|
unsigned short status_code() const noexcept
|
||||||
{
|
{
|
||||||
return m_status_code;
|
return m_status_code;
|
||||||
}
|
}
|
||||||
|
|
@ -24,4 +24,4 @@ namespace signalr
|
||||||
private:
|
private:
|
||||||
unsigned short m_status_code;
|
unsigned short m_status_code;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,4 @@
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="packages.config" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -83,7 +83,7 @@ namespace signalr
|
||||||
|
|
||||||
utility::string_t callback_manager::get_callback_id()
|
utility::string_t callback_manager::get_callback_id()
|
||||||
{
|
{
|
||||||
auto callback_id = m_id++;
|
const auto callback_id = m_id++;
|
||||||
utility::stringstream_t ss;
|
utility::stringstream_t ss;
|
||||||
ss << callback_id;
|
ss << callback_id;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace signalr
|
||||||
|
|
||||||
struct case_insensitive_hash : std::unary_function<utility::string_t, std::size_t>
|
struct case_insensitive_hash : std::unary_function<utility::string_t, std::size_t>
|
||||||
{
|
{
|
||||||
std::size_t operator()(const utility::string_t& s) const
|
std::size_t operator()(const utility::string_t& s) const noexcept
|
||||||
{
|
{
|
||||||
size_t hash = 0;
|
size_t hash = 0;
|
||||||
std::hash<size_t> hasher;
|
std::hash<size_t> hasher;
|
||||||
|
|
@ -47,4 +47,4 @@ namespace signalr
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace signalr
|
||||||
return m_pImpl->stop();
|
return m_pImpl->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_state connection::get_connection_state() const
|
connection_state connection::get_connection_state() const noexcept
|
||||||
{
|
{
|
||||||
return m_pImpl->get_connection_state();
|
return m_pImpl->get_connection_state();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "cpprest/asyncrt_utils.h"
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "connection_impl.h"
|
#include "connection_impl.h"
|
||||||
#include "request_sender.h"
|
#include "request_sender.h"
|
||||||
|
|
@ -39,7 +38,7 @@ namespace signalr
|
||||||
std::unique_ptr<web_request_factory> web_request_factory, std::unique_ptr<transport_factory> transport_factory)
|
std::unique_ptr<web_request_factory> web_request_factory, std::unique_ptr<transport_factory> transport_factory)
|
||||||
: m_base_url(url), m_query_string(query_string), m_connection_state(connection_state::disconnected), m_logger(log_writer, trace_level),
|
: m_base_url(url), m_query_string(query_string), m_connection_state(connection_state::disconnected), m_logger(log_writer, trace_level),
|
||||||
m_transport(nullptr), m_web_request_factory(std::move(web_request_factory)), m_transport_factory(std::move(transport_factory)),
|
m_transport(nullptr), m_web_request_factory(std::move(web_request_factory)), m_transport_factory(std::move(transport_factory)),
|
||||||
m_message_received([](const utility::string_t&){}), m_disconnected([](){})
|
m_message_received([](const utility::string_t&) noexcept {}), m_disconnected([]() noexcept {})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
connection_impl::~connection_impl()
|
connection_impl::~connection_impl()
|
||||||
|
|
@ -87,28 +86,49 @@ namespace signalr
|
||||||
|
|
||||||
pplx::task_completion_event<void> start_tce;
|
pplx::task_completion_event<void> start_tce;
|
||||||
|
|
||||||
auto connection = shared_from_this();
|
auto weak_connection = weak_from_this();
|
||||||
|
|
||||||
pplx::task_from_result()
|
pplx::task_from_result()
|
||||||
.then([connection]()
|
.then([weak_connection]()
|
||||||
{
|
{
|
||||||
|
auto connection = weak_connection.lock();
|
||||||
|
if (!connection)
|
||||||
|
{
|
||||||
|
return pplx::task_from_exception<negotiation_response>(_XPLATSTR("connection no longer exists"));
|
||||||
|
}
|
||||||
return request_sender::negotiate(*connection->m_web_request_factory, connection->m_base_url,
|
return request_sender::negotiate(*connection->m_web_request_factory, connection->m_base_url,
|
||||||
connection->m_query_string, connection->m_signalr_client_config);
|
connection->m_query_string, connection->m_signalr_client_config);
|
||||||
}, m_disconnect_cts.get_token())
|
}, m_disconnect_cts.get_token())
|
||||||
.then([connection](negotiation_response negotiation_response)
|
.then([weak_connection](negotiation_response negotiation_response)
|
||||||
{
|
{
|
||||||
connection->m_connection_id = negotiation_response.connection_id;
|
auto connection = weak_connection.lock();
|
||||||
|
if (!connection)
|
||||||
|
{
|
||||||
|
return pplx::task_from_exception<void>(_XPLATSTR("connection no longer exists"));
|
||||||
|
}
|
||||||
|
connection->m_connection_id = std::move(negotiation_response.connection_id);
|
||||||
|
|
||||||
// TODO: check available transports
|
// TODO: check available transports
|
||||||
|
|
||||||
return connection->start_transport(negotiation_response)
|
return connection->start_transport()
|
||||||
.then([connection, negotiation_response](std::shared_ptr<transport> transport)
|
.then([weak_connection](std::shared_ptr<transport> transport)
|
||||||
{
|
{
|
||||||
|
auto connection = weak_connection.lock();
|
||||||
|
if (!connection)
|
||||||
|
{
|
||||||
|
return pplx::task_from_exception<void>(_XPLATSTR("connection no longer exists"));
|
||||||
|
}
|
||||||
connection->m_transport = transport;
|
connection->m_transport = transport;
|
||||||
|
return pplx::task_from_result();
|
||||||
});
|
});
|
||||||
}, m_disconnect_cts.get_token())
|
}, m_disconnect_cts.get_token())
|
||||||
.then([start_tce, connection](pplx::task<void> previous_task)
|
.then([start_tce, weak_connection](pplx::task<void> previous_task)
|
||||||
{
|
{
|
||||||
|
auto connection = weak_connection.lock();
|
||||||
|
if (!connection)
|
||||||
|
{
|
||||||
|
return pplx::task_from_exception<void>(_XPLATSTR("connection no longer exists"));
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
previous_task.get();
|
previous_task.get();
|
||||||
|
|
@ -144,20 +164,22 @@ namespace signalr
|
||||||
connection->m_start_completed_event.set();
|
connection->m_start_completed_event.set();
|
||||||
start_tce.set_exception(std::current_exception());
|
start_tce.set_exception(std::current_exception());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pplx::task_from_result();
|
||||||
});
|
});
|
||||||
|
|
||||||
return pplx::create_task(start_tce);
|
return pplx::create_task(start_tce);
|
||||||
}
|
}
|
||||||
|
|
||||||
pplx::task<std::shared_ptr<transport>> connection_impl::start_transport(negotiation_response negotiation_response)
|
pplx::task<std::shared_ptr<transport>> connection_impl::start_transport()
|
||||||
{
|
{
|
||||||
auto connection = shared_from_this();
|
auto connection = shared_from_this();
|
||||||
|
|
||||||
pplx::task_completion_event<void> connect_request_tce;
|
pplx::task_completion_event<void> connect_request_tce;
|
||||||
|
|
||||||
auto weak_connection = std::weak_ptr<connection_impl>(connection);
|
auto weak_connection = std::weak_ptr<connection_impl>(connection);
|
||||||
auto& disconnect_cts = m_disconnect_cts;
|
const auto& disconnect_cts = m_disconnect_cts;
|
||||||
auto& logger = m_logger;
|
const auto& logger = m_logger;
|
||||||
|
|
||||||
auto process_response_callback =
|
auto process_response_callback =
|
||||||
[weak_connection, disconnect_cts, logger](const utility::string_t& response) mutable
|
[weak_connection, disconnect_cts, logger](const utility::string_t& response) mutable
|
||||||
|
|
@ -169,7 +191,7 @@ namespace signalr
|
||||||
if (disconnect_cts.get_token().is_canceled())
|
if (disconnect_cts.get_token().is_canceled())
|
||||||
{
|
{
|
||||||
logger.log(trace_level::info,
|
logger.log(trace_level::info,
|
||||||
utility::string_t(_XPLATSTR("ignoring stray message received after connection was restarted. message: "))
|
utility::string_t{ _XPLATSTR("ignoring stray message received after connection was restarted. message: " })
|
||||||
.append(response));
|
.append(response));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +214,7 @@ namespace signalr
|
||||||
if (disconnect_cts.get_token().is_canceled())
|
if (disconnect_cts.get_token().is_canceled())
|
||||||
{
|
{
|
||||||
logger.log(trace_level::info,
|
logger.log(trace_level::info,
|
||||||
utility::string_t(_XPLATSTR("ignoring stray error received after connection was restarted. error: "))
|
utility::string_t{ _XPLATSTR("ignoring stray error received after connection was restarted. error: " })
|
||||||
.append(utility::conversions::to_string_t(e.what())));
|
.append(utility::conversions::to_string_t(e.what())));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -206,7 +228,7 @@ namespace signalr
|
||||||
transport_type::websockets, connection->m_logger, connection->m_signalr_client_config,
|
transport_type::websockets, connection->m_logger, connection->m_signalr_client_config,
|
||||||
process_response_callback, error_callback);
|
process_response_callback, error_callback);
|
||||||
|
|
||||||
pplx::create_task([negotiation_response, connect_request_tce, disconnect_cts, weak_connection]()
|
pplx::create_task([connect_request_tce, disconnect_cts, weak_connection]()
|
||||||
{
|
{
|
||||||
// TODO? std::this_thread::sleep_for(std::chrono::milliseconds(negotiation_response.transport_connect_timeout));
|
// TODO? std::this_thread::sleep_for(std::chrono::milliseconds(negotiation_response.transport_connect_timeout));
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
||||||
|
|
@ -290,11 +312,11 @@ namespace signalr
|
||||||
// we won't crash.
|
// we won't crash.
|
||||||
auto transport = m_transport;
|
auto transport = m_transport;
|
||||||
|
|
||||||
auto connection_state = get_connection_state();
|
const auto connection_state = get_connection_state();
|
||||||
if (connection_state != signalr::connection_state::connected || !transport)
|
if (connection_state != signalr::connection_state::connected || !transport)
|
||||||
{
|
{
|
||||||
return pplx::task_from_exception<void>(signalr_exception(
|
return pplx::task_from_exception<void>(signalr_exception(
|
||||||
utility::string_t{_XPLATSTR("cannot send data when the connection is not in the connected state. current connection state: " })
|
utility::string_t(_XPLATSTR("cannot send data when the connection is not in the connected state. current connection state: "))
|
||||||
.append(translate_connection_state(connection_state))));
|
.append(translate_connection_state(connection_state))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -368,7 +390,7 @@ namespace signalr
|
||||||
std::lock_guard<std::mutex> lock(m_stop_lock);
|
std::lock_guard<std::mutex> lock(m_stop_lock);
|
||||||
m_logger.log(trace_level::info, _XPLATSTR("acquired lock in shutdown()"));
|
m_logger.log(trace_level::info, _XPLATSTR("acquired lock in shutdown()"));
|
||||||
|
|
||||||
auto current_state = get_connection_state();
|
const auto current_state = get_connection_state();
|
||||||
if (current_state == connection_state::disconnected)
|
if (current_state == connection_state::disconnected)
|
||||||
{
|
{
|
||||||
return pplx::task_from_result();
|
return pplx::task_from_result();
|
||||||
|
|
@ -381,7 +403,7 @@ namespace signalr
|
||||||
// affect the other invocation which is using it.
|
// affect the other invocation which is using it.
|
||||||
auto cts = pplx::cancellation_token_source();
|
auto cts = pplx::cancellation_token_source();
|
||||||
cts.cancel();
|
cts.cancel();
|
||||||
return pplx::create_task([](){}, cts.get_token());
|
return pplx::create_task([]() noexcept {}, cts.get_token());
|
||||||
}
|
}
|
||||||
|
|
||||||
// we request a cancellation of the ongoing start (if any) and wait until it is canceled
|
// we request a cancellation of the ongoing start (if any) and wait until it is canceled
|
||||||
|
|
@ -408,7 +430,7 @@ namespace signalr
|
||||||
return m_transport->disconnect();
|
return m_transport->disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_state connection_impl::get_connection_state() const
|
connection_state connection_impl::get_connection_state() const noexcept
|
||||||
{
|
{
|
||||||
return m_connection_state.load();
|
return m_connection_state.load();
|
||||||
}
|
}
|
||||||
|
|
@ -429,13 +451,6 @@ namespace signalr
|
||||||
m_message_received = message_received;
|
m_message_received = message_received;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connection_impl::set_connection_data(const utility::string_t& connection_data)
|
|
||||||
{
|
|
||||||
_ASSERTE(get_connection_state() == connection_state::disconnected);
|
|
||||||
|
|
||||||
m_connection_data = connection_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connection_impl::set_client_config(const signalr_client_config& config)
|
void connection_impl::set_client_config(const signalr_client_config& config)
|
||||||
{
|
{
|
||||||
ensure_disconnected(_XPLATSTR("cannot set client config when the connection is not in the disconnected state. "));
|
ensure_disconnected(_XPLATSTR("cannot set client config when the connection is not in the disconnected state. "));
|
||||||
|
|
@ -450,7 +465,7 @@ namespace signalr
|
||||||
|
|
||||||
void connection_impl::ensure_disconnected(const utility::string_t& error_message)
|
void connection_impl::ensure_disconnected(const utility::string_t& error_message)
|
||||||
{
|
{
|
||||||
auto state = get_connection_state();
|
const auto state = get_connection_state();
|
||||||
if (state != connection_state::disconnected)
|
if (state != connection_state::disconnected)
|
||||||
{
|
{
|
||||||
throw signalr_exception(
|
throw signalr_exception(
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,13 @@ namespace signalr
|
||||||
pplx::task<void> send(const utility::string_t &data);
|
pplx::task<void> send(const utility::string_t &data);
|
||||||
pplx::task<void> stop();
|
pplx::task<void> stop();
|
||||||
|
|
||||||
connection_state get_connection_state() const;
|
connection_state get_connection_state() const noexcept;
|
||||||
utility::string_t get_connection_id() const;
|
utility::string_t get_connection_id() const;
|
||||||
|
|
||||||
void set_message_received(const std::function<void(const utility::string_t&)>& message_received);
|
void set_message_received(const std::function<void(const utility::string_t&)>& message_received);
|
||||||
void set_disconnected(const std::function<void()>& disconnected);
|
void set_disconnected(const std::function<void()>& disconnected);
|
||||||
void set_client_config(const signalr_client_config& config);
|
void set_client_config(const signalr_client_config& config);
|
||||||
|
|
||||||
void set_connection_data(const utility::string_t& connection_data);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
web::uri m_base_url;
|
web::uri m_base_url;
|
||||||
utility::string_t m_query_string;
|
utility::string_t m_query_string;
|
||||||
|
|
@ -74,7 +72,7 @@ namespace signalr
|
||||||
connection_impl(const utility::string_t& url, const utility::string_t& query_string, trace_level trace_level, const std::shared_ptr<log_writer>& log_writer,
|
connection_impl(const utility::string_t& url, const utility::string_t& query_string, trace_level trace_level, const std::shared_ptr<log_writer>& log_writer,
|
||||||
std::unique_ptr<web_request_factory> web_request_factory, std::unique_ptr<transport_factory> transport_factory);
|
std::unique_ptr<web_request_factory> web_request_factory, std::unique_ptr<transport_factory> transport_factory);
|
||||||
|
|
||||||
pplx::task<std::shared_ptr<transport>> start_transport(negotiation_response negotiation_response);
|
pplx::task<std::shared_ptr<transport>> start_transport();
|
||||||
pplx::task<void> send_connect_request(const std::shared_ptr<transport>& transport,
|
pplx::task<void> send_connect_request(const std::shared_ptr<transport>& transport,
|
||||||
const pplx::task_completion_event<void>& connect_request_tce);
|
const pplx::task_completion_event<void>& connect_request_tce);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace signalr
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static web::websockets::client::websocket_client_config create_client_config(const signalr_client_config& signalr_client_config)
|
static web::websockets::client::websocket_client_config create_client_config(const signalr_client_config& signalr_client_config) noexcept
|
||||||
{
|
{
|
||||||
auto websocket_client_config = signalr_client_config.get_websocket_client_config();
|
auto websocket_client_config = signalr_client_config.get_websocket_client_config();
|
||||||
websocket_client_config.headers() = signalr_client_config.get_http_headers();
|
websocket_client_config.headers() = signalr_client_config.get_http_headers();
|
||||||
|
|
@ -17,7 +17,7 @@ namespace signalr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default_websocket_client::default_websocket_client(const signalr_client_config& signalr_client_config)
|
default_websocket_client::default_websocket_client(const signalr_client_config& signalr_client_config) noexcept
|
||||||
: m_underlying_client(create_client_config(signalr_client_config))
|
: m_underlying_client(create_client_config(signalr_client_config))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
@ -47,4 +47,4 @@ namespace signalr
|
||||||
{
|
{
|
||||||
return m_underlying_client.close();
|
return m_underlying_client.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace signalr
|
||||||
class default_websocket_client : public websocket_client
|
class default_websocket_client : public websocket_client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit default_websocket_client(const signalr_client_config& signalr_client_config = signalr_client_config{});
|
explicit default_websocket_client(const signalr_client_config& signalr_client_config = signalr_client_config{}) noexcept;
|
||||||
|
|
||||||
pplx::task<void> connect(const web::uri &url) override;
|
pplx::task<void> connect(const web::uri &url) override;
|
||||||
|
|
||||||
|
|
@ -25,4 +25,4 @@ namespace signalr
|
||||||
private:
|
private:
|
||||||
web::websockets::client::websocket_client m_underlying_client;
|
web::websockets::client::websocket_client m_underlying_client;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace signalr
|
||||||
|
|
||||||
static const unsigned int timeout_infinite = 0xFFFFFFFF;
|
static const unsigned int timeout_infinite = 0xFFFFFFFF;
|
||||||
|
|
||||||
event()
|
event() noexcept
|
||||||
: m_signaled(false)
|
: m_signaled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -42,13 +42,13 @@ namespace signalr
|
||||||
std::unique_lock<std::mutex> lock(m_lock);
|
std::unique_lock<std::mutex> lock(m_lock);
|
||||||
if (timeout == event::timeout_infinite)
|
if (timeout == event::timeout_infinite)
|
||||||
{
|
{
|
||||||
m_condition.wait(lock, [this]() { return m_signaled; });
|
m_condition.wait(lock, [this]() noexcept { return m_signaled; });
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::chrono::milliseconds period(timeout);
|
const std::chrono::milliseconds period(timeout);
|
||||||
auto status = m_condition.wait_for(lock, period, [this]() { return m_signaled; });
|
const auto status = m_condition.wait_for(lock, period, [this]() noexcept { return m_signaled; });
|
||||||
assert(status == m_signaled);
|
assert(status == m_signaled);
|
||||||
// Return 0 if the wait completed as a result of signaling the event. Otherwise, return timeout_infinite
|
// Return 0 if the wait completed as a result of signaling the event. Otherwise, return timeout_infinite
|
||||||
return status ? 0 : event::timeout_infinite;
|
return status ? 0 : event::timeout_infinite;
|
||||||
|
|
|
||||||
|
|
@ -37,24 +37,24 @@ namespace signalr
|
||||||
return m_pImpl->on(event_name, handler);
|
return m_pImpl->on(event_name, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
pplx::task<web::json::value> hub_connection::invoke_json(const utility::string_t& method_name, const web::json::value& arguments)
|
pplx::task<web::json::value> hub_connection::invoke(const utility::string_t& method_name, const web::json::value& arguments)
|
||||||
{
|
{
|
||||||
if (!m_pImpl)
|
if (!m_pImpl)
|
||||||
{
|
{
|
||||||
throw signalr_exception(_XPLATSTR("invoke() cannot be called on uninitialized hub_connection instance"));
|
throw signalr_exception(_XPLATSTR("invoke() cannot be called on uninitialized hub_connection instance"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_pImpl->invoke_json(method_name, arguments);
|
return m_pImpl->invoke(method_name, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
pplx::task<void> hub_connection::invoke_void(const utility::string_t& method_name, const web::json::value& arguments)
|
pplx::task<void> hub_connection::send(const utility::string_t& method_name, const web::json::value& arguments)
|
||||||
{
|
{
|
||||||
if (!m_pImpl)
|
if (!m_pImpl)
|
||||||
{
|
{
|
||||||
throw signalr_exception(_XPLATSTR("invoke() cannot be called on uninitialized hub_connection instance"));
|
throw signalr_exception(_XPLATSTR("send() cannot be called on uninitialized hub_connection instance"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_pImpl->invoke_void(method_name, arguments);
|
return m_pImpl->send(method_name, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_state hub_connection::get_connection_state() const
|
connection_state hub_connection::get_connection_state() const
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ namespace signalr
|
||||||
: m_connection(connection_impl::create(url, query_string, trace_level, log_writer,
|
: m_connection(connection_impl::create(url, query_string, trace_level, log_writer,
|
||||||
std::move(web_request_factory), std::move(transport_factory))),m_logger(log_writer, trace_level),
|
std::move(web_request_factory), std::move(transport_factory))),m_logger(log_writer, trace_level),
|
||||||
m_callback_manager(json::value::parse(_XPLATSTR("{ \"error\" : \"connection went out of scope before invocation result was received\"}"))),
|
m_callback_manager(json::value::parse(_XPLATSTR("{ \"error\" : \"connection went out of scope before invocation result was received\"}"))),
|
||||||
m_disconnected([]() {})
|
m_disconnected([]() noexcept {}), m_handshakeReceived(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void hub_connection_impl::initialize()
|
void hub_connection_impl::initialize()
|
||||||
|
|
@ -108,9 +108,9 @@ namespace signalr
|
||||||
|
|
||||||
m_handshakeTask = pplx::task_completion_event<void>();
|
m_handshakeTask = pplx::task_completion_event<void>();
|
||||||
m_handshakeReceived = false;
|
m_handshakeReceived = false;
|
||||||
auto weak_connection = m_connection->weak_from_this();
|
auto weak_connection = weak_from_this();
|
||||||
return m_connection->start()
|
return m_connection->start()
|
||||||
.then([weak_connection, this](pplx::task<void> startTask)
|
.then([weak_connection](pplx::task<void> startTask)
|
||||||
{
|
{
|
||||||
startTask.get();
|
startTask.get();
|
||||||
auto connection = weak_connection.lock();
|
auto connection = weak_connection.lock();
|
||||||
|
|
@ -119,11 +119,17 @@ namespace signalr
|
||||||
// The connection has been destructed
|
// The connection has been destructed
|
||||||
return pplx::task_from_exception<void>(signalr_exception(_XPLATSTR("the hub connection has been deconstructed")));
|
return pplx::task_from_exception<void>(signalr_exception(_XPLATSTR("the hub connection has been deconstructed")));
|
||||||
}
|
}
|
||||||
return connection->send(_XPLATSTR("{\"protocol\":\"json\",\"version\":1}\x1e"))
|
return connection->m_connection->send(_XPLATSTR("{\"protocol\":\"json\",\"version\":1}\x1e"))
|
||||||
.then([this](pplx::task<void> previous_task)
|
.then([weak_connection](pplx::task<void> previous_task)
|
||||||
{
|
{
|
||||||
|
auto connection = weak_connection.lock();
|
||||||
|
if (!connection)
|
||||||
|
{
|
||||||
|
// The connection has been destructed
|
||||||
|
return pplx::task_from_exception<void>(signalr_exception(_XPLATSTR("the hub connection has been deconstructed")));
|
||||||
|
}
|
||||||
previous_task.get();
|
previous_task.get();
|
||||||
return pplx::task<void>(m_handshakeTask);
|
return pplx::task<void>(connection->m_handshakeTask);
|
||||||
})
|
})
|
||||||
.then([weak_connection](pplx::task<void> previous_task)
|
.then([weak_connection](pplx::task<void> previous_task)
|
||||||
{
|
{
|
||||||
|
|
@ -137,7 +143,7 @@ namespace signalr
|
||||||
auto connection = weak_connection.lock();
|
auto connection = weak_connection.lock();
|
||||||
if (connection)
|
if (connection)
|
||||||
{
|
{
|
||||||
connection->stop();
|
connection->m_connection->stop();
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
@ -267,7 +273,7 @@ namespace signalr
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pplx::task<json::value> hub_connection_impl::invoke_json(const utility::string_t& method_name, const json::value& arguments)
|
pplx::task<json::value> hub_connection_impl::invoke(const utility::string_t& method_name, const json::value& arguments)
|
||||||
{
|
{
|
||||||
_ASSERTE(arguments.is_array());
|
_ASSERTE(arguments.is_array());
|
||||||
|
|
||||||
|
|
@ -283,7 +289,7 @@ namespace signalr
|
||||||
return pplx::create_task(tce);
|
return pplx::create_task(tce);
|
||||||
}
|
}
|
||||||
|
|
||||||
pplx::task<void> hub_connection_impl::invoke_void(const utility::string_t& method_name, const json::value& arguments)
|
pplx::task<void> hub_connection_impl::send(const utility::string_t& method_name, const json::value& arguments)
|
||||||
{
|
{
|
||||||
_ASSERTE(arguments.is_array());
|
_ASSERTE(arguments.is_array());
|
||||||
|
|
||||||
|
|
@ -337,7 +343,7 @@ namespace signalr
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_state hub_connection_impl::get_connection_state() const
|
connection_state hub_connection_impl::get_connection_state() const noexcept
|
||||||
{
|
{
|
||||||
return m_connection->get_connection_state();
|
return m_connection->get_connection_state();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ namespace signalr
|
||||||
|
|
||||||
void on(const utility::string_t& event_name, const std::function<void(const json::value &)>& handler);
|
void on(const utility::string_t& event_name, const std::function<void(const json::value &)>& handler);
|
||||||
|
|
||||||
pplx::task<json::value> invoke_json(const utility::string_t& method_name, const json::value& arguments);
|
pplx::task<json::value> invoke(const utility::string_t& method_name, const json::value& arguments);
|
||||||
pplx::task<void> invoke_void(const utility::string_t& method_name, const json::value& arguments);
|
pplx::task<void> send(const utility::string_t& method_name, const json::value& arguments);
|
||||||
|
|
||||||
pplx::task<void> start();
|
pplx::task<void> start();
|
||||||
pplx::task<void> stop();
|
pplx::task<void> stop();
|
||||||
|
|
||||||
connection_state get_connection_state() const;
|
connection_state get_connection_state() const noexcept;
|
||||||
utility::string_t get_connection_id() const;
|
utility::string_t get_connection_id() const;
|
||||||
|
|
||||||
void set_client_config(const signalr_client_config& config);
|
void set_client_config(const signalr_client_config& config);
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@
|
||||||
|
|
||||||
namespace signalr
|
namespace signalr
|
||||||
{
|
{
|
||||||
logger::logger(const std::shared_ptr<log_writer>& log_writer, trace_level trace_level)
|
logger::logger(const std::shared_ptr<log_writer>& log_writer, trace_level trace_level) noexcept
|
||||||
: m_log_writer(log_writer), m_trace_level(trace_level)
|
: m_log_writer(log_writer), m_trace_level(trace_level)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void logger::log(trace_level level, const utility::string_t& entry)
|
void logger::log(trace_level level, const utility::string_t& entry) const
|
||||||
{
|
{
|
||||||
if ((level & m_trace_level) != trace_level::none)
|
if ((level & m_trace_level) != trace_level::none)
|
||||||
{
|
{
|
||||||
|
|
@ -54,4 +54,4 @@ namespace signalr
|
||||||
return _XPLATSTR("(unknown)");
|
return _XPLATSTR("(unknown)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ namespace signalr
|
||||||
class logger
|
class logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
logger(const std::shared_ptr<log_writer>& log_writer, trace_level trace_level);
|
logger(const std::shared_ptr<log_writer>& log_writer, trace_level trace_level) noexcept;
|
||||||
|
|
||||||
void log(trace_level level, const utility::string_t& entry);
|
void log(trace_level level, const utility::string_t& entry) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<log_writer> m_log_writer;
|
std::shared_ptr<log_writer> m_log_writer;
|
||||||
|
|
@ -22,4 +22,4 @@ namespace signalr
|
||||||
|
|
||||||
static utility::string_t translate_trace_level(trace_level trace_level);
|
static utility::string_t translate_trace_level(trace_level trace_level);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ namespace signalr
|
||||||
negotiation_response_json[_XPLATSTR("availableTransports")],
|
negotiation_response_json[_XPLATSTR("availableTransports")],
|
||||||
};
|
};
|
||||||
|
|
||||||
return response;
|
return std::move(response);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace signalr
|
||||||
m_http_client_config = http_client_config;
|
m_http_client_config = http_client_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
web::websockets::client::websocket_client_config signalr_client_config::get_websocket_client_config() const
|
web::websockets::client::websocket_client_config signalr_client_config::get_websocket_client_config() const noexcept
|
||||||
{
|
{
|
||||||
return m_websocket_client_config;
|
return m_websocket_client_config;
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ namespace signalr
|
||||||
m_websocket_client_config = websocket_client_config;
|
m_websocket_client_config = websocket_client_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
web::http::http_headers signalr_client_config::get_http_headers() const
|
web::http::http_headers signalr_client_config::get_http_headers() const noexcept
|
||||||
{
|
{
|
||||||
return m_http_headers;
|
return m_http_headers;
|
||||||
}
|
}
|
||||||
|
|
@ -49,4 +49,4 @@ namespace signalr
|
||||||
{
|
{
|
||||||
m_http_headers = http_headers;
|
m_http_headers = http_headers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ namespace signalr
|
||||||
_ASSERTE(transport == transport_type::websockets || transport == transport_type::long_polling);
|
_ASSERTE(transport == transport_type::websockets || transport == transport_type::long_polling);
|
||||||
|
|
||||||
return transport == transport_type::websockets
|
return transport == transport_type::websockets
|
||||||
? _XPLATSTR("webSockets")
|
? utility::string_t(_XPLATSTR("webSockets"))
|
||||||
: _XPLATSTR("longPolling");
|
: utility::string_t(_XPLATSTR("longPolling"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_transport(web::uri_builder &builder, transport_type transport)
|
void append_transport(web::uri_builder &builder, transport_type transport)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace signalr
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
transport_type websocket_transport::get_transport_type() const
|
transport_type websocket_transport::get_transport_type() const noexcept
|
||||||
{
|
{
|
||||||
return transport_type::websockets;
|
return transport_type::websockets;
|
||||||
}
|
}
|
||||||
|
|
@ -236,10 +236,10 @@ namespace signalr
|
||||||
std::shared_ptr<websocket_client> websocket_transport::safe_get_websocket_client()
|
std::shared_ptr<websocket_client> websocket_transport::safe_get_websocket_client()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_websocket_client_lock);
|
const std::lock_guard<std::mutex> lock(m_websocket_client_lock);
|
||||||
auto websocket_client = m_websocket_client;
|
auto websocket_client = m_websocket_client;
|
||||||
|
|
||||||
return websocket_client;
|
return websocket_client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace signalr
|
||||||
|
|
||||||
pplx::task<void> disconnect() override;
|
pplx::task<void> disconnect() override;
|
||||||
|
|
||||||
transport_type get_transport_type() const override;
|
transport_type get_transport_type() const noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
websocket_transport(const std::function<std::shared_ptr<websocket_client>()>& websocket_client_factory,
|
websocket_transport(const std::function<std::shared_ptr<websocket_client>()>& websocket_client_factory,
|
||||||
|
|
@ -52,4 +52,4 @@ namespace signalr
|
||||||
|
|
||||||
std::shared_ptr<websocket_client> safe_get_websocket_client();
|
std::shared_ptr<websocket_client> safe_get_websocket_client();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,4 @@
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="packages.config" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -64,7 +64,7 @@ TEST(connection_impl_start, connection_state_is_connecting_when_connection_is_be
|
||||||
|
|
||||||
auto connection = create_connection(websocket_client, writer, trace_level::errors);
|
auto connection = create_connection(websocket_client, writer, trace_level::errors);
|
||||||
|
|
||||||
connection->start()
|
auto startTask = connection->start()
|
||||||
// this test is not set up to connect successfully so we have to observe exceptions otherwise
|
// this test is not set up to connect successfully so we have to observe exceptions otherwise
|
||||||
// other tests may fail due to an unobserved exception from the outstanding start task
|
// other tests may fail due to an unobserved exception from the outstanding start task
|
||||||
.then([](pplx::task<void> start_task)
|
.then([](pplx::task<void> start_task)
|
||||||
|
|
@ -78,6 +78,7 @@ TEST(connection_impl_start, connection_state_is_connecting_when_connection_is_be
|
||||||
});
|
});
|
||||||
|
|
||||||
ASSERT_EQ(connection->get_connection_state(), connection_state::connecting);
|
ASSERT_EQ(connection->get_connection_state(), connection_state::connecting);
|
||||||
|
startTask.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(connection_impl_start, connection_state_is_connected_when_connection_established_succesfully)
|
TEST(connection_impl_start, connection_state_is_connected_when_connection_established_succesfully)
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,7 @@ TEST(stop, stop_cancels_pending_callbacks)
|
||||||
|
|
||||||
auto hub_connection = create_hub_connection(websocket_client);
|
auto hub_connection = create_hub_connection(websocket_client);
|
||||||
hub_connection->start().get();
|
hub_connection->start().get();
|
||||||
auto t = hub_connection->invoke_json(_XPLATSTR("method"), json::value::array());
|
auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
hub_connection->stop();
|
hub_connection->stop();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -262,7 +262,7 @@ TEST(stop, pending_callbacks_finished_if_hub_connections_goes_out_of_scope)
|
||||||
{
|
{
|
||||||
auto hub_connection = create_hub_connection(websocket_client);
|
auto hub_connection = create_hub_connection(websocket_client);
|
||||||
hub_connection->start().get();
|
hub_connection->start().get();
|
||||||
t = hub_connection->invoke_json(_XPLATSTR("method"), json::value::array());
|
t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -309,7 +309,7 @@ TEST(hub_invocation, hub_connection_invokes_users_code_on_hub_invocations)
|
||||||
ASSERT_EQ(_XPLATSTR("[\"message\",1]"), *payload);
|
ASSERT_EQ(_XPLATSTR("[\"message\",1]"), *payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke, invoke_creates_correct_payload)
|
TEST(send, creates_correct_payload)
|
||||||
{
|
{
|
||||||
utility::string_t payload;
|
utility::string_t payload;
|
||||||
bool handshakeReceived = false;
|
bool handshakeReceived = false;
|
||||||
|
|
@ -321,7 +321,7 @@ TEST(invoke, invoke_creates_correct_payload)
|
||||||
if (handshakeReceived)
|
if (handshakeReceived)
|
||||||
{
|
{
|
||||||
payload = m;
|
payload = m;
|
||||||
return pplx::task_from_exception<void>(std::runtime_error("error"));
|
return pplx::task_from_result();
|
||||||
}
|
}
|
||||||
handshakeReceived = true;
|
handshakeReceived = true;
|
||||||
return pplx::task_from_result();
|
return pplx::task_from_result();
|
||||||
|
|
@ -330,16 +330,74 @@ TEST(invoke, invoke_creates_correct_payload)
|
||||||
auto hub_connection = create_hub_connection(websocket_client);
|
auto hub_connection = create_hub_connection(websocket_client);
|
||||||
hub_connection->start().get();
|
hub_connection->start().get();
|
||||||
|
|
||||||
|
hub_connection->send(_XPLATSTR("method"), json::value::array()).get();
|
||||||
|
|
||||||
|
ASSERT_EQ(_XPLATSTR("{\"arguments\":[],\"target\":\"method\",\"type\":1}\x1e"), payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(send, does_not_wait_for_server_response)
|
||||||
|
{
|
||||||
|
int call_number = -1;
|
||||||
|
pplx::task_completion_event<void> waitForSend;
|
||||||
|
|
||||||
|
auto websocket_client = create_test_websocket_client(
|
||||||
|
/* receive function */ [waitForSend, call_number]() mutable
|
||||||
|
{
|
||||||
|
std::string responses[]
|
||||||
|
{
|
||||||
|
"{ }\x1e",
|
||||||
|
"{}"
|
||||||
|
};
|
||||||
|
|
||||||
|
call_number = std::min(call_number + 1, 1);
|
||||||
|
|
||||||
|
if (call_number == 1)
|
||||||
|
{
|
||||||
|
pplx::task<void>(waitForSend).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pplx::task_from_result(responses[call_number]);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto hub_connection = create_hub_connection(websocket_client);
|
||||||
|
hub_connection->start().get();
|
||||||
|
|
||||||
|
// wont block waiting for server response
|
||||||
|
hub_connection->send(_XPLATSTR("method"), json::value::array()).get();
|
||||||
|
waitForSend.set();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(invoke, creates_correct_payload)
|
||||||
|
{
|
||||||
|
utility::string_t payload;
|
||||||
|
bool handshakeReceived = false;
|
||||||
|
|
||||||
|
auto websocket_client = create_test_websocket_client(
|
||||||
|
/* receive function */ []() { return pplx::task_from_result(std::string("{ }\x1e")); },
|
||||||
|
/* send function */[&payload, &handshakeReceived](const utility::string_t& m)
|
||||||
|
{
|
||||||
|
if (handshakeReceived)
|
||||||
|
{
|
||||||
|
payload = m;
|
||||||
|
return pplx::task_from_exception<void>(std::runtime_error("error"));
|
||||||
|
}
|
||||||
|
handshakeReceived = true;
|
||||||
|
return pplx::task_from_result();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto hub_connection = create_hub_connection(websocket_client);
|
||||||
|
hub_connection->start().get();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hub_connection->invoke_void(_XPLATSTR("method"), json::value::array()).get();
|
hub_connection->invoke(_XPLATSTR("method"), json::value::array()).get();
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
// the send is not setup to succeed because it's not needed in this test
|
// the invoke is not setup to succeed because it's not needed in this test
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(_XPLATSTR("{\"arguments\":[],\"target\":\"method\",\"type\":1}\x1e"), payload);
|
ASSERT_EQ(_XPLATSTR("{\"arguments\":[],\"invocationId\":\"0\",\"target\":\"method\",\"type\":1}\x1e"), payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke, callback_not_called_if_send_throws)
|
TEST(invoke, callback_not_called_if_send_throws)
|
||||||
|
|
@ -362,7 +420,7 @@ TEST(invoke, callback_not_called_if_send_throws)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hub_connection->invoke_void(_XPLATSTR("method"), json::value::array()).get();
|
hub_connection->invoke(_XPLATSTR("method"), json::value::array()).get();
|
||||||
ASSERT_TRUE(false); // exception expected but not thrown
|
ASSERT_TRUE(false); // exception expected but not thrown
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e)
|
catch (const std::runtime_error& e)
|
||||||
|
|
@ -376,7 +434,7 @@ TEST(invoke, callback_not_called_if_send_throws)
|
||||||
hub_connection->stop().get();
|
hub_connection->stop().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke_json, invoke_returns_value_returned_from_the_server)
|
TEST(invoke, invoke_returns_value_returned_from_the_server)
|
||||||
{
|
{
|
||||||
auto callback_registered_event = std::make_shared<event>();
|
auto callback_registered_event = std::make_shared<event>();
|
||||||
|
|
||||||
|
|
@ -404,7 +462,7 @@ TEST(invoke_json, invoke_returns_value_returned_from_the_server)
|
||||||
auto result = hub_connection->start()
|
auto result = hub_connection->start()
|
||||||
.then([hub_connection, callback_registered_event]()
|
.then([hub_connection, callback_registered_event]()
|
||||||
{
|
{
|
||||||
auto t = hub_connection->invoke_json(_XPLATSTR("method"), json::value::array());
|
auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
callback_registered_event->set();
|
callback_registered_event->set();
|
||||||
return t;
|
return t;
|
||||||
}).get();
|
}).get();
|
||||||
|
|
@ -412,7 +470,7 @@ TEST(invoke_json, invoke_returns_value_returned_from_the_server)
|
||||||
ASSERT_EQ(_XPLATSTR("\"abc\""), result.serialize());
|
ASSERT_EQ(_XPLATSTR("\"abc\""), result.serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke_json, invoke_propagates_errors_from_server_as_exceptions)
|
TEST(invoke, invoke_propagates_hub_errors_from_server_as_hub_exceptions)
|
||||||
{
|
{
|
||||||
auto callback_registered_event = std::make_shared<event>();
|
auto callback_registered_event = std::make_shared<event>();
|
||||||
|
|
||||||
|
|
@ -442,50 +500,7 @@ TEST(invoke_json, invoke_propagates_errors_from_server_as_exceptions)
|
||||||
hub_connection->start()
|
hub_connection->start()
|
||||||
.then([hub_connection, callback_registered_event]()
|
.then([hub_connection, callback_registered_event]()
|
||||||
{
|
{
|
||||||
auto t = hub_connection->invoke_json(_XPLATSTR("method"), json::value::array());
|
auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
callback_registered_event->set();
|
|
||||||
return t;
|
|
||||||
}).get();
|
|
||||||
|
|
||||||
ASSERT_TRUE(false); // exception expected but not thrown
|
|
||||||
}
|
|
||||||
catch (const std::runtime_error& e)
|
|
||||||
{
|
|
||||||
ASSERT_STREQ("\"Ooops\"", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(invoke_json, invoke_propagates_hub_errors_from_server_as_hub_exceptions)
|
|
||||||
{
|
|
||||||
auto callback_registered_event = std::make_shared<event>();
|
|
||||||
|
|
||||||
int call_number = -1;
|
|
||||||
auto websocket_client = create_test_websocket_client(
|
|
||||||
/* receive function */ [call_number, callback_registered_event]()
|
|
||||||
mutable {
|
|
||||||
std::string responses[]
|
|
||||||
{
|
|
||||||
"{ }\x1e",
|
|
||||||
"{ \"type\": 3, \"invocationId\": \"0\", \"error\": \"Ooops\" }\x1e"
|
|
||||||
};
|
|
||||||
|
|
||||||
call_number = std::min(call_number + 1, 1);
|
|
||||||
|
|
||||||
if (call_number > 0)
|
|
||||||
{
|
|
||||||
callback_registered_event->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pplx::task_from_result(responses[call_number]);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto hub_connection = create_hub_connection(websocket_client);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
hub_connection->start()
|
|
||||||
.then([hub_connection, callback_registered_event]()
|
|
||||||
{
|
|
||||||
auto t = hub_connection->invoke_json(_XPLATSTR("method"), json::value::array());
|
|
||||||
callback_registered_event->set();
|
callback_registered_event->set();
|
||||||
return t;
|
return t;
|
||||||
}).get();
|
}).get();
|
||||||
|
|
@ -498,7 +513,7 @@ TEST(invoke_json, invoke_propagates_hub_errors_from_server_as_hub_exceptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke_void, invoke_unblocks_task_when_server_completes_call)
|
TEST(invoke, unblocks_task_when_server_completes_call)
|
||||||
{
|
{
|
||||||
auto callback_registered_event = std::make_shared<event>();
|
auto callback_registered_event = std::make_shared<event>();
|
||||||
|
|
||||||
|
|
@ -509,7 +524,7 @@ TEST(invoke_void, invoke_unblocks_task_when_server_completes_call)
|
||||||
std::string responses[]
|
std::string responses[]
|
||||||
{
|
{
|
||||||
"{ }\x1e",
|
"{ }\x1e",
|
||||||
"{\"I\":\"0\"}\x1e"
|
"{ \"type\": 3, \"invocationId\": \"0\" }\x1e"
|
||||||
};
|
};
|
||||||
|
|
||||||
call_number = std::min(call_number + 1, 1);
|
call_number = std::min(call_number + 1, 1);
|
||||||
|
|
@ -526,7 +541,7 @@ TEST(invoke_void, invoke_unblocks_task_when_server_completes_call)
|
||||||
hub_connection->start()
|
hub_connection->start()
|
||||||
.then([hub_connection, callback_registered_event]()
|
.then([hub_connection, callback_registered_event]()
|
||||||
{
|
{
|
||||||
auto t = hub_connection->invoke_void(_XPLATSTR("method"), json::value::array());
|
auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
callback_registered_event->set();
|
callback_registered_event->set();
|
||||||
return t;
|
return t;
|
||||||
}).get();
|
}).get();
|
||||||
|
|
@ -535,7 +550,7 @@ TEST(invoke_void, invoke_unblocks_task_when_server_completes_call)
|
||||||
ASSERT_TRUE(true);
|
ASSERT_TRUE(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke_void, invoke_logs_if_callback_for_given_id_not_found)
|
TEST(receive, logs_if_callback_for_given_id_not_found)
|
||||||
{
|
{
|
||||||
auto message_received_event = std::make_shared<event>();
|
auto message_received_event = std::make_shared<event>();
|
||||||
auto handshake_sent = std::make_shared<event>();
|
auto handshake_sent = std::make_shared<event>();
|
||||||
|
|
@ -547,7 +562,7 @@ TEST(invoke_void, invoke_logs_if_callback_for_given_id_not_found)
|
||||||
std::string responses[]
|
std::string responses[]
|
||||||
{
|
{
|
||||||
"{ }\x1e",
|
"{ }\x1e",
|
||||||
"{ \"type\": 3, \"invocationId\": \"0\", \"error\": \"Ooops\" }\x1e"
|
"{ \"type\": 3, \"invocationId\": \"0\" }\x1e"
|
||||||
"{}"
|
"{}"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -582,7 +597,7 @@ TEST(invoke_void, invoke_logs_if_callback_for_given_id_not_found)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Flaky until hub_connection.start waits for handshake response
|
// TODO Flaky until hub_connection.start waits for handshake response
|
||||||
TEST(invoke_void, DISABLED_invoke_propagates_errors_from_server_as_exceptions)
|
TEST(invoke, DISABLED_invoke_propagates_errors_from_server_as_exceptions)
|
||||||
{
|
{
|
||||||
auto callback_registered_event = std::make_shared<event>();
|
auto callback_registered_event = std::make_shared<event>();
|
||||||
|
|
||||||
|
|
@ -613,7 +628,7 @@ TEST(invoke_void, DISABLED_invoke_propagates_errors_from_server_as_exceptions)
|
||||||
hub_connection->start()
|
hub_connection->start()
|
||||||
.then([hub_connection, callback_registered_event]()
|
.then([hub_connection, callback_registered_event]()
|
||||||
{
|
{
|
||||||
auto t = hub_connection->invoke_void(_XPLATSTR("method"), json::value::array());
|
auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
callback_registered_event->set();
|
callback_registered_event->set();
|
||||||
return t;
|
return t;
|
||||||
}).get();
|
}).get();
|
||||||
|
|
@ -626,51 +641,6 @@ TEST(invoke_void, DISABLED_invoke_propagates_errors_from_server_as_exceptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Flaky until hub_connection.start waits for handshake response
|
|
||||||
TEST(invoke_void, DISABLED_invoke_propagates_hub_errors_from_server_as_hub_exceptions)
|
|
||||||
{
|
|
||||||
auto callback_registered_event = std::make_shared<event>();
|
|
||||||
|
|
||||||
int call_number = -1;
|
|
||||||
auto websocket_client = create_test_websocket_client(
|
|
||||||
/* receive function */ [call_number, callback_registered_event]()
|
|
||||||
mutable {
|
|
||||||
std::string responses[]
|
|
||||||
{
|
|
||||||
"{ }\x1e",
|
|
||||||
"{ \"type\": 3, \"invocationId\": \"0\", \"error\": \"Ooops\" }\x1e"
|
|
||||||
"{}"
|
|
||||||
};
|
|
||||||
|
|
||||||
call_number = std::min(call_number + 1, 2);
|
|
||||||
|
|
||||||
if (call_number > 0)
|
|
||||||
{
|
|
||||||
callback_registered_event->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pplx::task_from_result(responses[call_number]);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto hub_connection = create_hub_connection(websocket_client);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
hub_connection->start()
|
|
||||||
.then([hub_connection, callback_registered_event]()
|
|
||||||
{
|
|
||||||
auto t = hub_connection->invoke_void(_XPLATSTR("method"), json::value::array());
|
|
||||||
callback_registered_event->set();
|
|
||||||
return t;
|
|
||||||
}).get();
|
|
||||||
|
|
||||||
ASSERT_TRUE(false); // exception expected but not thrown
|
|
||||||
}
|
|
||||||
catch (const hub_exception& e)
|
|
||||||
{
|
|
||||||
ASSERT_STREQ("\"Ooops\"", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Flaky until hub_connection.start waits for handshake response
|
// TODO Flaky until hub_connection.start waits for handshake response
|
||||||
TEST(invoke_void, DISABLED_invoke_creates_runtime_error)
|
TEST(invoke_void, DISABLED_invoke_creates_runtime_error)
|
||||||
{
|
{
|
||||||
|
|
@ -702,7 +672,7 @@ TEST(invoke_void, DISABLED_invoke_creates_runtime_error)
|
||||||
hub_connection->start()
|
hub_connection->start()
|
||||||
.then([hub_connection, callback_registered_event]()
|
.then([hub_connection, callback_registered_event]()
|
||||||
{
|
{
|
||||||
auto t = hub_connection->invoke_void(_XPLATSTR("method"), json::value::array());
|
auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
|
||||||
callback_registered_event->set();
|
callback_registered_event->set();
|
||||||
return t;
|
return t;
|
||||||
}).get();
|
}).get();
|
||||||
|
|
@ -783,13 +753,13 @@ TEST(on, cannot_register_handler_if_connection_not_in_disconnected_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke_json, invoke_throws_when_the_underlying_connection_is_not_valid)
|
TEST(invoke, invoke_throws_when_the_underlying_connection_is_not_valid)
|
||||||
{
|
{
|
||||||
auto hub_connection = create_hub_connection();
|
auto hub_connection = create_hub_connection();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hub_connection->invoke_json(_XPLATSTR("method"), json::value::array()).get();
|
hub_connection->invoke(_XPLATSTR("method"), json::value::array()).get();
|
||||||
ASSERT_TRUE(true); // exception expected but not thrown
|
ASSERT_TRUE(true); // exception expected but not thrown
|
||||||
}
|
}
|
||||||
catch (const signalr_exception& e)
|
catch (const signalr_exception& e)
|
||||||
|
|
@ -798,13 +768,13 @@ TEST(invoke_json, invoke_throws_when_the_underlying_connection_is_not_valid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(invoke_void, send_throws_when_the_underlying_connection_is_not_valid)
|
TEST(invoke, send_throws_when_the_underlying_connection_is_not_valid)
|
||||||
{
|
{
|
||||||
auto hub_connection = create_hub_connection();
|
auto hub_connection = create_hub_connection();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hub_connection->invoke_void(_XPLATSTR("method"), json::value::array()).get();
|
hub_connection->invoke(_XPLATSTR("method"), json::value::array()).get();
|
||||||
ASSERT_TRUE(true); // exception expected but not thrown
|
ASSERT_TRUE(true); // exception expected but not thrown
|
||||||
}
|
}
|
||||||
catch (const signalr_exception& e)
|
catch (const signalr_exception& e)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue