mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-06-14 03:32:00 +08:00
fix: 优化 RustDesk 中继服务器推导策略;修复鼠键输入异常
This commit is contained in:
@@ -27,7 +27,7 @@ use super::bytes_codec::{read_frame, write_frame, write_frame_buffered};
|
||||
use super::config::RustDeskConfig;
|
||||
use super::crypto::{self, KeyPair, SigningKeyPair};
|
||||
use super::frame_adapters::{AudioFrameAdapter, VideoCodec, VideoFrameAdapter};
|
||||
use super::hid_adapter::{convert_key_event, convert_mouse_event, mouse_type};
|
||||
use super::hid_adapter::{convert_key_events, convert_mouse_event, mouse_type};
|
||||
use super::protocol::{
|
||||
decode_message, login_response, message, misc, Clipboard, ControlKey, DisplayInfo, Hash,
|
||||
HbbMessage, IdPk, KeyEvent, LoginRequest, LoginResponse, Misc, MouseEvent, OptionMessage,
|
||||
@@ -1331,18 +1331,21 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert RustDesk key event to One-KVM key event
|
||||
if let Some(kb_event) = convert_key_event(ke) {
|
||||
debug!(
|
||||
"Converted to HID: key=0x{:02X}, event_type={:?}, modifiers={:02X}",
|
||||
kb_event.key.to_hid_usage(),
|
||||
kb_event.event_type,
|
||||
kb_event.modifiers.to_hid_byte()
|
||||
);
|
||||
// Send to HID controller if available
|
||||
// Convert RustDesk key event to One-KVM key events
|
||||
let kb_events = convert_key_events(ke);
|
||||
if !kb_events.is_empty() {
|
||||
if let Some(ref hid) = self.hid {
|
||||
if let Err(e) = hid.send_keyboard(kb_event).await {
|
||||
warn!("Failed to send keyboard event: {}", e);
|
||||
for kb_event in kb_events {
|
||||
debug!(
|
||||
"Converted to HID: key=0x{:02X}, event_type={:?}, modifiers={:02X}",
|
||||
kb_event.key.to_hid_usage(),
|
||||
kb_event.event_type,
|
||||
kb_event.modifiers.to_hid_byte()
|
||||
);
|
||||
|
||||
if let Err(e) = hid.send_keyboard(kb_event).await {
|
||||
warn!("Failed to send keyboard event: {}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("HID controller not available, skipping key event");
|
||||
@@ -1381,12 +1384,7 @@ impl Connection {
|
||||
debug!("Mouse event: x={}, y={}, mask={}", me.x, me.y, me.mask);
|
||||
|
||||
// Convert RustDesk mouse event to One-KVM mouse events
|
||||
let mouse_events = convert_mouse_event(
|
||||
me,
|
||||
self.screen_width,
|
||||
self.screen_height,
|
||||
self.relative_mouse_active,
|
||||
);
|
||||
let mouse_events = convert_mouse_event(me, self.screen_width, self.screen_height);
|
||||
|
||||
// Send to HID controller if available
|
||||
if let Some(ref hid) = self.hid {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::protocol::hbb::message::key_event as ke_union;
|
||||
use super::protocol::{ControlKey, KeyEvent, MouseEvent};
|
||||
use super::protocol::{ControlKey, KeyEvent, KeyboardMode, MouseEvent};
|
||||
use crate::hid::{
|
||||
CanonicalKey, KeyEventType, KeyboardEvent, KeyboardModifiers, MouseButton,
|
||||
MouseEvent as OneKvmMouseEvent, MouseEventType,
|
||||
@@ -27,13 +27,11 @@ pub fn convert_mouse_event(
|
||||
event: &MouseEvent,
|
||||
screen_width: u32,
|
||||
screen_height: u32,
|
||||
relative_mode: bool,
|
||||
) -> Vec<OneKvmMouseEvent> {
|
||||
let mut events = Vec::new();
|
||||
|
||||
let event_type = event.mask & 0x07;
|
||||
let button_id = event.mask >> 3;
|
||||
let include_abs_move = !relative_mode;
|
||||
|
||||
match event_type {
|
||||
mouse_type::MOVE => {
|
||||
@@ -61,20 +59,6 @@ pub fn convert_mouse_event(
|
||||
});
|
||||
}
|
||||
mouse_type::DOWN => {
|
||||
if include_abs_move {
|
||||
let x = event.x.max(0) as u32;
|
||||
let y = event.y.max(0) as u32;
|
||||
let abs_x = ((x as u64 * 32767) / screen_width.max(1) as u64) as i32;
|
||||
let abs_y = ((y as u64 * 32767) / screen_height.max(1) as u64) as i32;
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::MoveAbs,
|
||||
x: abs_x,
|
||||
y: abs_y,
|
||||
button: None,
|
||||
scroll: 0,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(button) = button_id_to_button(button_id) {
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::Down,
|
||||
@@ -86,20 +70,6 @@ pub fn convert_mouse_event(
|
||||
}
|
||||
}
|
||||
mouse_type::UP => {
|
||||
if include_abs_move {
|
||||
let x = event.x.max(0) as u32;
|
||||
let y = event.y.max(0) as u32;
|
||||
let abs_x = ((x as u64 * 32767) / screen_width.max(1) as u64) as i32;
|
||||
let abs_y = ((y as u64 * 32767) / screen_height.max(1) as u64) as i32;
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::MoveAbs,
|
||||
x: abs_x,
|
||||
y: abs_y,
|
||||
button: None,
|
||||
scroll: 0,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(button) = button_id_to_button(button_id) {
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::Up,
|
||||
@@ -111,20 +81,6 @@ pub fn convert_mouse_event(
|
||||
}
|
||||
}
|
||||
mouse_type::WHEEL => {
|
||||
if include_abs_move {
|
||||
let x = event.x.max(0) as u32;
|
||||
let y = event.y.max(0) as u32;
|
||||
let abs_x = ((x as u64 * 32767) / screen_width.max(1) as u64) as i32;
|
||||
let abs_y = ((y as u64 * 32767) / screen_height.max(1) as u64) as i32;
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::MoveAbs,
|
||||
x: abs_x,
|
||||
y: abs_y,
|
||||
button: None,
|
||||
scroll: 0,
|
||||
});
|
||||
}
|
||||
|
||||
let scroll = if event.y > 0 { 1i8 } else { -1i8 };
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::Scroll,
|
||||
@@ -134,21 +90,7 @@ pub fn convert_mouse_event(
|
||||
scroll,
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
if include_abs_move {
|
||||
let x = event.x.max(0) as u32;
|
||||
let y = event.y.max(0) as u32;
|
||||
let abs_x = ((x as u64 * 32767) / screen_width.max(1) as u64) as i32;
|
||||
let abs_y = ((y as u64 * 32767) / screen_height.max(1) as u64) as i32;
|
||||
events.push(OneKvmMouseEvent {
|
||||
event_type: MouseEventType::MoveAbs,
|
||||
x: abs_x,
|
||||
y: abs_y,
|
||||
button: None,
|
||||
scroll: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
events
|
||||
@@ -163,42 +105,89 @@ fn button_id_to_button(button_id: i32) -> Option<MouseButton> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_key_event(event: &KeyEvent) -> Option<KeyboardEvent> {
|
||||
let event_type = if event.down || event.press {
|
||||
KeyEventType::Down
|
||||
} else {
|
||||
KeyEventType::Up
|
||||
};
|
||||
|
||||
let modifiers = if is_modifier_control_key(event) {
|
||||
pub fn convert_key_events(event: &KeyEvent) -> Vec<KeyboardEvent> {
|
||||
let base_modifiers = if is_modifier_control_key(event) {
|
||||
KeyboardModifiers::default()
|
||||
} else {
|
||||
parse_modifiers(event)
|
||||
};
|
||||
|
||||
if let Some(ke_union::Union::ControlKey(ck)) = &event.union {
|
||||
if let Some(key) = control_key_to_hid(ck.value()) {
|
||||
let key = CanonicalKey::from_hid_usage(key)?;
|
||||
return Some(KeyboardEvent {
|
||||
event_type,
|
||||
let Some(mapping) = key_event_to_hid(event, base_modifiers) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
if event.press {
|
||||
let up_modifiers = if mapping.added_shift {
|
||||
base_modifiers
|
||||
} else {
|
||||
mapping.modifiers
|
||||
};
|
||||
vec![
|
||||
KeyboardEvent {
|
||||
event_type: KeyEventType::Down,
|
||||
key: mapping.key,
|
||||
modifiers: mapping.modifiers,
|
||||
},
|
||||
KeyboardEvent {
|
||||
event_type: KeyEventType::Up,
|
||||
key: mapping.key,
|
||||
modifiers: up_modifiers,
|
||||
},
|
||||
]
|
||||
} else {
|
||||
let event_type = if event.down {
|
||||
KeyEventType::Down
|
||||
} else {
|
||||
KeyEventType::Up
|
||||
};
|
||||
vec![KeyboardEvent {
|
||||
event_type,
|
||||
key: mapping.key,
|
||||
modifiers: mapping.modifiers,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_key_event(event: &KeyEvent) -> Option<KeyboardEvent> {
|
||||
convert_key_events(event).into_iter().next()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct KeyMapping {
|
||||
key: CanonicalKey,
|
||||
modifiers: KeyboardModifiers,
|
||||
added_shift: bool,
|
||||
}
|
||||
|
||||
fn key_event_to_hid(event: &KeyEvent, modifiers: KeyboardModifiers) -> Option<KeyMapping> {
|
||||
match &event.union {
|
||||
Some(ke_union::Union::ControlKey(ck)) => {
|
||||
let key = CanonicalKey::from_hid_usage(control_key_to_hid(ck.value())?)?;
|
||||
Some(KeyMapping {
|
||||
key,
|
||||
modifiers,
|
||||
});
|
||||
added_shift: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ke_union::Union::Chr(chr)) = &event.union {
|
||||
if let Some(key) = keycode_to_hid(*chr) {
|
||||
let key = CanonicalKey::from_hid_usage(key)?;
|
||||
return Some(KeyboardEvent {
|
||||
event_type,
|
||||
Some(ke_union::Union::Chr(chr)) => {
|
||||
if event.mode.value() != KeyboardMode::Map.value() {
|
||||
if let Some(mapping) = shifted_printable_char_to_hid(*chr, modifiers) {
|
||||
return Some(mapping);
|
||||
}
|
||||
}
|
||||
let key = CanonicalKey::from_hid_usage(keycode_to_hid(*chr)?)?;
|
||||
Some(KeyMapping {
|
||||
key,
|
||||
modifiers,
|
||||
});
|
||||
added_shift: false,
|
||||
})
|
||||
}
|
||||
Some(ke_union::Union::Unicode(unicode)) => {
|
||||
let mapping = printable_char_to_hid(*unicode, modifiers)?;
|
||||
Some(mapping)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn is_modifier_control_key(event: &KeyEvent) -> bool {
|
||||
@@ -235,6 +224,96 @@ fn parse_modifiers(event: &KeyEvent) -> KeyboardModifiers {
|
||||
modifiers
|
||||
}
|
||||
|
||||
fn with_shift(mut modifiers: KeyboardModifiers) -> KeyboardModifiers {
|
||||
modifiers.left_shift = true;
|
||||
modifiers
|
||||
}
|
||||
|
||||
fn shifted_mapping(key: CanonicalKey, modifiers: KeyboardModifiers) -> KeyMapping {
|
||||
let added_shift = !modifiers.left_shift && !modifiers.right_shift;
|
||||
KeyMapping {
|
||||
key,
|
||||
modifiers: with_shift(modifiers),
|
||||
added_shift,
|
||||
}
|
||||
}
|
||||
|
||||
fn plain_mapping(key: CanonicalKey, modifiers: KeyboardModifiers) -> KeyMapping {
|
||||
KeyMapping {
|
||||
key,
|
||||
modifiers,
|
||||
added_shift: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn shifted_printable_char_to_hid(ch: u32, modifiers: KeyboardModifiers) -> Option<KeyMapping> {
|
||||
match ch {
|
||||
33 => Some(shifted_mapping(CanonicalKey::Digit1, modifiers)),
|
||||
64 => Some(shifted_mapping(CanonicalKey::Digit2, modifiers)),
|
||||
35 => Some(shifted_mapping(CanonicalKey::Digit3, modifiers)),
|
||||
36 => Some(shifted_mapping(CanonicalKey::Digit4, modifiers)),
|
||||
37 => Some(shifted_mapping(CanonicalKey::Digit5, modifiers)),
|
||||
94 => Some(shifted_mapping(CanonicalKey::Digit6, modifiers)),
|
||||
38 => Some(shifted_mapping(CanonicalKey::Digit7, modifiers)),
|
||||
42 => Some(shifted_mapping(CanonicalKey::Digit8, modifiers)),
|
||||
40 => Some(shifted_mapping(CanonicalKey::Digit9, modifiers)),
|
||||
41 => Some(shifted_mapping(CanonicalKey::Digit0, modifiers)),
|
||||
95 => Some(shifted_mapping(CanonicalKey::Minus, modifiers)),
|
||||
43 => Some(shifted_mapping(CanonicalKey::Equal, modifiers)),
|
||||
123 => Some(shifted_mapping(CanonicalKey::BracketLeft, modifiers)),
|
||||
125 => Some(shifted_mapping(CanonicalKey::BracketRight, modifiers)),
|
||||
124 => Some(shifted_mapping(CanonicalKey::Backslash, modifiers)),
|
||||
58 => Some(shifted_mapping(CanonicalKey::Semicolon, modifiers)),
|
||||
34 => Some(shifted_mapping(CanonicalKey::Quote, modifiers)),
|
||||
126 => Some(shifted_mapping(CanonicalKey::Backquote, modifiers)),
|
||||
60 => Some(shifted_mapping(CanonicalKey::Comma, modifiers)),
|
||||
62 => Some(shifted_mapping(CanonicalKey::Period, modifiers)),
|
||||
63 => Some(shifted_mapping(CanonicalKey::Slash, modifiers)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn printable_char_to_hid(ch: u32, modifiers: KeyboardModifiers) -> Option<KeyMapping> {
|
||||
match ch {
|
||||
65..=90 => Some(shifted_mapping(
|
||||
CanonicalKey::from_hid_usage((ch - 65 + 0x04) as u8)?,
|
||||
modifiers,
|
||||
)),
|
||||
97..=122 => Some(plain_mapping(
|
||||
CanonicalKey::from_hid_usage((ch - 97 + 0x04) as u8)?,
|
||||
modifiers,
|
||||
)),
|
||||
48 => Some(plain_mapping(CanonicalKey::Digit0, modifiers)),
|
||||
49 => Some(plain_mapping(CanonicalKey::Digit1, modifiers)),
|
||||
50 => Some(plain_mapping(CanonicalKey::Digit2, modifiers)),
|
||||
51 => Some(plain_mapping(CanonicalKey::Digit3, modifiers)),
|
||||
52 => Some(plain_mapping(CanonicalKey::Digit4, modifiers)),
|
||||
53 => Some(plain_mapping(CanonicalKey::Digit5, modifiers)),
|
||||
54 => Some(plain_mapping(CanonicalKey::Digit6, modifiers)),
|
||||
55 => Some(plain_mapping(CanonicalKey::Digit7, modifiers)),
|
||||
56 => Some(plain_mapping(CanonicalKey::Digit8, modifiers)),
|
||||
57 => Some(plain_mapping(CanonicalKey::Digit9, modifiers)),
|
||||
32 => Some(plain_mapping(CanonicalKey::Space, modifiers)),
|
||||
13 | 10 => Some(plain_mapping(CanonicalKey::Enter, modifiers)),
|
||||
9 => Some(plain_mapping(CanonicalKey::Tab, modifiers)),
|
||||
27 => Some(plain_mapping(CanonicalKey::Escape, modifiers)),
|
||||
8 => Some(plain_mapping(CanonicalKey::Backspace, modifiers)),
|
||||
127 => Some(plain_mapping(CanonicalKey::Delete, modifiers)),
|
||||
45 => Some(plain_mapping(CanonicalKey::Minus, modifiers)),
|
||||
61 => Some(plain_mapping(CanonicalKey::Equal, modifiers)),
|
||||
91 => Some(plain_mapping(CanonicalKey::BracketLeft, modifiers)),
|
||||
93 => Some(plain_mapping(CanonicalKey::BracketRight, modifiers)),
|
||||
92 => Some(plain_mapping(CanonicalKey::Backslash, modifiers)),
|
||||
59 => Some(plain_mapping(CanonicalKey::Semicolon, modifiers)),
|
||||
39 => Some(plain_mapping(CanonicalKey::Quote, modifiers)),
|
||||
96 => Some(plain_mapping(CanonicalKey::Backquote, modifiers)),
|
||||
44 => Some(plain_mapping(CanonicalKey::Comma, modifiers)),
|
||||
46 => Some(plain_mapping(CanonicalKey::Period, modifiers)),
|
||||
47 => Some(plain_mapping(CanonicalKey::Slash, modifiers)),
|
||||
_ => shifted_printable_char_to_hid(ch, modifiers),
|
||||
}
|
||||
}
|
||||
|
||||
fn control_key_to_hid(key: i32) -> Option<u8> {
|
||||
match key {
|
||||
x if x == ControlKey::Alt as i32 => Some(0xE2), // Left Alt
|
||||
@@ -476,7 +555,7 @@ mod tests {
|
||||
event.y = 300;
|
||||
event.mask = mouse_type::MOVE; // Pure move event
|
||||
|
||||
let events = convert_mouse_event(&event, 1920, 1080, false);
|
||||
let events = convert_mouse_event(&event, 1920, 1080);
|
||||
assert!(!events.is_empty());
|
||||
assert_eq!(events[0].event_type, MouseEventType::MoveAbs);
|
||||
}
|
||||
@@ -488,11 +567,34 @@ mod tests {
|
||||
event.y = 300;
|
||||
event.mask = (mouse_button::LEFT << 3) | mouse_type::DOWN;
|
||||
|
||||
let events = convert_mouse_event(&event, 1920, 1080, false);
|
||||
assert!(events.len() >= 2);
|
||||
assert!(events
|
||||
.iter()
|
||||
.any(|e| e.event_type == MouseEventType::Down && e.button == Some(MouseButton::Left)));
|
||||
let events = convert_mouse_event(&event, 1920, 1080);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].event_type, MouseEventType::Down);
|
||||
assert_eq!(events[0].button, Some(MouseButton::Left));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_mouse_button_down_does_not_move() {
|
||||
let mut event = MouseEvent::new();
|
||||
event.mask = (mouse_button::LEFT << 3) | mouse_type::DOWN;
|
||||
|
||||
let events = convert_mouse_event(&event, 1920, 1080);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].event_type, MouseEventType::Down);
|
||||
assert_eq!(events[0].button, Some(MouseButton::Left));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_mouse_wheel_does_not_move() {
|
||||
let mut event = MouseEvent::new();
|
||||
event.x = 500;
|
||||
event.y = 1;
|
||||
event.mask = mouse_type::WHEEL;
|
||||
|
||||
let events = convert_mouse_event(&event, 1920, 1080);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].event_type, MouseEventType::Scroll);
|
||||
assert_eq!(events[0].scroll, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -502,7 +604,7 @@ mod tests {
|
||||
event.y = 8;
|
||||
event.mask = mouse_type::MOVE_RELATIVE;
|
||||
|
||||
let events = convert_mouse_event(&event, 1920, 1080, true);
|
||||
let events = convert_mouse_event(&event, 1920, 1080);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].event_type, MouseEventType::Move);
|
||||
assert_eq!(events[0].x, -12);
|
||||
@@ -526,4 +628,65 @@ mod tests {
|
||||
assert_eq!(kb_event.event_type, KeyEventType::Down);
|
||||
assert_eq!(kb_event.key, CanonicalKey::Enter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_at_press_to_shift_digit2() {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.press = true;
|
||||
key_event.union = Some(ke_union::Union::Unicode('@' as u32));
|
||||
|
||||
let events = convert_key_events(&key_event);
|
||||
assert_eq!(events.len(), 2);
|
||||
assert_eq!(events[0].event_type, KeyEventType::Down);
|
||||
assert_eq!(events[0].key, CanonicalKey::Digit2);
|
||||
assert!(events[0].modifiers.left_shift);
|
||||
assert_eq!(events[1].event_type, KeyEventType::Up);
|
||||
assert_eq!(events[1].key, CanonicalKey::Digit2);
|
||||
assert!(!events[1].modifiers.left_shift);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_shifted_chr_to_shift_digit2() {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.down = true;
|
||||
key_event.union = Some(ke_union::Union::Chr('@' as u32));
|
||||
|
||||
let events = convert_key_events(&key_event);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].event_type, KeyEventType::Down);
|
||||
assert_eq!(events[0].key, CanonicalKey::Digit2);
|
||||
assert!(events[0].modifiers.left_shift);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_map_mode_chr_as_physical_key() {
|
||||
use protobuf::EnumOrUnknown;
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.down = true;
|
||||
key_event.mode = EnumOrUnknown::new(KeyboardMode::Map);
|
||||
key_event.union = Some(ke_union::Union::Chr(0x41));
|
||||
|
||||
let events = convert_key_events(&key_event);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].event_type, KeyEventType::Down);
|
||||
assert_eq!(events[0].key, CanonicalKey::KeyA);
|
||||
assert!(!events[0].modifiers.left_shift);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_press_generates_down_and_up() {
|
||||
use protobuf::EnumOrUnknown;
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.press = true;
|
||||
key_event.union = Some(ke_union::Union::ControlKey(EnumOrUnknown::new(
|
||||
ControlKey::Return,
|
||||
)));
|
||||
|
||||
let events = convert_key_events(&key_event);
|
||||
assert_eq!(events.len(), 2);
|
||||
assert_eq!(events[0].event_type, KeyEventType::Down);
|
||||
assert_eq!(events[1].event_type, KeyEventType::Up);
|
||||
assert_eq!(events[0].key, CanonicalKey::Enter);
|
||||
assert_eq!(events[1].key, CanonicalKey::Enter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@ pub use hbb::rendezvous::{
|
||||
pub use hbb::message::{
|
||||
key_event, login_response, message, misc, AudioFormat, AudioFrame, Auth2FA, Clipboard,
|
||||
ControlKey, CursorData, CursorPosition, DisplayInfo, EncodedVideoFrame, EncodedVideoFrames,
|
||||
Features, Hash, IdPk, KeyEvent, LoginRequest, LoginResponse, Message as HbbMessage, Misc,
|
||||
MouseEvent, OptionMessage, PeerInfo, PublicKey, SignedId, SupportedDecoding, SupportedEncoding,
|
||||
SupportedResolutions, TestDelay, VideoFrame, WindowsSessions,
|
||||
Features, Hash, IdPk, KeyEvent, KeyboardMode, LoginRequest, LoginResponse,
|
||||
Message as HbbMessage, Misc, MouseEvent, OptionMessage, PeerInfo, PublicKey, SignedId,
|
||||
SupportedDecoding, SupportedEncoding, SupportedResolutions, TestDelay, VideoFrame,
|
||||
WindowsSessions,
|
||||
};
|
||||
|
||||
pub fn make_register_peer(id: &str, serial: i32) -> RendezvousMessage {
|
||||
|
||||
@@ -439,8 +439,11 @@ impl RendezvousMediator {
|
||||
}
|
||||
Some(rendezvous_message::Union::PunchHole(ph)) => {
|
||||
let config = self.config.read().clone();
|
||||
let effective_relay_server =
|
||||
select_relay_server(config.relay_server.as_deref(), &ph.relay_server);
|
||||
let effective_relay_server = select_relay_server(
|
||||
config.relay_server.as_deref(),
|
||||
&ph.relay_server,
|
||||
&config.rendezvous_server,
|
||||
);
|
||||
|
||||
let peer_addr = if !ph.socket_addr.is_empty() {
|
||||
AddrMangle::decode(&ph.socket_addr)
|
||||
@@ -514,8 +517,11 @@ impl RendezvousMediator {
|
||||
}
|
||||
Some(rendezvous_message::Union::RequestRelay(rr)) => {
|
||||
let config = self.config.read().clone();
|
||||
let effective_relay_server =
|
||||
select_relay_server(config.relay_server.as_deref(), &rr.relay_server);
|
||||
let effective_relay_server = select_relay_server(
|
||||
config.relay_server.as_deref(),
|
||||
&rr.relay_server,
|
||||
&config.rendezvous_server,
|
||||
);
|
||||
|
||||
info!(
|
||||
"Received RequestRelay: relay_server={}, effective_relay_server={}, uuid={}, secure={}",
|
||||
@@ -542,9 +548,12 @@ impl RendezvousMediator {
|
||||
}
|
||||
Some(rendezvous_message::Union::FetchLocalAddr(fla)) => {
|
||||
let config = self.config.read().clone();
|
||||
let effective_relay_server =
|
||||
select_relay_server(config.relay_server.as_deref(), &fla.relay_server)
|
||||
.unwrap_or_default();
|
||||
let effective_relay_server = select_relay_server(
|
||||
config.relay_server.as_deref(),
|
||||
&fla.relay_server,
|
||||
&config.rendezvous_server,
|
||||
)
|
||||
.unwrap_or_default();
|
||||
|
||||
let peer_addr = AddrMangle::decode(&fla.socket_addr);
|
||||
info!(
|
||||
@@ -613,10 +622,18 @@ fn normalize_relay_server(server: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn select_relay_server(local_relay: Option<&str>, server_relay: &str) -> Option<String> {
|
||||
fn select_relay_server(
|
||||
local_relay: Option<&str>,
|
||||
server_relay: &str,
|
||||
rendezvous_server: &str,
|
||||
) -> Option<String> {
|
||||
local_relay
|
||||
.and_then(normalize_relay_server)
|
||||
.or_else(|| normalize_relay_server(server_relay))
|
||||
.or_else(|| {
|
||||
let host = rendezvous_server.trim().split(':').next().unwrap_or("");
|
||||
normalize_relay_server(host)
|
||||
})
|
||||
}
|
||||
|
||||
impl AddrMangle {
|
||||
@@ -799,25 +816,38 @@ mod tests {
|
||||
#[test]
|
||||
fn test_select_relay_server_prefers_local() {
|
||||
assert_eq!(
|
||||
select_relay_server(Some("local.example.com:21117"), "server.example.com:21117"),
|
||||
select_relay_server(
|
||||
Some("local.example.com:21117"),
|
||||
"server.example.com:21117",
|
||||
"hbbs.example.com:21116"
|
||||
),
|
||||
Some("local.example.com:21117".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
select_relay_server(Some("local.example.com"), "server.example.com:21117"),
|
||||
select_relay_server(
|
||||
Some("local.example.com"),
|
||||
"server.example.com:21117",
|
||||
"hbbs.example.com:21116"
|
||||
),
|
||||
Some("local.example.com:21117".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
select_relay_server(Some(" "), "server.example.com"),
|
||||
select_relay_server(Some(" "), "server.example.com", "hbbs.example.com:21116"),
|
||||
Some("server.example.com:21117".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
select_relay_server(None, "server.example.com:21117"),
|
||||
select_relay_server(None, "server.example.com:21117", "hbbs.example.com:21116"),
|
||||
Some("server.example.com:21117".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(select_relay_server(None, ""), None);
|
||||
assert_eq!(
|
||||
select_relay_server(None, "", "hbbs.example.com:21116"),
|
||||
Some("hbbs.example.com:21117".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(select_relay_server(None, "", ""), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user