diff --git a/src/interface/x.h b/src/interface/x.h index 103642c..0056cd3 100644 --- a/src/interface/x.h +++ b/src/interface/x.h @@ -29,7 +29,8 @@ enum SignalStatus { SignalConnected, SignalFailed, SignalClosed, - SignalReconnecting + SignalReconnecting, + SignalServerClosed }; enum TraversalMode { P2P = 0, Relay, UnknownMode }; diff --git a/src/pc/peer_connection.cpp b/src/pc/peer_connection.cpp index 748fe85..843b54b 100644 --- a/src/pc/peer_connection.cpp +++ b/src/pc/peer_connection.cpp @@ -131,6 +131,10 @@ int PeerConnection::Init(PeerConnectionParams params, ws_status_ = WsStatus::WsReconnecting; signal_status_ = SignalStatus::SignalReconnecting; on_signal_status_(SignalStatus::SignalReconnecting, user_data_); + } else if (WsStatus::WsServerClosed == ws_status) { + ws_status_ = WsStatus::WsServerClosed; + signal_status_ = SignalStatus::SignalServerClosed; + on_signal_status_(SignalStatus::SignalServerClosed, user_data_); } }; diff --git a/src/ws/ws_core.cpp b/src/ws/ws_core.cpp index 46b5282..b4dd99e 100644 --- a/src/ws/ws_core.cpp +++ b/src/ws/ws_core.cpp @@ -23,6 +23,7 @@ WsCore::~WsCore() { cond_var_.notify_one(); if (ping_thread_.joinable()) { ping_thread_.join(); + heartbeat_started_ = false; } m_endpoint_.stop_perpetual(); @@ -109,13 +110,17 @@ void WsCore::Ping(websocketpp::connection_hdl hdl) { [this] { return !running_; }); } - auto con = m_endpoint_.get_con_from_hdl(hdl); - if (con && con->get_state() == websocketpp::session::state::open) { - websocketpp::lib::error_code ec; - m_endpoint_.ping(hdl, "", ec); - if (ec) { - LOG_ERROR("Ping error: {}", ec.message()); - break; + if (hdl.expired()) { + LOG_WARN("Websocket connection expired, reconnecting..."); + } else { + auto con = m_endpoint_.get_con_from_hdl(hdl); + if (con && con->get_state() == websocketpp::session::state::open) { + websocketpp::lib::error_code ec; + m_endpoint_.ping(hdl, "", ec); + if (ec) { + LOG_ERROR("Ping error: {}", ec.message()); + break; + } } } @@ -129,7 +134,19 @@ void WsCore::OnOpen(client *c, websocketpp::connection_hdl hdl) { ws_status_ = WsStatus::WsOpened; OnWsStatus(WsStatus::WsOpened); - ping_thread_ = std::thread(&WsCore::Ping, this, hdl); + if (!heartbeat_started_) { + heartbeat_started_ = true; + running_ = true; + ping_thread_ = std::thread(&WsCore::Ping, this, hdl); + } else { + running_ = false; + cond_var_.notify_one(); + if (ping_thread_.joinable()) { + ping_thread_.join(); + running_ = true; + ping_thread_ = std::thread(&WsCore::Ping, this, hdl); + } + } } void WsCore::OnFail(client *c, websocketpp::connection_hdl hdl) { @@ -140,9 +157,11 @@ void WsCore::OnFail(client *c, websocketpp::connection_hdl hdl) { } void WsCore::OnClose(client *c, websocketpp::connection_hdl hdl) { - ws_status_ = WsStatus::WsClosed; + ws_status_ = WsStatus::WsServerClosed; if (running_) { - OnWsStatus(WsStatus::WsClosed); + OnWsStatus(WsStatus::WsServerClosed); + // try to reconnect + Connect(uri_); } } diff --git a/src/ws/ws_core.h b/src/ws/ws_core.h index c29fdb4..1eaadd2 100644 --- a/src/ws/ws_core.h +++ b/src/ws/ws_core.h @@ -15,7 +15,14 @@ typedef websocketpp::client client; -enum WsStatus { WsOpening = 0, WsOpened, WsFailed, WsClosed, WsReconnecting }; +enum WsStatus { + WsOpening = 0, + WsOpened, + WsFailed, + WsClosed, + WsReconnecting, + WsServerClosed +}; class WsCore { public: @@ -59,10 +66,11 @@ class WsCore { websocketpp::connection_hdl connection_handle_; std::thread m_thread_; std::thread ping_thread_; - bool running_ = true; + std::atomic running_{false}; std::mutex mtx_; unsigned int interval_ = 3; std::condition_variable cond_var_; + bool heartbeat_started_ = false; WsStatus ws_status_ = WsStatus::WsClosed; int timeout_count_ = 0;