Skip to content

Commit

Permalink
WS 切断時の処理をいい感じにする
Browse files Browse the repository at this point in the history
  • Loading branch information
melpon committed Dec 9, 2024
1 parent d53fdf4 commit 4b71935
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 64 deletions.
107 changes: 44 additions & 63 deletions src/sora_signaling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,35 +611,8 @@ void SoraSignaling::DoInternalDisconnect(
}
};

// Close 処理中に、意図しない場所で WS Close が呼ばれた場合の対策。
// 例えば dc_->Close()→送信完了して on_ws_close_ に値を設定して切断を待つ、
// となるまでの間に WS Close された場合、on_ws_close_ に値が設定されていなくて
// 永遠に終了できなくなってしまう。
if (ws_connected_) {
on_ws_close_ = [self = shared_from_this(),
on_close](boost::system::error_code ec) {
boost::system::error_code tec;
self->closing_timeout_timer_.cancel(tec);
auto ws_reason = self->ws_->reason();
self->SendOnWsClose(ws_reason);
std::string message =
"Unintended disconnect WebSocket during Disconnect process: ec=" +
ec.message() + " wscode=" + std::to_string(ws_reason.code) +
" wsreason=" + ws_reason.reason.c_str();
on_close(false, SoraSignalingErrorCode::CLOSE_FAILED, message);
};
}

