Compare commits

...
6 Commits
18 changed files with 72 additions and 121 deletions
@@ -103,7 +103,12 @@ int ConfigCenter::Load() {
ini_.SetLongValue(section_, "turn_mode", static_cast<long>(turn_mode_));
persist_config_migration = true;
}
enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_);
// Migrate the former user switch. Keep true in the file for older builds,
// while the current application always requests encrypted native media.
if (!ini_.GetBoolValue(section_, "enable_srtp", false)) {
ini_.SetBoolValue(section_, "enable_srtp", true);
persist_config_migration = true;
}
enable_self_hosted_ =
ini_.GetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
@@ -165,7 +170,7 @@ int ConfigCenter::Save() {
ini_.SetLongValue(section_, "turn_mode", static_cast<long>(turn_mode_));
ini_.SetBoolValue(section_, "enable_turn",
turn_mode_ != TURN_MODE::DISABLED);
ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_);
ini_.SetBoolValue(section_, "enable_srtp", true);
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
// only save when self hosted
@@ -301,16 +306,6 @@ int ConfigCenter::SetTurn(bool enable_turn) {
return SetTurnMode(turn_mode_);
}
int ConfigCenter::SetSrtp(bool enable_srtp) {
enable_srtp_ = enable_srtp;
ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_);
SI_Error rc = ini_.SaveFile(config_path_.c_str());
if (rc < 0) {
return -1;
}
return 0;
}
int ConfigCenter::SetServerHost(const std::string& signal_server_host) {
signal_server_host_ = signal_server_host;
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
@@ -472,7 +467,7 @@ bool ConfigCenter::IsEnableTurn() const {
return turn_mode_ != TURN_MODE::DISABLED;
}
bool ConfigCenter::IsEnableSrtp() const { return enable_srtp_; }
bool ConfigCenter::IsEnableSrtp() const { return true; }
std::string ConfigCenter::GetSignalServerHost() const {
return signal_server_host_;
@@ -47,7 +47,6 @@ class ConfigCenter {
int SetHardwareVideoCodec(bool hardware_video_codec);
int SetTurnMode(TURN_MODE turn_mode);
int SetTurn(bool enable_turn);
int SetSrtp(bool enable_srtp);
int SetServerHost(const std::string& signal_server_host);
int SetServerPort(int signal_server_port);
int SetSelfHosted(bool enable_self_hosted);
@@ -99,7 +98,6 @@ class ConfigCenter {
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::H264;
bool hardware_video_codec_ = false;
TURN_MODE turn_mode_ = TURN_MODE::AUTO_UDP_TCP;
bool enable_srtp_ = false;
std::string signal_server_host_ = "";
std::string signal_server_host_default_ = "api.crossdesk.cn";
int signal_server_port_ = 0;
@@ -1230,7 +1230,6 @@ void GuiApplication::ResetSettingsUi() {
ui_->main->set_hardware_codec_enabled(hardware_codec_available &&
enable_hardware_video_codec_);
ui_->main->set_turn_enabled(enable_turn_);
ui_->main->set_srtp_enabled(enable_srtp_);
ui_->main->set_self_hosted_enabled(enable_self_hosted_);
ui_->main->set_autostart_enabled(enable_autostart_);
ui_->main->set_daemon_enabled(enable_daemon_);
@@ -2419,7 +2418,6 @@ void GuiApplication::SyncStreamWindow() {
return;
}
(*ui_->stream)->set_window_maximized((*ui_->stream)->window().is_maximized());
(*ui_->stream)->set_srtp_enabled(enable_srtp_);
#if defined(__APPLE__)
if (ui_->stream_live_resize_configuration_attempts > 0) {
if (ConfigureStreamWindowLiveResize(
@@ -2987,7 +2985,6 @@ void GuiApplication::SaveSettingsFromUi() {
enable_hardware_video_codec_ = ConfigCenter::IsHardwareVideoCodecAvailable() &&
main->get_hardware_codec_enabled();
enable_turn_ = main->get_turn_enabled();
enable_srtp_ = main->get_srtp_enabled();
enable_self_hosted_ = main->get_self_hosted_enabled();
enable_autostart_ = main->get_autostart_enabled();
enable_daemon_ = main->get_daemon_enabled();
@@ -3010,7 +3007,6 @@ void GuiApplication::SaveSettingsFromUi() {
video_encode_format_button_value_));
config_center_->SetHardwareVideoCodec(enable_hardware_video_codec_);
config_center_->SetTurn(enable_turn_);
config_center_->SetSrtp(enable_srtp_);
config_center_->SetSelfHosted(enable_self_hosted_);
config_center_->SetAutostart(enable_autostart_);
config_center_->SetDaemon(enable_daemon_);
@@ -3056,7 +3052,6 @@ void GuiApplication::SaveSettingsFromUi() {
video_encode_format_button_value_last_ = video_encode_format_button_value_;
enable_hardware_video_codec_last_ = enable_hardware_video_codec_;
enable_turn_last_ = enable_turn_;
enable_srtp_last_ = enable_srtp_;
enable_self_hosted_last_ = enable_self_hosted_;
enable_autostart_last_ = enable_autostart_;
enable_daemon_last_ = enable_daemon_;
@@ -53,8 +53,6 @@
#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN 218 * dpi_scale_
#define ENABLE_TURN_CHECKBOX_PADDING_CN 171 * dpi_scale_
#define ENABLE_TURN_CHECKBOX_PADDING_EN 218 * dpi_scale_
#define ENABLE_SRTP_CHECKBOX_PADDING_CN 171 * dpi_scale_
#define ENABLE_SRTP_CHECKBOX_PADDING_EN 218 * dpi_scale_
#define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN 171 * dpi_scale_
#define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN 218 * dpi_scale_
#define ENABLE_AUTOSTART_PADDING_CN 171 * dpi_scale_
@@ -57,8 +57,6 @@
#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN 218
#define ENABLE_TURN_CHECKBOX_PADDING_CN 171
#define ENABLE_TURN_CHECKBOX_PADDING_EN 218
#define ENABLE_SRTP_CHECKBOX_PADDING_CN 171
#define ENABLE_SRTP_CHECKBOX_PADDING_EN 218
#define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN 171
#define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN 218
#define ENABLE_AUTOSTART_PADDING_CN 171
@@ -149,7 +149,6 @@ struct TranslationRow {
"Enable Hardware Video Codec:", u8"Использовать аппаратный кодек:") \
X(enable_turn, u8"启用中继服务:", \
"Enable TURN Service:", u8"Включить TURN-сервис:") \
X(enable_srtp, u8"启用SRTP:", "Enable SRTP:", u8"Включить SRTP:") \
X(self_hosted_server_config, u8"自托管配置", "Self-Hosted Config", \
u8"Конфигурация self-hosted") \
X(self_hosted_server_settings, u8"自托管设置", "Self-Hosted Settings", \
@@ -308,7 +308,6 @@ int SettingsManager::Load() {
owner_.enable_hardware_video_codec_ =
owner_.config_center_->IsHardwareVideoCodec();
owner_.enable_turn_ = owner_.config_center_->IsEnableTurn();
owner_.enable_srtp_ = owner_.config_center_->IsEnableSrtp();
owner_.enable_self_hosted_ = owner_.config_center_->IsSelfHosted();
owner_.enable_autostart_ = owner_.config_center_->IsEnableAutostart();
owner_.enable_daemon_ = owner_.config_center_->IsEnableDaemon();
@@ -335,7 +334,6 @@ int SettingsManager::Load() {
owner_.enable_hardware_video_codec_last_ =
owner_.enable_hardware_video_codec_;
owner_.enable_turn_last_ = owner_.enable_turn_;
owner_.enable_srtp_last_ = owner_.enable_srtp_;
owner_.enable_self_hosted_last_ = owner_.enable_self_hosted_;
owner_.enable_autostart_last_ = owner_.enable_autostart_;
@@ -136,7 +136,6 @@ struct UserSettingsState {
int video_encode_format_button_value_ = 0;
bool enable_hardware_video_codec_ = true;
bool enable_turn_ = true;
bool enable_srtp_ = false;
char signal_server_ip_[256] = "api.crossdesk.cn";
char signal_server_port_[6] = "9099";
bool enable_self_hosted_ = false;
@@ -147,7 +146,6 @@ struct UserSettingsState {
int video_encode_format_button_value_last_ = 0;
bool enable_hardware_video_codec_last_ = false;
bool enable_turn_last_ = true;
bool enable_srtp_last_ = false;
bool enable_self_hosted_last_ = false;
bool enable_autostart_ = false;
bool enable_autostart_last_ = false;
@@ -48,7 +48,6 @@ export global UiStrings {
in-out property <string> codec: "Video codec";
in-out property <string> hardware-codec: "Hardware video codec";
in-out property <string> turn-relay: "TURN relay";
in-out property <string> srtp: "SRTP encryption";
in-out property <string> self-hosted: "Self-hosted server";
in-out property <string> autostart: "Start with system";
in-out property <string> daemon: "Run in background";
@@ -247,7 +246,6 @@ export component MainWindow inherits Window {
in-out property <int> codec-index: 0;
in-out property <bool> hardware-codec-enabled: true;
in-out property <bool> turn-enabled: true;
in-out property <bool> srtp-enabled: false;
in-out property <bool> self-hosted-enabled: false;
in-out property <bool> autostart-enabled: false;
in-out property <bool> daemon-enabled: false;
@@ -1488,11 +1486,6 @@ export component MainWindow inherits Window {
Text { x: 8px; y: 3px; width: root.compact-language ? 145px : 212px; height: 24px; text: UiStrings.turn-relay; font-size: ImGuiFontStyle.body; overflow: elide; vertical-alignment: center; }
ImGuiCheckBox { x: root.compact-language ? 157px : 224px; y: 3px; checked <=> root.turn-enabled; enabled: !root.settings-session-active; }
}
Rectangle {
height: 30px;
Text { x: 8px; y: 3px; width: root.compact-language ? 145px : 212px; height: 24px; text: UiStrings.srtp; font-size: ImGuiFontStyle.body; overflow: elide; vertical-alignment: center; }
ImGuiCheckBox { x: root.compact-language ? 157px : 224px; y: 3px; checked <=> root.srtp-enabled; enabled: !root.settings-session-active; }
}
Rectangle {
height: 30px;
Text { x: 8px; y: 3px; width: root.compact-language ? 145px : 212px; height: 24px; text: UiStrings.privacy-on-connect; color: root.privacy-setting-available ? #202124 : #8b8f95; font-size: ImGuiFontStyle.body; overflow: elide; vertical-alignment: center; }
+1 -14
View File
@@ -160,7 +160,6 @@ export component StreamWindow inherits Window {
in property <bool> remote-cursor-active: false;
in property <int> remote-cursor-shape: 0;
in property <bool> audio-enabled: true;
in property <bool> srtp-enabled: false;
in property <bool> fullscreen-enabled: false;
in property <bool> stats-visible: false;
in property <[NetworkStatsRow]> stats-rows;
@@ -506,20 +505,8 @@ export component StreamWindow inherits Window {
width: parent.width - 27px;
height: parent.height;
background: transparent;
if root.srtp-enabled: Text {
x: 0px;
width: 12px;
height: parent.height;
text: FontAwesomeIcons.shield-halved;
color: #30343b;
font-family: "Font Awesome 6 Free";
font-weight: 900;
font-size: ImGuiFontStyle.base;
horizontal-alignment: center;
vertical-alignment: center;
}
Text {
x: root.srtp-enabled ? 16px : 0px;
x: 0px;
width: parent.width - self.x;
height: parent.height;
text: tab.title;
@@ -69,7 +69,6 @@ inline int ApplyMainWindowStrings(
strings.set_hardware_codec(
Text(localization::enable_hardware_video_codec[language]));
strings.set_turn_relay(Text(localization::enable_turn[language]));
strings.set_srtp(Text(localization::enable_srtp[language]));
strings.set_self_hosted(
Text(localization::self_hosted_server_config[language]));
strings.set_autostart(Text(localization::enable_autostart[language]));
@@ -268,25 +268,6 @@ int GuiApplication::SettingWindow() {
ImGui::Separator();
{
settings_items_offset += settings_items_padding;
ImGui::SetCursorPosY(settings_items_offset);
ImGui::AlignTextToFramePadding();
ImGui::Text(
"%s",
localization::enable_srtp[localization_language_index_].c_str());
ImGui::SameLine();
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
ImGui::SetCursorPosX(title_bar_button_width_ * 4.275f);
} else {
ImGui::SetCursorPosX(title_bar_button_width_ * 5.955f);
}
ImGui::Checkbox("##enable_srtp", &enable_srtp_);
}
ImGui::Separator();
{
settings_items_offset += settings_items_padding;
ImGui::SetCursorPosY(settings_items_offset + 1);
@@ -569,14 +550,6 @@ int GuiApplication::SettingWindow() {
}
enable_turn_last_ = enable_turn_;
// SRTP
if (enable_srtp_) {
config_center_->SetSrtp(true);
} else {
config_center_->SetSrtp(false);
}
enable_srtp_last_ = enable_srtp_;
if (enable_self_hosted_) {
config_center_->SetSelfHosted(true);
} else {
@@ -136,10 +136,7 @@ int GuiApplication::StreamWindow() {
continue;
}
std::string tab_label =
enable_srtp_
? std::string(ICON_FA_SHIELD_HALVED) + " " + props->remote_id_
: props->remote_id_;
const std::string& tab_label = props->remote_id_;
if (ImGui::BeginTabItem(tab_label.c_str(), &props->tab_opened_)) {
props->tab_selected_ = true;
ImGui::SetWindowFontScale(0.6f);
@@ -308,4 +305,4 @@ int GuiApplication::StreamWindow() {
return 0;
}
} // namespace crossdesk
} // namespace crossdesk
@@ -99,8 +99,7 @@ typedef NS_ENUM(NSInteger, CrossDeskVideoAdaptationPolicy) {
@property(nonatomic, weak, nullable) id<CrossDeskRTCBridgeDelegate> delegate;
- (void)configureWithSignalHost:(NSString *)host
signalPort:(NSInteger)signalPort
enableSRTP:(BOOL)enableSRTP;
signalPort:(NSInteger)signalPort;
- (void)setHardwareAccelerationEnabled:(BOOL)enabled;
- (void)setVideoAdaptationPolicy:(CrossDeskVideoAdaptationPolicy)policy;
- (void)requestPresenceForRemoteIDs:(NSArray<NSString *> *)remoteIDs
@@ -75,7 +75,6 @@ struct RTCState {
CallbackContext controller_context;
std::string signal_host;
int signal_port = 0;
bool enable_srtp = false;
bool hardware_acceleration = true;
VideoDegradationPreference video_adaptation_policy =
VideoDegradationPreference::MaintainResolution;
@@ -86,6 +85,7 @@ struct RTCState {
std::string identity_base;
std::string controller_login;
std::string pending_remote_id;
uint64_t pending_controller_generation = 0;
std::string pending_password;
std::string transmission_id;
std::string log_path;
@@ -336,7 +336,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
params.native_video_output = true;
params.av1_encoding = false;
params.turn_mode = TurnMode::TurnAutoUdpTcp;
params.enable_srtp = state.enable_srtp;
params.enable_srtp = true;
params.video_content_type = VideoContentType::ScreenContent;
params.video_quality = VideoQuality::QualityHigh;
params.video_frame_rate = 60;
@@ -432,8 +432,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
}
- (void)configureWithSignalHost:(NSString *)host
signalPort:(NSInteger)signalPort
enableSRTP:(BOOL)enableSRTP {
signalPort:(NSInteger)signalPort {
NSString *trimmed = [host stringByTrimmingCharactersInSet:
NSCharacterSet.whitespaceAndNewlineCharacterSet];
const char *host_c_string = trimmed.UTF8String;
@@ -455,7 +454,6 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
dispatch_async(_rtcQueue, ^{
const bool unchanged = self->_state->signal_host == host_value &&
self->_state->signal_port == signalPort &&
self->_state->enable_srtp == enableSRTP &&
self->_state->identity_peer != nullptr;
if (unchanged) return;
@@ -463,7 +461,6 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
[self destroyIdentityPeer];
self->_state->signal_host = host_value;
self->_state->signal_port = static_cast<int>(signalPort);
self->_state->enable_srtp = enableSRTP;
self->_state->log_path = log_path;
self->_state->identity_ready = false;
self->_state->identity_recovery_attempted = false;
@@ -583,8 +580,14 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
password_c_string ? password_c_string : "";
if (identifier.empty()) return;
// Invalidate queued callbacks immediately, before asynchronous teardown. A
// canceled attempt for the same remote must not close a newly started one.
const uint64_t generation = _controllerGenerationCounter.fetch_add(1) + 1;
_activeControllerGeneration.store(0);
dispatch_async(_rtcQueue, ^{
if (generation != self->_controllerGenerationCounter.load()) return;
self->_state->pending_remote_id = identifier;
self->_state->pending_controller_generation = generation;
self->_state->pending_password = password_value;
[self destroyControllerPeer];
if (self->_state->identity_ready &&
@@ -595,6 +598,8 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
}
- (void)disconnect {
_controllerGenerationCounter.fetch_add(1);
_activeControllerGeneration.store(0);
dispatch_async(_rtcQueue, ^{
self->_state->pending_remote_id.clear();
self->_state->pending_password.clear();
@@ -868,7 +873,8 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
_state->identity_base.empty()) {
return;
}
const uint64_t generation = _controllerGenerationCounter.fetch_add(1) + 1;
const uint64_t generation = _state->pending_controller_generation;
if (generation == 0 || generation != _controllerGenerationCounter.load()) return;
_state->controller_context.generation = generation;
_activeControllerGeneration.store(generation);
_state->controller_login = "C-" + _state->identity_base;
@@ -1112,6 +1118,8 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
remoteID:(const std::string &)remoteID
generation:(uint64_t)generation {
if (![self isControllerGenerationCurrent:generation]) return;
if (state != CrossDeskConnectionStateFailed &&
![self isControllerGenerationActive:generation]) return;
const std::string remote_copy = remoteID;
if (state == CrossDeskConnectionStateConnected) {
dispatch_async(_rtcQueue, ^{
@@ -1149,7 +1157,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
}
DispatchMain(^{
if (![self isControllerGenerationCurrent:generation]) return;
if (state == CrossDeskConnectionStateConnected &&
if (state != CrossDeskConnectionStateFailed &&
![self isControllerGenerationActive:generation]) {
return;
}
@@ -1164,6 +1172,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
- (BOOL)isControllerGenerationActive:(uint64_t)generation {
return generation != 0 &&
_controllerGenerationCounter.load() == generation &&
_activeControllerGeneration.load() == generation;
}
+10 -5
View File
@@ -17,6 +17,14 @@ struct ContentView: View {
}
.animation(.easeInOut(duration: 0.2), value: session.sessionVisible)
.preferredColorScheme(session.sessionVisible ? .dark : .light)
.alert("连接提示", isPresented: Binding(
get: { session.connectionFailureMessage != nil },
set: { if !$0 { session.dismissConnectionFailure() } }
)) {
Button("确定", role: .cancel) { session.dismissConnectionFailure() }
} message: {
Text(session.connectionFailureMessage ?? "")
}
.onAppear {
if !session.sessionVisible {
AppOrientation.update(to: .portrait)
@@ -710,17 +718,14 @@ private struct ServerSettingsView: View {
.font(.caption)
.foregroundStyle(.tertiary)
}
Section("服务器") {
Section {
TextField("信令服务器", text: $session.signalHost)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
TextField("信令端口", text: $session.signalPort)
.keyboardType(.numberPad)
}
Section {
Toggle("启用 SRTP", isOn: $session.enableSRTP)
} header: {
Text("传输")
Text("服务器")
} footer: {
Text(session.localIdentity.isEmpty
? "正在获取本机 ID…"
@@ -358,7 +358,6 @@ private final class RemoteAudioPlayer {
final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDelegate {
@Published var signalHost = "api.crossdesk.cn"
@Published var signalPort = "9099"
@Published var enableSRTP = false
@Published var mouseControlMode = MouseControlMode.saved {
didSet { mouseControlMode.save() }
}
@@ -398,6 +397,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
@Published private(set) var recentConnections = RecentConnectionStore.load()
@Published private(set) var recentConnectionPresence: [String: Bool] = [:]
@Published private(set) var deviceOfflineAlertVisible = false
@Published private(set) var connectionFailureMessage: String?
let bridge = CrossDeskRTCBridge()
private let audioPlayer = RemoteAudioPlayer()
@@ -424,7 +424,6 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
private struct BridgeConfiguration: Equatable {
let host: String
let signalPort: Int
let enableSRTP: Bool
}
private var bridgeConfiguration: BridgeConfiguration?
@@ -457,8 +456,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
signalStatus = "服务器配置无效"
return false
}
let configuration = BridgeConfiguration(host: host, signalPort: signal,
enableSRTP: enableSRTP)
let configuration = BridgeConfiguration(host: host, signalPort: signal)
if bridgeConfiguration != configuration {
bridgeConfiguration = configuration
signalConnected = false
@@ -472,8 +470,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
bridge.setHardwareAccelerationEnabled(videoCodecMode == .hardware)
bridge.setVideoAdaptationPolicy(videoAdaptationPolicy.bridgeValue)
bridge.configure(withSignalHost: host,
signalPort: signal,
enableSRTP: enableSRTP)
signalPort: signal)
return true
}
@@ -484,6 +481,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
}
func connect() {
connectionFailureMessage = nil
let identifier = remoteID.trimmingCharacters(in: .whitespacesAndNewlines)
guard !identifier.isEmpty else {
connectionStatus = "请输入远程设备 ID"
@@ -576,7 +574,25 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
deviceOfflineAlertVisible = false
}
func dismissConnectionFailure() {
guard connectionFailureMessage != nil else { return }
connectionFailureMessage = nil
}
private func finishConnection(withError message: String) {
// Cleanup may emit Closed. Preserve the terminal reason independently
// of the progress view and invalidate those callbacks in the bridge.
resetConnection()
connectionStatus = message
connectionFailureMessage = message
}
func disconnect() {
resetConnection()
}
private func resetConnection() {
connectionFailureMessage = nil
cancelVideoRecovery()
let wasCheckingPresence = pendingPresenceRemoteID != nil
cancelPresenceProbe()
@@ -882,6 +898,10 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
func rtcBridge(_ bridge: CrossDeskRTCBridge,
didChange state: CrossDeskConnectionState,
remoteID: String) {
guard isConnecting || isConnected || sessionVisible,
remoteID.isEmpty || remoteID == activeRemoteID else {
return
}
isConnected = state.rawValue == 1
if !isConnected {
cancelVideoRecovery()
@@ -897,35 +917,25 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
bridge.setAudioEnabled(audioEnabled)
AppOrientation.update(to: .allButUpsideDown)
case 2: connectionStatus = "正在收集 ICE 候选"
case 3: connectionStatus = "网络连接已中断"
case 3: finishConnection(withError: "网络连接已中断,请重新连接。")
case 4:
connectionStatus = "P2P/TURN 建链失败"
sessionVisible = false
AppOrientation.update(to: .portrait)
finishConnection(withError: "P2P/TURN 建链失败,请检查网络后重试。")
case 5:
connectionStatus = "未连接"
sessionVisible = false
AppOrientation.update(to: .portrait)
finishConnection(withError: "远程连接已结束。")
case 6:
connectionStatus = "访问密码错误"
sessionVisible = false
AppOrientation.update(to: .portrait)
finishConnection(withError: "访问密码错误,请重新输入。")
case 7:
connectionStatus = "远程设备 ID 不存在"
if !remoteID.isEmpty {
recentConnectionPresence[remoteID] = false
presenceUpdatedAt.removeValue(forKey: remoteID)
}
sessionVisible = false
AppOrientation.update(to: .portrait)
finishConnection(withError: "远程设备 ID 不存在,请检查设备 ID。")
case 8:
connectionStatus = "远程设备当前不可用"
if !remoteID.isEmpty {
recentConnectionPresence[remoteID] = false
presenceUpdatedAt.removeValue(forKey: remoteID)
}
sessionVisible = false
AppOrientation.update(to: .portrait)
finishConnection(withError: "远程设备当前不可用,请稍后重试。")
default: connectionStatus = "未知连接状态"
}
}