aspnetcore/clients/cpp/src/signalrclient/connection_impl.h

106 lines
5.1 KiB
C++

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#pragma once
#include <atomic>
#include <mutex>
#include "cpprest/http_client.h"
#include "signalrclient/trace_level.h"
#include "signalrclient/connection_state.h"
#include "signalrclient/signalr_client_config.h"
#include "web_request_factory.h"
#include "transport_factory.h"
#include "logger.h"
#include "negotiation_response.h"
#include "event.h"
namespace signalr
{
// Note:
// Factory methods and private constructors prevent from using this class incorrectly. Because this class
// derives from `std::enable_shared_from_this` the instance has to be owned by a `std::shared_ptr` whenever
// a member method calls `std::shared_from_this()` otherwise the behavior is undefined. Therefore constructors
// are private to disallow creating instances directly and factory methods return `std::shared_ptr<connection_impl>`.
class connection_impl : public std::enable_shared_from_this<connection_impl>
{
public:
static std::shared_ptr<connection_impl> create(const utility::string_t& url, const utility::string_t& query_string,
trace_level trace_level, const std::shared_ptr<log_writer>& log_writer);
static std::shared_ptr<connection_impl> create(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);
connection_impl(const connection_impl&) = delete;
connection_impl& operator=(const connection_impl&) = delete;
~connection_impl();
pplx::task<void> start();
pplx::task<void> send(const utility::string_t &data);
pplx::task<void> stop();
connection_state get_connection_state() const;
utility::string_t get_connection_id() const;
void set_message_received_string(const std::function<void(const utility::string_t&)>& message_received);
void set_message_received_json(const std::function<void(const web::json::value&)>& message_received);
void set_reconnecting(const std::function<void()>& reconnecting);
void set_reconnected(const std::function<void()>& reconnected);
void set_disconnected(const std::function<void()>& disconnected);
void set_client_config(const signalr_client_config& config);
void set_reconnect_delay(const int reconnect_delay /*milliseconds*/);
void set_connection_data(const utility::string_t& connection_data);
private:
web::uri m_base_url;
utility::string_t m_query_string;
std::atomic<connection_state> m_connection_state;
logger m_logger;
std::shared_ptr<transport> m_transport;
std::unique_ptr<web_request_factory> m_web_request_factory;
std::unique_ptr<transport_factory> m_transport_factory;
std::function<void(const web::json::value&)> m_message_received;
std::function<void()> m_reconnecting;
std::function<void()> m_reconnected;
std::function<void()> m_disconnected;
signalr_client_config m_signalr_client_config;
pplx::cancellation_token_source m_disconnect_cts;
std::mutex m_stop_lock;
event m_start_completed_event;
utility::string_t m_connection_id;
utility::string_t m_connection_data;
int m_reconnect_window; // in milliseconds
int m_reconnect_delay; // in milliseconds
utility::string_t m_message_id;
utility::string_t m_groups_token;
bool m_handshakeReceived;
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);
pplx::task<std::shared_ptr<transport>> start_transport(negotiation_response negotiation_response);
pplx::task<void> send_connect_request(const std::shared_ptr<transport>& transport,
const pplx::task_completion_event<void>& connect_request_tce);
void process_response(const utility::string_t& response, const pplx::task_completion_event<void>& connect_request_tce);
pplx::task<void> shutdown();
void reconnect();
pplx::task<bool> try_reconnect(const web::uri& reconnect_url, const utility::datetime::interval_type reconnect_start_time,
int reconnect_window, int reconnect_delay, pplx::cancellation_token_source disconnect_cts);
bool change_state(connection_state old_state, connection_state new_state);
connection_state change_state(connection_state new_state);
void handle_connection_state_change(connection_state old_state, connection_state new_state);
void invoke_message_received(const web::json::value& message);
static utility::string_t translate_connection_state(connection_state state);
void ensure_disconnected(const utility::string_t& error_message);
};
}