if (using_datachannel_ && ws_connected_) {
closing_timeout_timer_.expires_from_now(
boost::posix_time::seconds(config_.websocket_close_timeout));
closing_timeout_timer_.async_wait(
[self = shared_from_this()](boost::system::error_code ec) {
if (ec) {
return;
}
self->ws_->Cancel();
});
// DC の切断タイムアウトがあるので、closing_timeout_timer_ は使わない
std::shared_ptr<bool> ws_close_called = std::make_shared<bool>(false);
std::shared_ptr<bool> dc_close_called = std::make_shared<bool>(false);
on_ws_close_ = [self = shared_from_this(), on_close, ws_close_called,
Expand All @@ -649,8 +622,6 @@ void SoraSignaling::DoInternalDisconnect(
return;
}
*ws_close_called = true;
boost::system::error_code tec;
self->closing_timeout_timer_.cancel(tec);
auto reason = self->ws_->reason();
self->SendOnWsClose(reason);
if (ec != boost::beast::websocket::error::closed) {
Expand All @@ -660,7 +631,7 @@ void SoraSignaling::DoInternalDisconnect(
on_close(false, SoraSignalingErrorCode::CLOSE_FAILED, message);
} else {
on_close(true, SoraSignalingErrorCode::CLOSE_SUCCEEDED,
"Succeeded to close Websocket");
"Succeeded to close Websocket (DC signaling is enabled)");
}
};

Expand All @@ -683,7 +654,7 @@ void SoraSignaling::DoInternalDisconnect(
}
*dc_close_called = true;

// WebSocket の Close 処理が来てない状態なので何か問題が起きてる
// DC 切断のタイムアウトかつ WebSocket の Close 処理が来てない状態なので何か問題が起きてる
self->ws_->Cancel();

// reason は自分で作る
Expand Down Expand Up @@ -721,46 +692,56 @@ void SoraSignaling::DoInternalDisconnect(
SendOnSignalingMessage(SoraSignalingType::DATACHANNEL,
SoraSignalingDirection::SENT, std::move(text));
} else if (!using_datachannel_ && ws_connected_) {
closing_timeout_timer_.expires_from_now(
boost::posix_time::seconds(config_.websocket_close_timeout));
closing_timeout_timer_.async_wait(
[self = shared_from_this()](boost::system::error_code ec) {
if (ec) {
return;
}
self->ws_->Cancel();
});
on_ws_close_ = [self = shared_from_this(),
on_close](boost::system::error_code ec) {
boost::system::error_code tec;
self->closing_timeout_timer_.cancel(tec);
auto reason = self->ws_->reason();
if (ec == boost::asio::error::operation_aborted) {
// タイムアウトによる切断なので 4999 をコールバックする
auto timeout_reason = boost::beast::websocket::close_reason(
(boost::beast::websocket::close_code)4999,
"DISCONNECT-WAIT-TIMEOUT-ERROR");
self->SendOnWsClose(timeout_reason);
} else {
self->SendOnWsClose(reason);
}
bool ec_error = ec != boost::beast::websocket::error::closed;
if (ec_error) {
on_close(false, SoraSignalingErrorCode::CLOSE_FAILED,
"Failed to close WebSocket: ec=" + ec.message() +
" wscode=" + std::to_string(reason.code) +
" wsreason=" + reason.reason.c_str());
return;
}
on_close(true, SoraSignalingErrorCode::CLOSE_SUCCEEDED,
"Succeeded to close WebSocket (DC signaling is not enabled)");
};
boost::json::value disconnect = {{"type", "disconnect"},
{"reason", "NO-ERROR"}};
WsWriteSignaling(
boost::json::serialize(disconnect),
[self = shared_from_this(), on_close](boost::system::error_code ec,
std::size_t) {
if (ec) {
on_close(
false, SoraSignalingErrorCode::CLOSE_FAILED,
"Failed to write disconnect message to close WebSocket: ec=" +
ec.message());
// 書き込みが成功した段階で Sora サーバーから切断されるので、
// 成功時の処理は不要
if (!ec) {
return;
}

self->closing_timeout_timer_.expires_from_now(
boost::posix_time::seconds(
self->config_.websocket_close_timeout));
self->closing_timeout_timer_.async_wait(
[self](boost::system::error_code ec) {
if (ec) {
return;
}
self->ws_->Cancel();
});
self->on_ws_close_ = [self, on_close](boost::system::error_code ec) {
boost::system::error_code tec;
self->closing_timeout_timer_.cancel(tec);
auto reason = self->ws_->reason();
self->SendOnWsClose(reason);
bool ec_error = ec != boost::beast::websocket::error::closed;
if (ec_error) {
on_close(false, SoraSignalingErrorCode::CLOSE_FAILED,
"Failed to close WebSocket: ec=" + ec.message() +
" wscode=" + std::to_string(reason.code) +
" wsreason=" + reason.reason.c_str());
return;
}
on_close(true, SoraSignalingErrorCode::CLOSE_SUCCEEDED,
"Succeeded to close WebSocket");
};
on_close(
false, SoraSignalingErrorCode::CLOSE_FAILED,
"Failed to write disconnect message to close WebSocket: ec=" +
ec.message());
});
} else {
on_close(false, SoraSignalingErrorCode::INTERNAL_ERROR,
Expand Down
1 change: 1 addition & 0 deletions test/.testparam.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"simulcast": false,
"use_hardware_encoder": true,
"openh264": null,
"data_channel_signaling": null,
"ignore_disconnect_websocket": null,
"client_id": null,

Expand Down
5 changes: 4 additions & 1 deletion test/hello.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void HelloSora::Run() {
config.video_bit_rate = config_.video_bit_rate;
config.multistream = true;
config.simulcast = config_.simulcast;
config.data_channel_signaling = true;
config.data_channel_signaling = config_.data_channel_signaling;
if (config_.ignore_disconnect_websocket) {
config.ignore_disconnect_websocket = *config_.ignore_disconnect_websocket;
}
Expand Down Expand Up @@ -192,6 +192,9 @@ int main(int argc, char* argv[]) {
if (get(v, "client_id", x)) {
config.client_id = x.as_string();
}
if (get(v, "data_channel_signaling", x)) {
config.data_channel_signaling = x.as_bool();
}
if (get(v, "ignore_disconnect_websocket", x)) {
config.ignore_disconnect_websocket = x.as_bool();
}
Expand Down
1 change: 1 addition & 0 deletions test/hello.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct HelloSoraConfig {
int video_bit_rate = 0;
std::string video_codec_type = "H264";
bool simulcast = false;
std::optional<bool> data_channel_signaling;
std::optional<bool> ignore_disconnect_websocket;
std::string client_id;
std::vector<sora::SoraSignalingConfig::DataChannel> data_channels;
Expand Down

0 comments on commit 4b71935

Please sign in to comment.