Просмотр исходного кода

replace libs/hbb_common with submodule (#502)

cargo update -p schannel to fix crash on higher rust toolchain, https://github.com/seanmonstar/reqwest/issues/2311

Signed-off-by: 21pages <sunboeasy@gmail.com>
21pages 1 год назад
Родитель
Сommit
7a509f6975

+ 11 - 1
.github/workflows/build.yaml

@@ -41,6 +41,8 @@ jobs:
41 41
       
42 42
       - name: Checkout
43 43
         uses: actions/checkout@v3
44
+        with:
45
+          submodules: recursive
44 46
 
45 47
       - name: Install toolchain
46 48
         uses: actions-rs/toolchain@v1
@@ -80,6 +82,8 @@ jobs:
80 82
       
81 83
       - name: Checkout
82 84
         uses: actions/checkout@v3
85
+        with:
86
+          submodules: recursive
83 87
 
84 88
       - name: Install toolchain
85 89
         uses: actions-rs/toolchain@v1
@@ -222,6 +226,8 @@ jobs:
222 226
 
223 227
       - name: Checkout
224 228
         uses: actions/checkout@v3
229
+        with:
230
+          submodules: recursive
225 231
         
226 232
       - name: Download binaries
227 233
         uses: actions/download-artifact@v3
@@ -343,6 +349,8 @@ jobs:
343 349
 
344 350
       - name: Checkout
345 351
         uses: actions/checkout@v3
352
+        with:
353
+          submodules: recursive
346 354
         
347 355
       - name: Download binaries
348 356
         uses: actions/download-artifact@v3
@@ -462,7 +470,9 @@ jobs:
462 470
 
463 471
       - name: Checkout
464 472
         uses: actions/checkout@v3
465
-        
473
+        with:
474
+          submodules: recursive
475
+
466 476
       - name: Set up QEMU
467 477
         uses: docker/setup-qemu-action@v2
468 478
 

+ 6 - 0
.github/workflows/ghcr.yml

@@ -36,6 +36,8 @@ jobs:
36 36
     steps:
37 37
       - name: Checkout
38 38
         uses: actions/checkout@v4
39
+        with:
40
+          submodules: recursive
39 41
     
40 42
       - name: Install Rust toolchain
41 43
         uses: dtolnay/rust-toolchain@v1
@@ -85,6 +87,8 @@ jobs:
85 87
     steps:
86 88
       - name: Checkout
87 89
         uses: actions/checkout@v4
90
+        with:
91
+          submodules: recursive
88 92
 
89 93
       - name: Download binaries
90 94
         uses: actions/download-artifact@v4
@@ -216,6 +220,8 @@ jobs:
216 220
     steps:
217 221
       - name: Checkout
218 222
         uses: actions/checkout@v4
223
+        with:
224
+          submodules: recursive
219 225
 
220 226
       - name: Download binaries
221 227
         uses: actions/download-artifact@v4

+ 4 - 0
.github/workflows/test.yml

@@ -20,6 +20,7 @@ jobs:
20 20
           profile: minimal
21 21
           toolchain: stable
22 22
           override: true
23
+          submodules: recursive
23 24
       - uses: Swatinem/rust-cache@v2
24 25
       - uses: actions-rs/cargo@v1
25 26
         with:
@@ -34,6 +35,7 @@ jobs:
34 35
           profile: minimal
35 36
           toolchain: stable
36 37
           override: true
38
+          submodules: recursive
37 39
       - uses: Swatinem/rust-cache@v2
38 40
       - uses: actions-rs/cargo@v1
39 41
         with:
@@ -50,6 +52,7 @@ jobs:
50 52
           toolchain: stable
51 53
           override: true
52 54
           components: rustfmt
55
+          submodules: recursive
53 56
       - uses: Swatinem/rust-cache@v2
54 57
       - uses: actions-rs/cargo@v1
55 58
         with:
@@ -69,6 +72,7 @@ jobs:
69 72
           toolchain: stable
70 73
           override: true
71 74
           components: clippy
75
+          submodules: recursive
72 76
       - uses: Swatinem/rust-cache@v2
73 77
       - uses: actions-rs/cargo@v1
74 78
         with:

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
1
+[submodule "libs/hbb_common"]
2
+	path = libs/hbb_common
3
+	url = https://github.com/rustdesk/hbb_common

Разница между файлами не показана из-за своего большого размера
+ 1329 - 353
Cargo.lock


+ 7 - 0
Cargo.toml

@@ -52,6 +52,13 @@ local-ip-address = "0.5.1"
52 52
 dns-lookup = "1.0.8"
53 53
 ping = "0.4.0"
54 54
 
55
+[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies]
56
+# https://github.com/rustdesk/rustdesk-server-pro/issues/189, using native-tls for better tls support
57
+reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "native-tls", "gzip"], default-features=false }
58
+
59
+[target.'cfg(not(any(target_os = "macos", target_os = "windows")))'.dependencies]
60
+reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "rustls-tls", "rustls-tls-native-roots", "gzip"], default-features=false }
61
+
55 62
 [build-dependencies]
56 63
 hbb_common = { path = "libs/hbb_common" }
57 64
 

+ 1 - 0
libs/hbb_common

@@ -0,0 +1 @@
1
+Subproject commit 49c6b24a7a8c39d4448e07b743007ef1a3febd43

+ 0 - 4
libs/hbb_common/.gitignore

@@ -1,4 +0,0 @@
1
-/target
2
-**/*.rs.bk
3
-Cargo.lock
4
-src/protos/

+ 0 - 51
libs/hbb_common/Cargo.toml

@@ -1,51 +0,0 @@
1
-[package]
2
-name = "hbb_common"
3
-version = "0.1.0"
4
-authors = ["open-trade <info@opentradesolutions.com>"]
5
-edition = "2018"
6
-
7
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
-
9
-[dependencies]
10
-protobuf = { version = "3.1", features = ["with-bytes"] }
11
-tokio = { version = "1.20", features = ["full"] }
12
-tokio-util = { version = "0.7", features = ["full"] }
13
-futures = "0.3"
14
-bytes = { version = "1.2", features = ["serde"] }
15
-log = "0.4"
16
-env_logger = "0.9"
17
-socket2 = { version = "0.3", features = ["reuseport"] }
18
-zstd = "0.9"
19
-quinn = {version = "0.8", optional = true }
20
-anyhow = "1.0"
21
-futures-util = "0.3"
22
-directories-next = "2.0"
23
-rand = "0.8"
24
-serde_derive = "1.0"
25
-serde = "1.0"
26
-lazy_static = "1.4"
27
-confy = { git = "https://github.com/open-trade/confy" }
28
-dirs-next = "2.0"
29
-filetime = "0.2"
30
-sodiumoxide = "0.2"
31
-regex = "1.4"
32
-tokio-socks = { git = "https://github.com/open-trade/tokio-socks" }
33
-chrono = "0.4"
34
-
35
-[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
36
-mac_address = "1.1"
37
-machine-uid = "0.2"
38
-
39
-[features]
40
-quic = []
41
-flatpak = []
42
-
43
-[build-dependencies]
44
-protobuf-codegen = { version = "3.1" }
45
-
46
-[target.'cfg(target_os = "windows")'.dependencies]
47
-winapi = { version = "0.3", features = ["winuser"] }
48
-
49
-[dev-dependencies]
50
-toml = "0.5"
51
-serde_json = "1.0"

+ 0 - 14
libs/hbb_common/build.rs

@@ -1,14 +0,0 @@
1
-fn main() {
2
-    let out_dir = format!("{}/protos", std::env::var("OUT_DIR").unwrap());
3
-
4
-    std::fs::create_dir_all(&out_dir).unwrap();
5
-
6
-    protobuf_codegen::Codegen::new()
7
-        .pure()
8
-        .out_dir(out_dir)
9
-        .inputs(["protos/rendezvous.proto", "protos/message.proto"])
10
-        .include("protos")
11
-        .customize(protobuf_codegen::Customize::default().tokio_bytes(true))
12
-        .run()
13
-        .expect("Codegen failed.");
14
-}

+ 0 - 638
libs/hbb_common/protos/message.proto

@@ -1,638 +0,0 @@
1
-syntax = "proto3";
2
-package hbb;
3
-
4
-message EncodedVideoFrame {
5
-  bytes data = 1;
6
-  bool key = 2;
7
-  int64 pts = 3;
8
-}
9
-
10
-message EncodedVideoFrames { repeated EncodedVideoFrame frames = 1; }
11
-
12
-message RGB { bool compress = 1; }
13
-
14
-// planes data send directly in binary for better use arraybuffer on web
15
-message YUV {
16
-  bool compress = 1;
17
-  int32 stride = 2;
18
-}
19
-
20
-message VideoFrame {
21
-  oneof union {
22
-    EncodedVideoFrames vp9s = 6;
23
-    RGB rgb = 7;
24
-    YUV yuv = 8;
25
-    EncodedVideoFrames h264s = 10;
26
-    EncodedVideoFrames h265s = 11;
27
-  }
28
-  int64 timestamp = 9;
29
-}
30
-
31
-message IdPk {
32
-  string id = 1;
33
-  bytes pk = 2;
34
-}
35
-
36
-message DisplayInfo {
37
-  sint32 x = 1;
38
-  sint32 y = 2;
39
-  int32 width = 3;
40
-  int32 height = 4;
41
-  string name = 5;
42
-  bool online = 6;
43
-  bool cursor_embedded = 7;
44
-}
45
-
46
-message PortForward {
47
-  string host = 1;
48
-  int32 port = 2;
49
-}
50
-
51
-message FileTransfer {
52
-  string dir = 1;
53
-  bool show_hidden = 2;
54
-}
55
-
56
-message LoginRequest {
57
-  string username = 1;
58
-  bytes password = 2;
59
-  string my_id = 4;
60
-  string my_name = 5;
61
-  OptionMessage option = 6;
62
-  oneof union {
63
-    FileTransfer file_transfer = 7;
64
-    PortForward port_forward = 8;
65
-  }
66
-  bool video_ack_required = 9;
67
-  uint64 session_id = 10;
68
-  string version = 11;
69
-}
70
-
71
-message ChatMessage { string text = 1; }
72
-
73
-message Features {
74
-  bool privacy_mode = 1;
75
-}
76
-
77
-message SupportedEncoding {
78
-  bool h264 = 1;
79
-  bool h265 = 2;
80
-}
81
-
82
-message PeerInfo {
83
-  string username = 1;
84
-  string hostname = 2;
85
-  string platform = 3;
86
-  repeated DisplayInfo displays = 4;
87
-  int32 current_display = 5;
88
-  bool sas_enabled = 6;
89
-  string version = 7;
90
-  int32 conn_id = 8;
91
-  Features features = 9;
92
-  SupportedEncoding encoding = 10;
93
-}
94
-
95
-message LoginResponse {
96
-  oneof union {
97
-    string error = 1;
98
-    PeerInfo peer_info = 2;
99
-  }
100
-}
101
-
102
-message MouseEvent {
103
-  int32 mask = 1;
104
-  sint32 x = 2;
105
-  sint32 y = 3;
106
-  repeated ControlKey modifiers = 4;
107
-}
108
-
109
-enum KeyboardMode{
110
-  Legacy = 0;
111
-  Map = 1;
112
-  Translate = 2;
113
-  Auto = 3;
114
-}
115
-
116
-enum ControlKey {
117
-  Unknown = 0;
118
-  Alt = 1;
119
-  Backspace = 2;
120
-  CapsLock = 3;
121
-  Control = 4;
122
-  Delete = 5;
123
-  DownArrow = 6;
124
-  End = 7;
125
-  Escape = 8;
126
-  F1 = 9;
127
-  F10 = 10;
128
-  F11 = 11;
129
-  F12 = 12;
130
-  F2 = 13;
131
-  F3 = 14;
132
-  F4 = 15;
133
-  F5 = 16;
134
-  F6 = 17;
135
-  F7 = 18;
136
-  F8 = 19;
137
-  F9 = 20;
138
-  Home = 21;
139
-  LeftArrow = 22;
140
-  /// meta key (also known as "windows"; "super"; and "command")
141
-  Meta = 23;
142
-  /// option key on macOS (alt key on Linux and Windows)
143
-  Option = 24; // deprecated, use Alt instead
144
-  PageDown = 25;
145
-  PageUp = 26;
146
-  Return = 27;
147
-  RightArrow = 28;
148
-  Shift = 29;
149
-  Space = 30;
150
-  Tab = 31;
151
-  UpArrow = 32;
152
-  Numpad0 = 33;
153
-  Numpad1 = 34;
154
-  Numpad2 = 35;
155
-  Numpad3 = 36;
156
-  Numpad4 = 37;
157
-  Numpad5 = 38;
158
-  Numpad6 = 39;
159
-  Numpad7 = 40;
160
-  Numpad8 = 41;
161
-  Numpad9 = 42;
162
-  Cancel = 43;
163
-  Clear = 44;
164
-  Menu = 45; // deprecated, use Alt instead
165
-  Pause = 46;
166
-  Kana = 47;
167
-  Hangul = 48;
168
-  Junja = 49;
169
-  Final = 50;
170
-  Hanja = 51;
171
-  Kanji = 52;
172
-  Convert = 53;
173
-  Select = 54;
174
-  Print = 55;
175
-  Execute = 56;
176
-  Snapshot = 57;
177
-  Insert = 58;
178
-  Help = 59;
179
-  Sleep = 60;
180
-  Separator = 61;
181
-  Scroll = 62;
182
-  NumLock = 63;
183
-  RWin = 64;
184
-  Apps = 65;
185
-  Multiply = 66;
186
-  Add = 67;
187
-  Subtract = 68;
188
-  Decimal = 69;
189
-  Divide = 70;
190
-  Equals = 71;
191
-  NumpadEnter = 72;
192
-  RShift = 73;
193
-  RControl = 74;
194
-  RAlt = 75;
195
-  CtrlAltDel = 100;
196
-  LockScreen = 101;
197
-}
198
-
199
-message KeyEvent {
200
-  bool down = 1;
201
-  bool press = 2;
202
-  oneof union {
203
-    ControlKey control_key = 3;
204
-    uint32 chr = 4;
205
-    uint32 unicode = 5;
206
-    string seq = 6;
207
-  }
208
-  repeated ControlKey modifiers = 8;
209
-  KeyboardMode mode = 9;
210
-}
211
-
212
-message CursorData {
213
-  uint64 id = 1;
214
-  sint32 hotx = 2;
215
-  sint32 hoty = 3;
216
-  int32 width = 4;
217
-  int32 height = 5;
218
-  bytes colors = 6;
219
-}
220
-
221
-message CursorPosition {
222
-  sint32 x = 1;
223
-  sint32 y = 2;
224
-}
225
-
226
-message Hash {
227
-  string salt = 1;
228
-  string challenge = 2;
229
-}
230
-
231
-message Clipboard {
232
-  bool compress = 1;
233
-  bytes content = 2;
234
-}
235
-
236
-enum FileType {
237
-  Dir = 0;
238
-  DirLink = 2;
239
-  DirDrive = 3;
240
-  File = 4;
241
-  FileLink = 5;
242
-}
243
-
244
-message FileEntry {
245
-  FileType entry_type = 1;
246
-  string name = 2;
247
-  bool is_hidden = 3;
248
-  uint64 size = 4;
249
-  uint64 modified_time = 5;
250
-}
251
-
252
-message FileDirectory {
253
-  int32 id = 1;
254
-  string path = 2;
255
-  repeated FileEntry entries = 3;
256
-}
257
-
258
-message ReadDir {
259
-  string path = 1;
260
-  bool include_hidden = 2;
261
-}
262
-
263
-message ReadAllFiles {
264
-  int32 id = 1;
265
-  string path = 2;
266
-  bool include_hidden = 3;
267
-}
268
-
269
-message FileAction {
270
-  oneof union {
271
-    ReadDir read_dir = 1;
272
-    FileTransferSendRequest send = 2;
273
-    FileTransferReceiveRequest receive = 3;
274
-    FileDirCreate create = 4;
275
-    FileRemoveDir remove_dir = 5;
276
-    FileRemoveFile remove_file = 6;
277
-    ReadAllFiles all_files = 7;
278
-    FileTransferCancel cancel = 8;
279
-    FileTransferSendConfirmRequest send_confirm = 9;
280
-  }
281
-}
282
-
283
-message FileTransferCancel { int32 id = 1; }
284
-
285
-message FileResponse {
286
-  oneof union {
287
-    FileDirectory dir = 1;
288
-    FileTransferBlock block = 2;
289
-    FileTransferError error = 3;
290
-    FileTransferDone done = 4;
291
-    FileTransferDigest digest = 5;
292
-  }
293
-}
294
-
295
-message FileTransferDigest {
296
-  int32 id = 1;
297
-  sint32 file_num = 2;
298
-  uint64 last_modified = 3;
299
-  uint64 file_size = 4;
300
-  bool is_upload = 5;
301
-}
302
-
303
-message FileTransferBlock {
304
-  int32 id = 1;
305
-  sint32 file_num = 2;
306
-  bytes data = 3;
307
-  bool compressed = 4;
308
-  uint32 blk_id = 5;
309
-}
310
-
311
-message FileTransferError {
312
-  int32 id = 1;
313
-  string error = 2;
314
-  sint32 file_num = 3;
315
-}
316
-
317
-message FileTransferSendRequest {
318
-  int32 id = 1;
319
-  string path = 2;
320
-  bool include_hidden = 3;
321
-  int32 file_num = 4;
322
-}
323
-
324
-message FileTransferSendConfirmRequest {
325
-  int32 id = 1;
326
-  sint32 file_num = 2;
327
-  oneof union {
328
-    bool skip = 3;
329
-    uint32 offset_blk = 4;
330
-  }
331
-}
332
-
333
-message FileTransferDone {
334
-  int32 id = 1;
335
-  sint32 file_num = 2;
336
-}
337
-
338
-message FileTransferReceiveRequest {
339
-  int32 id = 1;
340
-  string path = 2; // path written to
341
-  repeated FileEntry files = 3;
342
-  int32 file_num = 4;
343
-}
344
-
345
-message FileRemoveDir {
346
-  int32 id = 1;
347
-  string path = 2;
348
-  bool recursive = 3;
349
-}
350
-
351
-message FileRemoveFile {
352
-  int32 id = 1;
353
-  string path = 2;
354
-  sint32 file_num = 3;
355
-}
356
-
357
-message FileDirCreate {
358
-  int32 id = 1;
359
-  string path = 2;
360
-}
361
-
362
-// main logic from freeRDP
363
-message CliprdrMonitorReady {
364
-}
365
-
366
-message CliprdrFormat {
367
-  int32 id = 2;
368
-  string format = 3;
369
-}
370
-
371
-message CliprdrServerFormatList {
372
-  repeated CliprdrFormat formats = 2;
373
-}
374
-
375
-message CliprdrServerFormatListResponse {
376
-  int32 msg_flags = 2;
377
-}
378
-
379
-message CliprdrServerFormatDataRequest {
380
-  int32 requested_format_id = 2;
381
-}
382
-
383
-message CliprdrServerFormatDataResponse {
384
-  int32 msg_flags = 2;
385
-  bytes format_data = 3;
386
-}
387
-
388
-message CliprdrFileContentsRequest {
389
-  int32 stream_id = 2;
390
-  int32 list_index = 3;
391
-  int32 dw_flags = 4;
392
-  int32 n_position_low = 5;
393
-  int32 n_position_high = 6;
394
-  int32 cb_requested = 7;
395
-  bool have_clip_data_id = 8;
396
-  int32 clip_data_id = 9;
397
-}
398
-
399
-message CliprdrFileContentsResponse {
400
-  int32 msg_flags = 3;
401
-  int32 stream_id = 4;
402
-  bytes requested_data = 5;
403
-}
404
-
405
-message Cliprdr {
406
-  oneof union {
407
-    CliprdrMonitorReady ready = 1;
408
-    CliprdrServerFormatList format_list = 2;
409
-    CliprdrServerFormatListResponse format_list_response = 3;
410
-    CliprdrServerFormatDataRequest format_data_request = 4;
411
-    CliprdrServerFormatDataResponse format_data_response = 5;
412
-    CliprdrFileContentsRequest file_contents_request = 6;
413
-    CliprdrFileContentsResponse file_contents_response = 7;
414
-  }
415
-}
416
-
417
-message SwitchDisplay {
418
-  int32 display = 1;
419
-  sint32 x = 2;
420
-  sint32 y = 3;
421
-  int32 width = 4;
422
-  int32 height = 5;
423
-  bool cursor_embedded = 6;
424
-}
425
-
426
-message PermissionInfo {
427
-  enum Permission {
428
-    Keyboard = 0;
429
-    Clipboard = 2;
430
-    Audio = 3;
431
-    File = 4;
432
-    Restart = 5;
433
-    Recording = 6;
434
-  }
435
-
436
-  Permission permission = 1;
437
-  bool enabled = 2;
438
-}
439
-
440
-enum ImageQuality {
441
-  NotSet = 0;
442
-  Low = 2;
443
-  Balanced = 3;
444
-  Best = 4;
445
-}
446
-
447
-message VideoCodecState {
448
-  enum PreferCodec {
449
-    Auto = 0;
450
-    VPX = 1;
451
-    H264 = 2;
452
-    H265 = 3;
453
-  }
454
-
455
-  int32 score_vpx = 1;
456
-  int32 score_h264 = 2;
457
-  int32 score_h265 = 3;
458
-  PreferCodec prefer = 4;
459
-}
460
-
461
-message OptionMessage {
462
-  enum BoolOption {
463
-    NotSet = 0;
464
-    No = 1;
465
-    Yes = 2;
466
-  }
467
-  ImageQuality image_quality = 1;
468
-  BoolOption lock_after_session_end = 2;
469
-  BoolOption show_remote_cursor = 3;
470
-  BoolOption privacy_mode = 4;
471
-  BoolOption block_input = 5;
472
-  int32 custom_image_quality = 6;
473
-  BoolOption disable_audio = 7;
474
-  BoolOption disable_clipboard = 8;
475
-  BoolOption enable_file_transfer = 9;
476
-  VideoCodecState video_codec_state = 10;
477
-  int32 custom_fps = 11;
478
-}
479
-
480
-message TestDelay {
481
-  int64 time = 1;
482
-  bool from_client = 2;
483
-  uint32 last_delay = 3;
484
-  uint32 target_bitrate = 4;
485
-}
486
-
487
-message PublicKey {
488
-  bytes asymmetric_value = 1;
489
-  bytes symmetric_value = 2;
490
-}
491
-
492
-message SignedId { bytes id = 1; }
493
-
494
-message AudioFormat {
495
-  uint32 sample_rate = 1;
496
-  uint32 channels = 2;
497
-}
498
-
499
-message AudioFrame { 
500
-  bytes data = 1; 
501
-  int64 timestamp = 2;
502
-}
503
-
504
-// Notify peer to show message box.
505
-message MessageBox {
506
-  // Message type. Refer to flutter/lib/common.dart/msgBox().
507
-  string msgtype = 1;
508
-  string title = 2;
509
-  // English
510
-  string text = 3;
511
-  // If not empty, msgbox provides a button to following the link.
512
-  // The link here can't be directly http url.
513
-  // It must be the key of http url configed in peer side or "rustdesk://*" (jump in app).
514
-  string link = 4;
515
-}
516
-
517
-message BackNotification {
518
-  // no need to consider block input by someone else
519
-  enum BlockInputState {
520
-    BlkStateUnknown = 0;
521
-    BlkOnSucceeded = 2;
522
-    BlkOnFailed = 3;
523
-    BlkOffSucceeded = 4;
524
-    BlkOffFailed = 5;
525
-  }
526
-  enum PrivacyModeState {
527
-    PrvStateUnknown = 0;
528
-    // Privacy mode on by someone else
529
-    PrvOnByOther = 2;
530
-    // Privacy mode is not supported on the remote side
531
-    PrvNotSupported = 3;
532
-    // Privacy mode on by self
533
-    PrvOnSucceeded = 4;
534
-    // Privacy mode on by self, but denied
535
-    PrvOnFailedDenied = 5;
536
-    // Some plugins are not found
537
-    PrvOnFailedPlugin = 6;
538
-    // Privacy mode on by self, but failed
539
-    PrvOnFailed = 7;
540
-    // Privacy mode off by self
541
-    PrvOffSucceeded = 8;
542
-    // Ctrl + P
543
-    PrvOffByPeer = 9;
544
-    // Privacy mode off by self, but failed
545
-    PrvOffFailed = 10;
546
-    PrvOffUnknown = 11;
547
-  }
548
-
549
-  oneof union {
550
-    PrivacyModeState privacy_mode_state = 1;
551
-    BlockInputState block_input_state = 2;
552
-  }
553
-}
554
-
555
-message ElevationRequestWithLogon {
556
-  string username = 1;
557
-  string password = 2;
558
-}
559
-
560
-message ElevationRequest {
561
-  oneof union {
562
-    bool direct = 1;
563
-    ElevationRequestWithLogon logon = 2;
564
-  }
565
-}
566
-
567
-message SwitchSidesRequest {
568
-  bytes uuid = 1;
569
-}
570
-
571
-message SwitchSidesResponse {
572
-  bytes uuid = 1;
573
-  LoginRequest lr = 2;
574
-}
575
-
576
-message SwitchBack {}
577
-
578
-message Misc {
579
-  oneof union {
580
-    ChatMessage chat_message = 4;
581
-    SwitchDisplay switch_display = 5;
582
-    PermissionInfo permission_info = 6;
583
-    OptionMessage option = 7;
584
-    AudioFormat audio_format = 8;
585
-    string close_reason = 9;
586
-    bool refresh_video = 10;
587
-    bool video_received = 12;
588
-    BackNotification back_notification = 13;
589
-    bool restart_remote_device = 14;
590
-    bool uac = 15;
591
-    bool foreground_window_elevated = 16;
592
-    bool stop_service = 17;
593
-    ElevationRequest elevation_request = 18;
594
-    string elevation_response = 19;
595
-    bool portable_service_running = 20;
596
-    SwitchSidesRequest switch_sides_request = 21;
597
-    SwitchBack switch_back = 22;
598
-  }
599
-}
600
-
601
-message VoiceCallRequest {
602
-  int64 req_timestamp = 1;
603
-  // Indicates whether the request is a connect action or a disconnect action.
604
-  bool is_connect = 2;
605
-}
606
-
607
-message VoiceCallResponse {
608
-  bool accepted = 1;
609
-  int64 req_timestamp = 2; // Should copy from [VoiceCallRequest::req_timestamp].
610
-  int64 ack_timestamp = 3;
611
-}
612
-
613
-message Message {
614
-  oneof union {
615
-    SignedId signed_id = 3;
616
-    PublicKey public_key = 4;
617
-    TestDelay test_delay = 5;
618
-    VideoFrame video_frame = 6;
619
-    LoginRequest login_request = 7;
620
-    LoginResponse login_response = 8;
621
-    Hash hash = 9;
622
-    MouseEvent mouse_event = 10;
623
-    AudioFrame audio_frame = 11;
624
-    CursorData cursor_data = 12;
625
-    CursorPosition cursor_position = 13;
626
-    uint64 cursor_id = 14;
627
-    KeyEvent key_event = 15;
628
-    Clipboard clipboard = 16;
629
-    FileAction file_action = 17;
630
-    FileResponse file_response = 18;
631
-    Misc misc = 19;
632
-    Cliprdr cliprdr = 20;
633
-    MessageBox message_box = 21;
634
-    SwitchSidesResponse switch_sides_response = 22;
635
-    VoiceCallRequest voice_call_request = 23;
636
-    VoiceCallResponse voice_call_response = 24;
637
-  }
638
-}

+ 0 - 182
libs/hbb_common/protos/rendezvous.proto

@@ -1,182 +0,0 @@
1
-syntax = "proto3";
2
-package hbb;
3
-
4
-message RegisterPeer {
5
-  string id = 1;
6
-  int32 serial = 2;
7
-}
8
-
9
-enum ConnType {
10
-  DEFAULT_CONN = 0;
11
-  FILE_TRANSFER = 1;
12
-  PORT_FORWARD = 2;
13
-  RDP = 3;
14
-}
15
-
16
-message RegisterPeerResponse { bool request_pk = 2; }
17
-
18
-message PunchHoleRequest { 
19
-  string id = 1; 
20
-  NatType nat_type = 2;
21
-  string licence_key = 3;
22
-  ConnType conn_type = 4;
23
-  string token = 5;
24
-}
25
-
26
-message PunchHole { 
27
-  bytes socket_addr = 1;
28
-  string relay_server = 2;
29
-  NatType nat_type = 3;
30
-}
31
-
32
-message TestNatRequest {
33
-  int32 serial = 1;
34
-}
35
-
36
-// per my test, uint/int has no difference in encoding, int not good for negative, use sint for negative
37
-message TestNatResponse {
38
-  int32 port = 1; 
39
-  ConfigUpdate cu = 2; // for mobile
40
-}
41
-
42
-enum NatType {
43
-  UNKNOWN_NAT = 0;
44
-  ASYMMETRIC = 1;
45
-  SYMMETRIC = 2;
46
-}
47
-
48
-message PunchHoleSent {
49
-  bytes socket_addr = 1;
50
-  string id = 2;
51
-  string relay_server = 3;
52
-  NatType nat_type = 4;
53
-  string version = 5;
54
-}
55
-
56
-message RegisterPk {
57
-  string id = 1;
58
-  bytes uuid = 2;
59
-  bytes pk = 3;
60
-  string old_id = 4;
61
-}
62
-
63
-message RegisterPkResponse {
64
-  enum Result {
65
-    OK = 0;
66
-    UUID_MISMATCH = 2;
67
-    ID_EXISTS = 3;
68
-    TOO_FREQUENT = 4;
69
-    INVALID_ID_FORMAT = 5;
70
-    NOT_SUPPORT = 6;
71
-    SERVER_ERROR = 7;
72
-  }
73
-  Result result = 1;
74
-}
75
-
76
-message PunchHoleResponse {
77
-  bytes socket_addr = 1;
78
-  bytes pk = 2;
79
-  enum Failure {
80
-    ID_NOT_EXIST = 0;
81
-    OFFLINE = 2;
82
-    LICENSE_MISMATCH = 3;
83
-    LICENSE_OVERUSE = 4;
84
-  }
85
-  Failure failure = 3;
86
-  string relay_server = 4;
87
-  oneof union {
88
-    NatType nat_type = 5;
89
-    bool is_local = 6;
90
-  }
91
-  string other_failure = 7;
92
-}
93
-
94
-message ConfigUpdate {
95
-  int32 serial = 1;
96
-  repeated string rendezvous_servers = 2;
97
-}
98
-
99
-message RequestRelay {
100
-  string id = 1;
101
-  string uuid = 2;
102
-  bytes socket_addr = 3;
103
-  string relay_server = 4;
104
-  bool secure = 5;
105
-  string licence_key = 6;
106
-  ConnType conn_type = 7;
107
-  string token = 8;
108
-}
109
-
110
-message RelayResponse {
111
-  bytes socket_addr = 1;
112
-  string uuid = 2;
113
-  string relay_server = 3;
114
-  oneof union {
115
-    string id = 4;
116
-    bytes pk = 5;
117
-  }
118
-  string refuse_reason = 6;
119
-  string version = 7;
120
-}
121
-
122
-message SoftwareUpdate { string url = 1; }
123
-
124
-// if in same intranet, punch hole won't work both for udp and tcp,
125
-// even some router has below connection error if we connect itself,
126
-//  { kind: Other, error: "could not resolve to any address" },
127
-// so we request local address to connect.
128
-message FetchLocalAddr { 
129
-  bytes socket_addr = 1; 
130
-  string relay_server = 2;
131
-}
132
-
133
-message LocalAddr {
134
-  bytes socket_addr = 1;
135
-  bytes local_addr = 2;
136
-  string relay_server = 3;
137
-  string id = 4;
138
-  string version = 5;
139
-}
140
-
141
-message PeerDiscovery {
142
-  string cmd = 1;
143
-  string mac = 2;
144
-  string id = 3;
145
-  string username = 4;
146
-  string hostname = 5;
147
-  string platform = 6;
148
-  string misc = 7;
149
-}
150
-
151
-message OnlineRequest {
152
-  string id = 1;
153
-  repeated string peers = 2;
154
-}
155
-
156
-message OnlineResponse {
157
-  bytes states = 1;
158
-}
159
-
160
-message RendezvousMessage {
161
-  oneof union {
162
-    RegisterPeer register_peer = 6;
163
-    RegisterPeerResponse register_peer_response = 7;
164
-    PunchHoleRequest punch_hole_request = 8;
165
-    PunchHole punch_hole = 9;
166
-    PunchHoleSent punch_hole_sent = 10;
167
-    PunchHoleResponse punch_hole_response = 11;
168
-    FetchLocalAddr fetch_local_addr = 12;
169
-    LocalAddr local_addr = 13;
170
-    ConfigUpdate configure_update = 14;
171
-    RegisterPk register_pk = 15;
172
-    RegisterPkResponse register_pk_response = 16;
173
-    SoftwareUpdate software_update = 17;
174
-    RequestRelay request_relay = 18;
175
-    RelayResponse relay_response = 19;
176
-    TestNatRequest test_nat_request = 20;
177
-    TestNatResponse test_nat_response = 21;
178
-    PeerDiscovery peer_discovery = 22;
179
-    OnlineRequest online_request = 23;
180
-    OnlineResponse online_response = 24;
181
-  }
182
-}

+ 0 - 280
libs/hbb_common/src/bytes_codec.rs

@@ -1,280 +0,0 @@
1
-use bytes::{Buf, BufMut, Bytes, BytesMut};
2
-use std::io;
3
-use tokio_util::codec::{Decoder, Encoder};
4
-
5
-#[derive(Debug, Clone, Copy)]
6
-pub struct BytesCodec {
7
-    state: DecodeState,
8
-    raw: bool,
9
-    max_packet_length: usize,
10
-}
11
-
12
-#[derive(Debug, Clone, Copy)]
13
-enum DecodeState {
14
-    Head,
15
-    Data(usize),
16
-}
17
-
18
-impl Default for BytesCodec {
19
-    fn default() -> Self {
20
-        Self::new()
21
-    }
22
-}
23
-
24
-impl BytesCodec {
25
-    pub fn new() -> Self {
26
-        Self {
27
-            state: DecodeState::Head,
28
-            raw: false,
29
-            max_packet_length: usize::MAX,
30
-        }
31
-    }
32
-
33
-    pub fn set_raw(&mut self) {
34
-        self.raw = true;
35
-    }
36
-
37
-    pub fn set_max_packet_length(&mut self, n: usize) {
38
-        self.max_packet_length = n;
39
-    }
40
-
41
-    fn decode_head(&mut self, src: &mut BytesMut) -> io::Result<Option<usize>> {
42
-        if src.is_empty() {
43
-            return Ok(None);
44
-        }
45
-        let head_len = ((src[0] & 0x3) + 1) as usize;
46
-        if src.len() < head_len {
47
-            return Ok(None);
48
-        }
49
-        let mut n = src[0] as usize;
50
-        if head_len > 1 {
51
-            n |= (src[1] as usize) << 8;
52
-        }
53
-        if head_len > 2 {
54
-            n |= (src[2] as usize) << 16;
55
-        }
56
-        if head_len > 3 {
57
-            n |= (src[3] as usize) << 24;
58
-        }
59
-        n >>= 2;
60
-        if n > self.max_packet_length {
61
-            return Err(io::Error::new(io::ErrorKind::InvalidData, "Too big packet"));
62
-        }
63
-        src.advance(head_len);
64
-        src.reserve(n);
65
-        Ok(Some(n))
66
-    }
67
-
68
-    fn decode_data(&self, n: usize, src: &mut BytesMut) -> io::Result<Option<BytesMut>> {
69
-        if src.len() < n {
70
-            return Ok(None);
71
-        }
72
-        Ok(Some(src.split_to(n)))
73
-    }
74
-}
75
-
76
-impl Decoder for BytesCodec {
77
-    type Item = BytesMut;
78
-    type Error = io::Error;
79
-
80
-    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<BytesMut>, io::Error> {
81
-        if self.raw {
82
-            if !src.is_empty() {
83
-                let len = src.len();
84
-                return Ok(Some(src.split_to(len)));
85
-            } else {
86
-                return Ok(None);
87
-            }
88
-        }
89
-        let n = match self.state {
90
-            DecodeState::Head => match self.decode_head(src)? {
91
-                Some(n) => {
92
-                    self.state = DecodeState::Data(n);
93
-                    n
94
-                }
95
-                None => return Ok(None),
96
-            },
97
-            DecodeState::Data(n) => n,
98
-        };
99
-
100
-        match self.decode_data(n, src)? {
101
-            Some(data) => {
102
-                self.state = DecodeState::Head;
103
-                Ok(Some(data))
104
-            }
105
-            None => Ok(None),
106
-        }
107
-    }
108
-}
109
-
110
-impl Encoder<Bytes> for BytesCodec {
111
-    type Error = io::Error;
112
-
113
-    fn encode(&mut self, data: Bytes, buf: &mut BytesMut) -> Result<(), io::Error> {
114
-        if self.raw {
115
-            buf.reserve(data.len());
116
-            buf.put(data);
117
-            return Ok(());
118
-        }
119
-        if data.len() <= 0x3F {
120
-            buf.put_u8((data.len() << 2) as u8);
121
-        } else if data.len() <= 0x3FFF {
122
-            buf.put_u16_le((data.len() << 2) as u16 | 0x1);
123
-        } else if data.len() <= 0x3FFFFF {
124
-            let h = (data.len() << 2) as u32 | 0x2;
125
-            buf.put_u16_le((h & 0xFFFF) as u16);
126
-            buf.put_u8((h >> 16) as u8);
127
-        } else if data.len() <= 0x3FFFFFFF {
128
-            buf.put_u32_le((data.len() << 2) as u32 | 0x3);
129
-        } else {
130
-            return Err(io::Error::new(io::ErrorKind::InvalidInput, "Overflow"));
131
-        }
132
-        buf.extend(data);
133
-        Ok(())
134
-    }
135
-}
136
-
137
-#[cfg(test)]
138
-mod tests {
139
-    use super::*;
140
-    #[test]
141
-    fn test_codec1() {
142
-        let mut codec = BytesCodec::new();
143
-        let mut buf = BytesMut::new();
144
-        let mut bytes: Vec<u8> = Vec::new();
145
-        bytes.resize(0x3F, 1);
146
-        assert!(codec.encode(bytes.into(), &mut buf).is_ok());
147
-        let buf_saved = buf.clone();
148
-        assert_eq!(buf.len(), 0x3F + 1);
149
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
150
-            assert_eq!(res.len(), 0x3F);
151
-            assert_eq!(res[0], 1);
152
-        } else {
153
-            panic!();
154
-        }
155
-        let mut codec2 = BytesCodec::new();
156
-        let mut buf2 = BytesMut::new();
157
-        if let Ok(None) = codec2.decode(&mut buf2) {
158
-        } else {
159
-            panic!();
160
-        }
161
-        buf2.extend(&buf_saved[0..1]);
162
-        if let Ok(None) = codec2.decode(&mut buf2) {
163
-        } else {
164
-            panic!();
165
-        }
166
-        buf2.extend(&buf_saved[1..]);
167
-        if let Ok(Some(res)) = codec2.decode(&mut buf2) {
168
-            assert_eq!(res.len(), 0x3F);
169
-            assert_eq!(res[0], 1);
170
-        } else {
171
-            panic!();
172
-        }
173
-    }
174
-
175
-    #[test]
176
-    fn test_codec2() {
177
-        let mut codec = BytesCodec::new();
178
-        let mut buf = BytesMut::new();
179
-        let mut bytes: Vec<u8> = Vec::new();
180
-        assert!(codec.encode("".into(), &mut buf).is_ok());
181
-        assert_eq!(buf.len(), 1);
182
-        bytes.resize(0x3F + 1, 2);
183
-        assert!(codec.encode(bytes.into(), &mut buf).is_ok());
184
-        assert_eq!(buf.len(), 0x3F + 2 + 2);
185
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
186
-            assert_eq!(res.len(), 0);
187
-        } else {
188
-            panic!();
189
-        }
190
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
191
-            assert_eq!(res.len(), 0x3F + 1);
192
-            assert_eq!(res[0], 2);
193
-        } else {
194
-            panic!();
195
-        }
196
-    }
197
-
198
-    #[test]
199
-    fn test_codec3() {
200
-        let mut codec = BytesCodec::new();
201
-        let mut buf = BytesMut::new();
202
-        let mut bytes: Vec<u8> = Vec::new();
203
-        bytes.resize(0x3F - 1, 3);
204
-        assert!(codec.encode(bytes.into(), &mut buf).is_ok());
205
-        assert_eq!(buf.len(), 0x3F + 1 - 1);
206
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
207
-            assert_eq!(res.len(), 0x3F - 1);
208
-            assert_eq!(res[0], 3);
209
-        } else {
210
-            panic!();
211
-        }
212
-    }
213
-    #[test]
214
-    fn test_codec4() {
215
-        let mut codec = BytesCodec::new();
216
-        let mut buf = BytesMut::new();
217
-        let mut bytes: Vec<u8> = Vec::new();
218
-        bytes.resize(0x3FFF, 4);
219
-        assert!(codec.encode(bytes.into(), &mut buf).is_ok());
220
-        assert_eq!(buf.len(), 0x3FFF + 2);
221
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
222
-            assert_eq!(res.len(), 0x3FFF);
223
-            assert_eq!(res[0], 4);
224
-        } else {
225
-            panic!();
226
-        }
227
-    }
228
-
229
-    #[test]
230
-    fn test_codec5() {
231
-        let mut codec = BytesCodec::new();
232
-        let mut buf = BytesMut::new();
233
-        let mut bytes: Vec<u8> = Vec::new();
234
-        bytes.resize(0x3FFFFF, 5);
235
-        assert!(codec.encode(bytes.into(), &mut buf).is_ok());
236
-        assert_eq!(buf.len(), 0x3FFFFF + 3);
237
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
238
-            assert_eq!(res.len(), 0x3FFFFF);
239
-            assert_eq!(res[0], 5);
240
-        } else {
241
-            panic!();
242
-        }
243
-    }
244
-
245
-    #[test]
246
-    fn test_codec6() {
247
-        let mut codec = BytesCodec::new();
248
-        let mut buf = BytesMut::new();
249
-        let mut bytes: Vec<u8> = Vec::new();
250
-        bytes.resize(0x3FFFFF + 1, 6);
251
-        assert!(codec.encode(bytes.into(), &mut buf).is_ok());
252
-        let buf_saved = buf.clone();
253
-        assert_eq!(buf.len(), 0x3FFFFF + 4 + 1);
254
-        if let Ok(Some(res)) = codec.decode(&mut buf) {
255
-            assert_eq!(res.len(), 0x3FFFFF + 1);
256
-            assert_eq!(res[0], 6);
257
-        } else {
258
-            panic!();
259
-        }
260
-        let mut codec2 = BytesCodec::new();
261
-        let mut buf2 = BytesMut::new();
262
-        buf2.extend(&buf_saved[0..1]);
263
-        if let Ok(None) = codec2.decode(&mut buf2) {
264
-        } else {
265
-            panic!();
266
-        }
267
-        buf2.extend(&buf_saved[1..6]);
268
-        if let Ok(None) = codec2.decode(&mut buf2) {
269
-        } else {
270
-            panic!();
271
-        }
272
-        buf2.extend(&buf_saved[6..]);
273
-        if let Ok(Some(res)) = codec2.decode(&mut buf2) {
274
-            assert_eq!(res.len(), 0x3FFFFF + 1);
275
-            assert_eq!(res[0], 6);
276
-        } else {
277
-            panic!();
278
-        }
279
-    }
280
-}

+ 0 - 45
libs/hbb_common/src/compress.rs

@@ -1,45 +0,0 @@
1
-use std::cell::RefCell;
2
-use zstd::block::{Compressor, Decompressor};
3
-
4
-thread_local! {
5
-    static COMPRESSOR: RefCell<Compressor> = RefCell::new(Compressor::new());
6
-    static DECOMPRESSOR: RefCell<Decompressor> = RefCell::new(Decompressor::new());
7
-}
8
-
9
-/// The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),
10
-/// which is currently 22. Levels >= 20
11
-/// Default level is ZSTD_CLEVEL_DEFAULT==3.
12
-/// value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT
13
-pub fn compress(data: &[u8], level: i32) -> Vec<u8> {
14
-    let mut out = Vec::new();
15
-    COMPRESSOR.with(|c| {
16
-        if let Ok(mut c) = c.try_borrow_mut() {
17
-            match c.compress(data, level) {
18
-                Ok(res) => out = res,
19
-                Err(err) => {
20
-                    crate::log::debug!("Failed to compress: {}", err);
21
-                }
22
-            }
23
-        }
24
-    });
25
-    out
26
-}
27
-
28
-pub fn decompress(data: &[u8]) -> Vec<u8> {
29
-    let mut out = Vec::new();
30
-    DECOMPRESSOR.with(|d| {
31
-        if let Ok(mut d) = d.try_borrow_mut() {
32
-            const MAX: usize = 1024 * 1024 * 64;
33
-            const MIN: usize = 1024 * 1024;
34
-            let mut n = 30 * data.len();
35
-            n = n.clamp(MIN, MAX);
36
-            match d.decompress(data, n) {
37
-                Ok(res) => out = res,
38
-                Err(err) => {
39
-                    crate::log::debug!("Failed to decompress: {}", err);
40
-                }
41
-            }
42
-        }
43
-    });
44
-    out
45
-}

Разница между файлами не показана из-за своего большого размера
+ 0 - 1348
libs/hbb_common/src/config.rs


+ 0 - 839
libs/hbb_common/src/fs.rs

@@ -1,839 +0,0 @@
1
-#[cfg(windows)]
2
-use std::os::windows::prelude::*;
3
-use std::path::{Path, PathBuf};
4
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
5
-
6
-use serde_derive::{Deserialize, Serialize};
7
-use tokio::{fs::File, io::*};
8
-
9
-use crate::{bail, get_version_number, message_proto::*, ResultType, Stream};
10
-// https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html
11
-use crate::{
12
-    compress::{compress, decompress},
13
-    config::{Config, COMPRESS_LEVEL},
14
-};
15
-
16
-pub fn read_dir(path: &Path, include_hidden: bool) -> ResultType<FileDirectory> {
17
-    let mut dir = FileDirectory {
18
-        path: get_string(path),
19
-        ..Default::default()
20
-    };
21
-    #[cfg(windows)]
22
-    if "/" == &get_string(path) {
23
-        let drives = unsafe { winapi::um::fileapi::GetLogicalDrives() };
24
-        for i in 0..32 {
25
-            if drives & (1 << i) != 0 {
26
-                let name = format!(
27
-                    "{}:",
28
-                    std::char::from_u32('A' as u32 + i as u32).unwrap_or('A')
29
-                );
30
-                dir.entries.push(FileEntry {
31
-                    name,
32
-                    entry_type: FileType::DirDrive.into(),
33
-                    ..Default::default()
34
-                });
35
-            }
36
-        }
37
-        return Ok(dir);
38
-    }
39
-    for entry in path.read_dir()?.flatten() {
40
-        let p = entry.path();
41
-        let name = p
42
-            .file_name()
43
-            .map(|p| p.to_str().unwrap_or(""))
44
-            .unwrap_or("")
45
-            .to_owned();
46
-        if name.is_empty() {
47
-            continue;
48
-        }
49
-        let mut is_hidden = false;
50
-        let meta;
51
-        if let Ok(tmp) = std::fs::symlink_metadata(&p) {
52
-            meta = tmp;
53
-        } else {
54
-            continue;
55
-        }
56
-        // docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
57
-        #[cfg(windows)]
58
-        if meta.file_attributes() & 0x2 != 0 {
59
-            is_hidden = true;
60
-        }
61
-        #[cfg(not(windows))]
62
-        if name.find('.').unwrap_or(usize::MAX) == 0 {
63
-            is_hidden = true;
64
-        }
65
-        if is_hidden && !include_hidden {
66
-            continue;
67
-        }
68
-        let (entry_type, size) = {
69
-            if p.is_dir() {
70
-                if meta.file_type().is_symlink() {
71
-                    (FileType::DirLink.into(), 0)
72
-                } else {
73
-                    (FileType::Dir.into(), 0)
74
-                }
75
-            } else if meta.file_type().is_symlink() {
76
-                (FileType::FileLink.into(), 0)
77
-            } else {
78
-                (FileType::File.into(), meta.len())
79
-            }
80
-        };
81
-        let modified_time = meta
82
-            .modified()
83
-            .map(|x| {
84
-                x.duration_since(std::time::SystemTime::UNIX_EPOCH)
85
-                    .map(|x| x.as_secs())
86
-                    .unwrap_or(0)
87
-            })
88
-            .unwrap_or(0);
89
-        dir.entries.push(FileEntry {
90
-            name: get_file_name(&p),
91
-            entry_type,
92
-            is_hidden,
93
-            size,
94
-            modified_time,
95
-            ..Default::default()
96
-        });
97
-    }
98
-    Ok(dir)
99
-}
100
-
101
-#[inline]
102
-pub fn get_file_name(p: &Path) -> String {
103
-    p.file_name()
104
-        .map(|p| p.to_str().unwrap_or(""))
105
-        .unwrap_or("")
106
-        .to_owned()
107
-}
108
-
109
-#[inline]
110
-pub fn get_string(path: &Path) -> String {
111
-    path.to_str().unwrap_or("").to_owned()
112
-}
113
-
114
-#[inline]
115
-pub fn get_path(path: &str) -> PathBuf {
116
-    Path::new(path).to_path_buf()
117
-}
118
-
119
-#[inline]
120
-pub fn get_home_as_string() -> String {
121
-    get_string(&Config::get_home())
122
-}
123
-
124
-fn read_dir_recursive(
125
-    path: &PathBuf,
126
-    prefix: &Path,
127
-    include_hidden: bool,
128
-) -> ResultType<Vec<FileEntry>> {
129
-    let mut files = Vec::new();
130
-    if path.is_dir() {
131
-        // to-do: symbol link handling, cp the link rather than the content
132
-        // to-do: file mode, for unix
133
-        let fd = read_dir(path, include_hidden)?;
134
-        for entry in fd.entries.iter() {
135
-            match entry.entry_type.enum_value() {
136
-                Ok(FileType::File) => {
137
-                    let mut entry = entry.clone();
138
-                    entry.name = get_string(&prefix.join(entry.name));
139
-                    files.push(entry);
140
-                }
141
-                Ok(FileType::Dir) => {
142
-                    if let Ok(mut tmp) = read_dir_recursive(
143
-                        &path.join(&entry.name),
144
-                        &prefix.join(&entry.name),
145
-                        include_hidden,
146
-                    ) {
147
-                        for entry in tmp.drain(0..) {
148
-                            files.push(entry);
149
-                        }
150
-                    }
151
-                }
152
-                _ => {}
153
-            }
154
-        }
155
-        Ok(files)
156
-    } else if path.is_file() {
157
-        let (size, modified_time) = if let Ok(meta) = std::fs::metadata(path) {
158
-            (
159
-                meta.len(),
160
-                meta.modified()
161
-                    .map(|x| {
162
-                        x.duration_since(std::time::SystemTime::UNIX_EPOCH)
163
-                            .map(|x| x.as_secs())
164
-                            .unwrap_or(0)
165
-                    })
166
-                    .unwrap_or(0),
167
-            )
168
-        } else {
169
-            (0, 0)
170
-        };
171
-        files.push(FileEntry {
172
-            entry_type: FileType::File.into(),
173
-            size,
174
-            modified_time,
175
-            ..Default::default()
176
-        });
177
-        Ok(files)
178
-    } else {
179
-        bail!("Not exists");
180
-    }
181
-}
182
-
183
-pub fn get_recursive_files(path: &str, include_hidden: bool) -> ResultType<Vec<FileEntry>> {
184
-    read_dir_recursive(&get_path(path), &get_path(""), include_hidden)
185
-}
186
-
187
-#[inline]
188
-pub fn is_file_exists(file_path: &str) -> bool {
189
-    return Path::new(file_path).exists();
190
-}
191
-
192
-#[inline]
193
-pub fn can_enable_overwrite_detection(version: i64) -> bool {
194
-    version >= get_version_number("1.1.10")
195
-}
196
-
197
-#[derive(Default)]
198
-pub struct TransferJob {
199
-    pub id: i32,
200
-    pub remote: String,
201
-    pub path: PathBuf,
202
-    pub show_hidden: bool,
203
-    pub is_remote: bool,
204
-    pub is_last_job: bool,
205
-    pub file_num: i32,
206
-    pub files: Vec<FileEntry>,
207
-
208
-    file: Option<File>,
209
-    total_size: u64,
210
-    finished_size: u64,
211
-    transferred: u64,
212
-    enable_overwrite_detection: bool,
213
-    file_confirmed: bool,
214
-    // indicating the last file is skipped
215
-    file_skipped: bool,
216
-    file_is_waiting: bool,
217
-    default_overwrite_strategy: Option<bool>,
218
-}
219
-
220
-#[derive(Debug, Default, Serialize, Deserialize, Clone)]
221
-pub struct TransferJobMeta {
222
-    #[serde(default)]
223
-    pub id: i32,
224
-    #[serde(default)]
225
-    pub remote: String,
226
-    #[serde(default)]
227
-    pub to: String,
228
-    #[serde(default)]
229
-    pub show_hidden: bool,
230
-    #[serde(default)]
231
-    pub file_num: i32,
232
-    #[serde(default)]
233
-    pub is_remote: bool,
234
-}
235
-
236
-#[derive(Debug, Default, Serialize, Deserialize, Clone)]
237
-pub struct RemoveJobMeta {
238
-    #[serde(default)]
239
-    pub path: String,
240
-    #[serde(default)]
241
-    pub is_remote: bool,
242
-    #[serde(default)]
243
-    pub no_confirm: bool,
244
-}
245
-
246
-#[inline]
247
-fn get_ext(name: &str) -> &str {
248
-    if let Some(i) = name.rfind('.') {
249
-        return &name[i + 1..];
250
-    }
251
-    ""
252
-}
253
-
254
-#[inline]
255
-fn is_compressed_file(name: &str) -> bool {
256
-    let ext = get_ext(name);
257
-    ext == "xz"
258
-        || ext == "gz"
259
-        || ext == "zip"
260
-        || ext == "7z"
261
-        || ext == "rar"
262
-        || ext == "bz2"
263
-        || ext == "tgz"
264
-        || ext == "png"
265
-        || ext == "jpg"
266
-}
267
-
268
-impl TransferJob {
269
-    #[allow(clippy::too_many_arguments)]
270
-    pub fn new_write(
271
-        id: i32,
272
-        remote: String,
273
-        path: String,
274
-        file_num: i32,
275
-        show_hidden: bool,
276
-        is_remote: bool,
277
-        files: Vec<FileEntry>,
278
-        enable_overwrite_detection: bool,
279
-    ) -> Self {
280
-        log::info!("new write {}", path);
281
-        let total_size = files.iter().map(|x| x.size).sum();
282
-        Self {
283
-            id,
284
-            remote,
285
-            path: get_path(&path),
286
-            file_num,
287
-            show_hidden,
288
-            is_remote,
289
-            files,
290
-            total_size,
291
-            enable_overwrite_detection,
292
-            ..Default::default()
293
-        }
294
-    }
295
-
296
-    pub fn new_read(
297
-        id: i32,
298
-        remote: String,
299
-        path: String,
300
-        file_num: i32,
301
-        show_hidden: bool,
302
-        is_remote: bool,
303
-        enable_overwrite_detection: bool,
304
-    ) -> ResultType<Self> {
305
-        log::info!("new read {}", path);
306
-        let files = get_recursive_files(&path, show_hidden)?;
307
-        let total_size = files.iter().map(|x| x.size).sum();
308
-        Ok(Self {
309
-            id,
310
-            remote,
311
-            path: get_path(&path),
312
-            file_num,
313
-            show_hidden,
314
-            is_remote,
315
-            files,
316
-            total_size,
317
-            enable_overwrite_detection,
318
-            ..Default::default()
319
-        })
320
-    }
321
-
322
-    #[inline]
323
-    pub fn files(&self) -> &Vec<FileEntry> {
324
-        &self.files
325
-    }
326
-
327
-    #[inline]
328
-    pub fn set_files(&mut self, files: Vec<FileEntry>) {
329
-        self.files = files;
330
-    }
331
-
332
-    #[inline]
333
-    pub fn id(&self) -> i32 {
334
-        self.id
335
-    }
336
-
337
-    #[inline]
338
-    pub fn total_size(&self) -> u64 {
339
-        self.total_size
340
-    }
341
-
342
-    #[inline]
343
-    pub fn finished_size(&self) -> u64 {
344
-        self.finished_size
345
-    }
346
-
347
-    #[inline]
348
-    pub fn transferred(&self) -> u64 {
349
-        self.transferred
350
-    }
351
-
352
-    #[inline]
353
-    pub fn file_num(&self) -> i32 {
354
-        self.file_num
355
-    }
356
-
357
-    pub fn modify_time(&self) {
358
-        let file_num = self.file_num as usize;
359
-        if file_num < self.files.len() {
360
-            let entry = &self.files[file_num];
361
-            let path = self.join(&entry.name);
362
-            let download_path = format!("{}.download", get_string(&path));
363
-            std::fs::rename(download_path, &path).ok();
364
-            filetime::set_file_mtime(
365
-                &path,
366
-                filetime::FileTime::from_unix_time(entry.modified_time as _, 0),
367
-            )
368
-            .ok();
369
-        }
370
-    }
371
-
372
-    pub fn remove_download_file(&self) {
373
-        let file_num = self.file_num as usize;
374
-        if file_num < self.files.len() {
375
-            let entry = &self.files[file_num];
376
-            let path = self.join(&entry.name);
377
-            let download_path = format!("{}.download", get_string(&path));
378
-            std::fs::remove_file(download_path).ok();
379
-        }
380
-    }
381
-
382
-    pub async fn write(&mut self, block: FileTransferBlock) -> ResultType<()> {
383
-        if block.id != self.id {
384
-            bail!("Wrong id");
385
-        }
386
-        let file_num = block.file_num as usize;
387
-        if file_num >= self.files.len() {
388
-            bail!("Wrong file number");
389
-        }
390
-        if file_num != self.file_num as usize || self.file.is_none() {
391
-            self.modify_time();
392
-            if let Some(file) = self.file.as_mut() {
393
-                file.sync_all().await?;
394
-            }
395
-            self.file_num = block.file_num;
396
-            let entry = &self.files[file_num];
397
-            let path = self.join(&entry.name);
398
-            if let Some(p) = path.parent() {
399
-                std::fs::create_dir_all(p).ok();
400
-            }
401
-            let path = format!("{}.download", get_string(&path));
402
-            self.file = Some(File::create(&path).await?);
403
-        }
404
-        if block.compressed {
405
-            let tmp = decompress(&block.data);
406
-            self.file.as_mut().unwrap().write_all(&tmp).await?;
407
-            self.finished_size += tmp.len() as u64;
408
-        } else {
409
-            self.file.as_mut().unwrap().write_all(&block.data).await?;
410
-            self.finished_size += block.data.len() as u64;
411
-        }
412
-        self.transferred += block.data.len() as u64;
413
-        Ok(())
414
-    }
415
-
416
-    #[inline]
417
-    pub fn join(&self, name: &str) -> PathBuf {
418
-        if name.is_empty() {
419
-            self.path.clone()
420
-        } else {
421
-            self.path.join(name)
422
-        }
423
-    }
424
-
425
-    pub async fn read(&mut self, stream: &mut Stream) -> ResultType<Option<FileTransferBlock>> {
426
-        let file_num = self.file_num as usize;
427
-        if file_num >= self.files.len() {
428
-            self.file.take();
429
-            return Ok(None);
430
-        }
431
-        let name = &self.files[file_num].name;
432
-        if self.file.is_none() {
433
-            match File::open(self.join(name)).await {
434
-                Ok(file) => {
435
-                    self.file = Some(file);
436
-                    self.file_confirmed = false;
437
-                    self.file_is_waiting = false;
438
-                }
439
-                Err(err) => {
440
-                    self.file_num += 1;
441
-                    self.file_confirmed = false;
442
-                    self.file_is_waiting = false;
443
-                    return Err(err.into());
444
-                }
445
-            }
446
-        }
447
-        if self.enable_overwrite_detection && !self.file_confirmed() {
448
-            if !self.file_is_waiting() {
449
-                self.send_current_digest(stream).await?;
450
-                self.set_file_is_waiting(true);
451
-            }
452
-            return Ok(None);
453
-        }
454
-        const BUF_SIZE: usize = 128 * 1024;
455
-        let mut buf: Vec<u8> = vec![0; BUF_SIZE];
456
-        let mut compressed = false;
457
-        let mut offset: usize = 0;
458
-        loop {
459
-            match self.file.as_mut().unwrap().read(&mut buf[offset..]).await {
460
-                Err(err) => {
461
-                    self.file_num += 1;
462
-                    self.file = None;
463
-                    self.file_confirmed = false;
464
-                    self.file_is_waiting = false;
465
-                    return Err(err.into());
466
-                }
467
-                Ok(n) => {
468
-                    offset += n;
469
-                    if n == 0 || offset == BUF_SIZE {
470
-                        break;
471
-                    }
472
-                }
473
-            }
474
-        }
475
-        unsafe { buf.set_len(offset) };
476
-        if offset == 0 {
477
-            self.file_num += 1;
478
-            self.file = None;
479
-            self.file_confirmed = false;
480
-            self.file_is_waiting = false;
481
-        } else {
482
-            self.finished_size += offset as u64;
483
-            if !is_compressed_file(name) {
484
-                let tmp = compress(&buf, COMPRESS_LEVEL);
485
-                if tmp.len() < buf.len() {
486
-                    buf = tmp;
487
-                    compressed = true;
488
-                }
489
-            }
490
-            self.transferred += buf.len() as u64;
491
-        }
492
-        Ok(Some(FileTransferBlock {
493
-            id: self.id,
494
-            file_num: file_num as _,
495
-            data: buf.into(),
496
-            compressed,
497
-            ..Default::default()
498
-        }))
499
-    }
500
-
501
-    async fn send_current_digest(&mut self, stream: &mut Stream) -> ResultType<()> {
502
-        let mut msg = Message::new();
503
-        let mut resp = FileResponse::new();
504
-        let meta = self.file.as_ref().unwrap().metadata().await?;
505
-        let last_modified = meta
506
-            .modified()?
507
-            .duration_since(SystemTime::UNIX_EPOCH)?
508
-            .as_secs();
509
-        resp.set_digest(FileTransferDigest {
510
-            id: self.id,
511
-            file_num: self.file_num,
512
-            last_modified,
513
-            file_size: meta.len(),
514
-            ..Default::default()
515
-        });
516
-        msg.set_file_response(resp);
517
-        stream.send(&msg).await?;
518
-        log::info!(
519
-            "id: {}, file_num:{}, digest message is sent. waiting for confirm. msg: {:?}",
520
-            self.id,
521
-            self.file_num,
522
-            msg
523
-        );
524
-        Ok(())
525
-    }
526
-
527
-    pub fn set_overwrite_strategy(&mut self, overwrite_strategy: Option<bool>) {
528
-        self.default_overwrite_strategy = overwrite_strategy;
529
-    }
530
-
531
-    pub fn default_overwrite_strategy(&self) -> Option<bool> {
532
-        self.default_overwrite_strategy
533
-    }
534
-
535
-    pub fn set_file_confirmed(&mut self, file_confirmed: bool) {
536
-        log::info!("id: {}, file_confirmed: {}", self.id, file_confirmed);
537
-        self.file_confirmed = file_confirmed;
538
-        self.file_skipped = false;
539
-    }
540
-
541
-    pub fn set_file_is_waiting(&mut self, file_is_waiting: bool) {
542
-        self.file_is_waiting = file_is_waiting;
543
-    }
544
-
545
-    #[inline]
546
-    pub fn file_is_waiting(&self) -> bool {
547
-        self.file_is_waiting
548
-    }
549
-
550
-    #[inline]
551
-    pub fn file_confirmed(&self) -> bool {
552
-        self.file_confirmed
553
-    }
554
-
555
-    /// Indicating whether the last file is skipped
556
-    #[inline]
557
-    pub fn file_skipped(&self) -> bool {
558
-        self.file_skipped
559
-    }
560
-
561
-    /// Indicating whether the whole task is skipped
562
-    #[inline]
563
-    pub fn job_skipped(&self) -> bool {
564
-        self.file_skipped() && self.files.len() == 1
565
-    }
566
-
567
-    /// Check whether the job is completed after `read` returns `None`
568
-    /// This is a helper function which gives additional lifecycle when the job reads `None`.
569
-    /// If returns `true`, it means we can delete the job automatically. `False` otherwise.
570
-    ///
571
-    /// [`Note`]
572
-    /// Conditions:
573
-    /// 1. Files are not waiting for confirmation by peers.
574
-    #[inline]
575
-    pub fn job_completed(&self) -> bool {
576
-        // has no error, Condition 2
577
-        !self.enable_overwrite_detection || (!self.file_confirmed && !self.file_is_waiting)
578
-    }
579
-
580
-    /// Get job error message, useful for getting status when job had finished
581
-    pub fn job_error(&self) -> Option<String> {
582
-        if self.job_skipped() {
583
-            return Some("skipped".to_string());
584
-        }
585
-        None
586
-    }
587
-
588
-    pub fn set_file_skipped(&mut self) -> bool {
589
-        log::debug!("skip file {} in job {}", self.file_num, self.id);
590
-        self.file.take();
591
-        self.set_file_confirmed(false);
592
-        self.set_file_is_waiting(false);
593
-        self.file_num += 1;
594
-        self.file_skipped = true;
595
-        true
596
-    }
597
-
598
-    pub fn confirm(&mut self, r: &FileTransferSendConfirmRequest) -> bool {
599
-        if self.file_num() != r.file_num {
600
-            log::info!("file num truncated, ignoring");
601
-        } else {
602
-            match r.union {
603
-                Some(file_transfer_send_confirm_request::Union::Skip(s)) => {
604
-                    if s {
605
-                        self.set_file_skipped();
606
-                    } else {
607
-                        self.set_file_confirmed(true);
608
-                    }
609
-                }
610
-                Some(file_transfer_send_confirm_request::Union::OffsetBlk(_offset)) => {
611
-                    self.set_file_confirmed(true);
612
-                }
613
-                _ => {}
614
-            }
615
-        }
616
-        true
617
-    }
618
-
619
-    #[inline]
620
-    pub fn gen_meta(&self) -> TransferJobMeta {
621
-        TransferJobMeta {
622
-            id: self.id,
623
-            remote: self.remote.to_string(),
624
-            to: self.path.to_string_lossy().to_string(),
625
-            file_num: self.file_num,
626
-            show_hidden: self.show_hidden,
627
-            is_remote: self.is_remote,
628
-        }
629
-    }
630
-}
631
-
632
-#[inline]
633
-pub fn new_error<T: std::string::ToString>(id: i32, err: T, file_num: i32) -> Message {
634
-    let mut resp = FileResponse::new();
635
-    resp.set_error(FileTransferError {
636
-        id,
637
-        error: err.to_string(),
638
-        file_num,
639
-        ..Default::default()
640
-    });
641
-    let mut msg_out = Message::new();
642
-    msg_out.set_file_response(resp);
643
-    msg_out
644
-}
645
-
646
-#[inline]
647
-pub fn new_dir(id: i32, path: String, files: Vec<FileEntry>) -> Message {
648
-    let mut resp = FileResponse::new();
649
-    resp.set_dir(FileDirectory {
650
-        id,
651
-        path,
652
-        entries: files,
653
-        ..Default::default()
654
-    });
655
-    let mut msg_out = Message::new();
656
-    msg_out.set_file_response(resp);
657
-    msg_out
658
-}
659
-
660
-#[inline]
661
-pub fn new_block(block: FileTransferBlock) -> Message {
662
-    let mut resp = FileResponse::new();
663
-    resp.set_block(block);
664
-    let mut msg_out = Message::new();
665
-    msg_out.set_file_response(resp);
666
-    msg_out
667
-}
668
-
669
-#[inline]
670
-pub fn new_send_confirm(r: FileTransferSendConfirmRequest) -> Message {
671
-    let mut msg_out = Message::new();
672
-    let mut action = FileAction::new();
673
-    action.set_send_confirm(r);
674
-    msg_out.set_file_action(action);
675
-    msg_out
676
-}
677
-
678
-#[inline]
679
-pub fn new_receive(id: i32, path: String, file_num: i32, files: Vec<FileEntry>) -> Message {
680
-    let mut action = FileAction::new();
681
-    action.set_receive(FileTransferReceiveRequest {
682
-        id,
683
-        path,
684
-        files,
685
-        file_num,
686
-        ..Default::default()
687
-    });
688
-    let mut msg_out = Message::new();
689
-    msg_out.set_file_action(action);
690
-    msg_out
691
-}
692
-
693
-#[inline]
694
-pub fn new_send(id: i32, path: String, file_num: i32, include_hidden: bool) -> Message {
695
-    log::info!("new send: {},id : {}", path, id);
696
-    let mut action = FileAction::new();
697
-    action.set_send(FileTransferSendRequest {
698
-        id,
699
-        path,
700
-        include_hidden,
701
-        file_num,
702
-        ..Default::default()
703
-    });
704
-    let mut msg_out = Message::new();
705
-    msg_out.set_file_action(action);
706
-    msg_out
707
-}
708
-
709
-#[inline]
710
-pub fn new_done(id: i32, file_num: i32) -> Message {
711
-    let mut resp = FileResponse::new();
712
-    resp.set_done(FileTransferDone {
713
-        id,
714
-        file_num,
715
-        ..Default::default()
716
-    });
717
-    let mut msg_out = Message::new();
718
-    msg_out.set_file_response(resp);
719
-    msg_out
720
-}
721
-
722
-#[inline]
723
-pub fn remove_job(id: i32, jobs: &mut Vec<TransferJob>) {
724
-    *jobs = jobs.drain(0..).filter(|x| x.id() != id).collect();
725
-}
726
-
727
-#[inline]
728
-pub fn get_job(id: i32, jobs: &mut [TransferJob]) -> Option<&mut TransferJob> {
729
-    jobs.iter_mut().find(|x| x.id() == id)
730
-}
731
-
732
-pub async fn handle_read_jobs(
733
-    jobs: &mut Vec<TransferJob>,
734
-    stream: &mut crate::Stream,
735
-) -> ResultType<()> {
736
-    let mut finished = Vec::new();
737
-    for job in jobs.iter_mut() {
738
-        if job.is_last_job {
739
-            continue;
740
-        }
741
-        match job.read(stream).await {
742
-            Err(err) => {
743
-                stream
744
-                    .send(&new_error(job.id(), err, job.file_num()))
745
-                    .await?;
746
-            }
747
-            Ok(Some(block)) => {
748
-                stream.send(&new_block(block)).await?;
749
-            }
750
-            Ok(None) => {
751
-                if job.job_completed() {
752
-                    finished.push(job.id());
753
-                    let err = job.job_error();
754
-                    if err.is_some() {
755
-                        stream
756
-                            .send(&new_error(job.id(), err.unwrap(), job.file_num()))
757
-                            .await?;
758
-                    } else {
759
-                        stream.send(&new_done(job.id(), job.file_num())).await?;
760
-                    }
761
-                } else {
762
-                    // waiting confirmation.
763
-                }
764
-            }
765
-        }
766
-    }
767
-    for id in finished {
768
-        remove_job(id, jobs);
769
-    }
770
-    Ok(())
771
-}
772
-
773
-pub fn remove_all_empty_dir(path: &PathBuf) -> ResultType<()> {
774
-    let fd = read_dir(path, true)?;
775
-    for entry in fd.entries.iter() {
776
-        match entry.entry_type.enum_value() {
777
-            Ok(FileType::Dir) => {
778
-                remove_all_empty_dir(&path.join(&entry.name)).ok();
779
-            }
780
-            Ok(FileType::DirLink) | Ok(FileType::FileLink) => {
781
-                std::fs::remove_file(path.join(&entry.name)).ok();
782
-            }
783
-            _ => {}
784
-        }
785
-    }
786
-    std::fs::remove_dir(path).ok();
787
-    Ok(())
788
-}
789
-
790
-#[inline]
791
-pub fn remove_file(file: &str) -> ResultType<()> {
792
-    std::fs::remove_file(get_path(file))?;
793
-    Ok(())
794
-}
795
-
796
-#[inline]
797
-pub fn create_dir(dir: &str) -> ResultType<()> {
798
-    std::fs::create_dir_all(get_path(dir))?;
799
-    Ok(())
800
-}
801
-
802
-#[inline]
803
-pub fn transform_windows_path(entries: &mut Vec<FileEntry>) {
804
-    for entry in entries {
805
-        entry.name = entry.name.replace('\\', "/");
806
-    }
807
-}
808
-
809
-pub enum DigestCheckResult {
810
-    IsSame,
811
-    NeedConfirm(FileTransferDigest),
812
-    NoSuchFile,
813
-}
814
-
815
-#[inline]
816
-pub fn is_write_need_confirmation(
817
-    file_path: &str,
818
-    digest: &FileTransferDigest,
819
-) -> ResultType<DigestCheckResult> {
820
-    let path = Path::new(file_path);
821
-    if path.exists() && path.is_file() {
822
-        let metadata = std::fs::metadata(path)?;
823
-        let modified_time = metadata.modified()?;
824
-        let remote_mt = Duration::from_secs(digest.last_modified);
825
-        let local_mt = modified_time.duration_since(UNIX_EPOCH)?;
826
-        if remote_mt == local_mt && digest.file_size == metadata.len() {
827
-            return Ok(DigestCheckResult::IsSame);
828
-        }
829
-        Ok(DigestCheckResult::NeedConfirm(FileTransferDigest {
830
-            id: digest.id,
831
-            file_num: digest.file_num,
832
-            last_modified: local_mt.as_secs(),
833
-            file_size: metadata.len(),
834
-            ..Default::default()
835
-        }))
836
-    } else {
837
-        Ok(DigestCheckResult::NoSuchFile)
838
-    }
839
-}

+ 0 - 39
libs/hbb_common/src/keyboard.rs

@@ -1,39 +0,0 @@
1
-use std::{fmt, slice::Iter, str::FromStr};
2
-
3
-use crate::protos::message::KeyboardMode;
4
-
5
-impl fmt::Display for KeyboardMode {
6
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7
-        match self {
8
-            KeyboardMode::Legacy => write!(f, "legacy"),
9
-            KeyboardMode::Map => write!(f, "map"),
10
-            KeyboardMode::Translate => write!(f, "translate"),
11
-            KeyboardMode::Auto => write!(f, "auto"),
12
-        }
13
-    }
14
-}
15
-
16
-impl FromStr for KeyboardMode {
17
-    type Err = ();
18
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
19
-        match s {
20
-            "legacy" => Ok(KeyboardMode::Legacy),
21
-            "map" => Ok(KeyboardMode::Map),
22
-            "translate" => Ok(KeyboardMode::Translate),
23
-            "auto" => Ok(KeyboardMode::Auto),
24
-            _ => Err(()),
25
-        }
26
-    }
27
-}
28
-
29
-impl KeyboardMode {
30
-    pub fn iter() -> Iter<'static, KeyboardMode> {
31
-        const KEYBOARD_MODES: [KeyboardMode; 4] = [
32
-            KeyboardMode::Legacy,
33
-            KeyboardMode::Map,
34
-            KeyboardMode::Translate,
35
-            KeyboardMode::Auto,
36
-        ];
37
-        KEYBOARD_MODES.iter()
38
-    }
39
-}

+ 0 - 390
libs/hbb_common/src/lib.rs

@@ -1,390 +0,0 @@
1
-pub mod compress;
2
-pub mod protos;
3
-pub use bytes;
4
-use config::Config;
5
-pub use futures;
6
-pub use protobuf;
7
-pub use protos::message as message_proto;
8
-pub use protos::rendezvous as rendezvous_proto;
9
-use std::{
10
-    fs::File,
11
-    io::{self, BufRead},
12
-    net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
13
-    path::Path,
14
-    time::{self, SystemTime, UNIX_EPOCH},
15
-};
16
-pub use tokio;
17
-pub use tokio_util;
18
-pub mod socket_client;
19
-pub mod tcp;
20
-pub mod udp;
21
-pub use env_logger;
22
-pub use log;
23
-pub mod bytes_codec;
24
-#[cfg(feature = "quic")]
25
-pub mod quic;
26
-pub use anyhow::{self, bail};
27
-pub use futures_util;
28
-pub mod config;
29
-pub mod fs;
30
-pub use lazy_static;
31
-#[cfg(not(any(target_os = "android", target_os = "ios")))]
32
-pub use mac_address;
33
-pub use rand;
34
-pub use regex;
35
-pub use sodiumoxide;
36
-pub use tokio_socks;
37
-pub use tokio_socks::IntoTargetAddr;
38
-pub use tokio_socks::TargetAddr;
39
-pub mod password_security;
40
-pub use chrono;
41
-pub use directories_next;
42
-pub mod keyboard;
43
-
44
-#[cfg(feature = "quic")]
45
-pub type Stream = quic::Connection;
46
-#[cfg(not(feature = "quic"))]
47
-pub type Stream = tcp::FramedStream;
48
-
49
-#[inline]
50
-pub async fn sleep(sec: f32) {
51
-    tokio::time::sleep(time::Duration::from_secs_f32(sec)).await;
52
-}
53
-
54
-#[macro_export]
55
-macro_rules! allow_err {
56
-    ($e:expr) => {
57
-        if let Err(err) = $e {
58
-            log::debug!(
59
-                "{:?}, {}:{}:{}:{}",
60
-                err,
61
-                module_path!(),
62
-                file!(),
63
-                line!(),
64
-                column!()
65
-            );
66
-        } else {
67
-        }
68
-    };
69
-
70
-    ($e:expr, $($arg:tt)*) => {
71
-        if let Err(err) = $e {
72
-            log::debug!(
73
-                "{:?}, {}, {}:{}:{}:{}",
74
-                err,
75
-                format_args!($($arg)*),
76
-                module_path!(),
77
-                file!(),
78
-                line!(),
79
-                column!()
80
-            );
81
-        } else {
82
-        }
83
-    };
84
-}
85
-
86
-#[inline]
87
-pub fn timeout<T: std::future::Future>(ms: u64, future: T) -> tokio::time::Timeout<T> {
88
-    tokio::time::timeout(std::time::Duration::from_millis(ms), future)
89
-}
90
-
91
-pub type ResultType<F, E = anyhow::Error> = anyhow::Result<F, E>;
92
-
93
-/// Certain router and firewalls scan the packet and if they
94
-/// find an IP address belonging to their pool that they use to do the NAT mapping/translation, so here we mangle the ip address
95
-
96
-pub struct AddrMangle();
97
-
98
-#[inline]
99
-pub fn try_into_v4(addr: SocketAddr) -> SocketAddr {
100
-    match addr {
101
-        SocketAddr::V6(v6) if !addr.ip().is_loopback() => {
102
-            if let Some(v4) = v6.ip().to_ipv4() {
103
-                SocketAddr::new(IpAddr::V4(v4), addr.port())
104
-            } else {
105
-                addr
106
-            }
107
-        }
108
-        _ => addr,
109
-    }
110
-}
111
-
112
-impl AddrMangle {
113
-    pub fn encode(addr: SocketAddr) -> Vec<u8> {
114
-        // not work with [:1]:<port>
115
-        let addr = try_into_v4(addr);
116
-        match addr {
117
-            SocketAddr::V4(addr_v4) => {
118
-                let tm = (SystemTime::now()
119
-                    .duration_since(UNIX_EPOCH)
120
-                    .unwrap()
121
-                    .as_micros() as u32) as u128;
122
-                let ip = u32::from_le_bytes(addr_v4.ip().octets()) as u128;
123
-                let port = addr.port() as u128;
124
-                let v = ((ip + tm) << 49) | (tm << 17) | (port + (tm & 0xFFFF));
125
-                let bytes = v.to_le_bytes();
126
-                let mut n_padding = 0;
127
-                for i in bytes.iter().rev() {
128
-                    if i == &0u8 {
129
-                        n_padding += 1;
130
-                    } else {
131
-                        break;
132
-                    }
133
-                }
134
-                bytes[..(16 - n_padding)].to_vec()
135
-            }
136
-            SocketAddr::V6(addr_v6) => {
137
-                let mut x = addr_v6.ip().octets().to_vec();
138
-                let port: [u8; 2] = addr_v6.port().to_le_bytes();
139
-                x.push(port[0]);
140
-                x.push(port[1]);
141
-                x
142
-            }
143
-        }
144
-    }
145
-
146
-    pub fn decode(bytes: &[u8]) -> SocketAddr {
147
-        use std::convert::TryInto;
148
-
149
-        if bytes.len() > 16 {
150
-            if bytes.len() != 18 {
151
-                return Config::get_any_listen_addr(false);
152
-            }
153
-            let tmp: [u8; 2] = bytes[16..].try_into().unwrap();
154
-            let port = u16::from_le_bytes(tmp);
155
-            let tmp: [u8; 16] = bytes[..16].try_into().unwrap();
156
-            let ip = std::net::Ipv6Addr::from(tmp);
157
-            return SocketAddr::new(IpAddr::V6(ip), port);
158
-        }
159
-        let mut padded = [0u8; 16];
160
-        padded[..bytes.len()].copy_from_slice(bytes);
161
-        let number = u128::from_le_bytes(padded);
162
-        let tm = (number >> 17) & (u32::max_value() as u128);
163
-        let ip = (((number >> 49) - tm) as u32).to_le_bytes();
164
-        let port = (number & 0xFFFFFF) - (tm & 0xFFFF);
165
-        SocketAddr::V4(SocketAddrV4::new(
166
-            Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]),
167
-            port as u16,
168
-        ))
169
-    }
170
-}
171
-
172
-pub fn get_version_from_url(url: &str) -> String {
173
-    let n = url.chars().count();
174
-    let a = url.chars().rev().position(|x| x == '-');
175
-    if let Some(a) = a {
176
-        let b = url.chars().rev().position(|x| x == '.');
177
-        if let Some(b) = b {
178
-            if a > b {
179
-                if url
180
-                    .chars()
181
-                    .skip(n - b)
182
-                    .collect::<String>()
183
-                    .parse::<i32>()
184
-                    .is_ok()
185
-                {
186
-                    return url.chars().skip(n - a).collect();
187
-                } else {
188
-                    return url.chars().skip(n - a).take(a - b - 1).collect();
189
-                }
190
-            } else {
191
-                return url.chars().skip(n - a).collect();
192
-            }
193
-        }
194
-    }
195
-    "".to_owned()
196
-}
197
-
198
-pub fn gen_version() {
199
-    println!("cargo:rerun-if-changed=Cargo.toml");
200
-    use std::io::prelude::*;
201
-    let mut file = File::create("./src/version.rs").unwrap();
202
-    for line in read_lines("Cargo.toml").unwrap().flatten() {
203
-        let ab: Vec<&str> = line.split('=').map(|x| x.trim()).collect();
204
-        if ab.len() == 2 && ab[0] == "version" {
205
-            file.write_all(format!("pub const VERSION: &str = {};\n", ab[1]).as_bytes())
206
-                .ok();
207
-            break;
208
-        }
209
-    }
210
-    // generate build date
211
-    let build_date = format!("{}", chrono::Local::now().format("%Y-%m-%d %H:%M"));
212
-    file.write_all(
213
-        format!("#[allow(dead_code)]\npub const BUILD_DATE: &str = \"{build_date}\";\n").as_bytes(),
214
-    )
215
-    .ok();
216
-    file.sync_all().ok();
217
-}
218
-
219
-fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
220
-where
221
-    P: AsRef<Path>,
222
-{
223
-    let file = File::open(filename)?;
224
-    Ok(io::BufReader::new(file).lines())
225
-}
226
-
227
-pub fn is_valid_custom_id(id: &str) -> bool {
228
-    regex::Regex::new(r"^[a-zA-Z]\w{5,15}$")
229
-        .unwrap()
230
-        .is_match(id)
231
-}
232
-
233
-pub fn get_version_number(v: &str) -> i64 {
234
-    let mut n = 0;
235
-    for x in v.split('.') {
236
-        n = n * 1000 + x.parse::<i64>().unwrap_or(0);
237
-    }
238
-    n
239
-}
240
-
241
-pub fn get_modified_time(path: &std::path::Path) -> SystemTime {
242
-    std::fs::metadata(path)
243
-        .map(|m| m.modified().unwrap_or(UNIX_EPOCH))
244
-        .unwrap_or(UNIX_EPOCH)
245
-}
246
-
247
-pub fn get_created_time(path: &std::path::Path) -> SystemTime {
248
-    std::fs::metadata(path)
249
-        .map(|m| m.created().unwrap_or(UNIX_EPOCH))
250
-        .unwrap_or(UNIX_EPOCH)
251
-}
252
-
253
-pub fn get_exe_time() -> SystemTime {
254
-    std::env::current_exe().map_or(UNIX_EPOCH, |path| {
255
-        let m = get_modified_time(&path);
256
-        let c = get_created_time(&path);
257
-        if m > c {
258
-            m
259
-        } else {
260
-            c
261
-        }
262
-    })
263
-}
264
-
265
-pub fn get_uuid() -> Vec<u8> {
266
-    #[cfg(not(any(target_os = "android", target_os = "ios")))]
267
-    if let Ok(id) = machine_uid::get() {
268
-        return id.into();
269
-    }
270
-    Config::get_key_pair().1
271
-}
272
-
273
-#[inline]
274
-pub fn get_time() -> i64 {
275
-    std::time::SystemTime::now()
276
-        .duration_since(std::time::UNIX_EPOCH)
277
-        .map(|d| d.as_millis())
278
-        .unwrap_or(0) as _
279
-}
280
-
281
-#[inline]
282
-pub fn is_ipv4_str(id: &str) -> bool {
283
-    regex::Regex::new(r"^\d+\.\d+\.\d+\.\d+(:\d+)?$")
284
-        .unwrap()
285
-        .is_match(id)
286
-}
287
-
288
-#[inline]
289
-pub fn is_ipv6_str(id: &str) -> bool {
290
-    regex::Regex::new(r"^((([a-fA-F0-9]{1,4}:{1,2})+[a-fA-F0-9]{1,4})|(\[([a-fA-F0-9]{1,4}:{1,2})+[a-fA-F0-9]{1,4}\]:\d+))$")
291
-        .unwrap()
292
-        .is_match(id)
293
-}
294
-
295
-#[inline]
296
-pub fn is_ip_str(id: &str) -> bool {
297
-    is_ipv4_str(id) || is_ipv6_str(id)
298
-}
299
-
300
-#[inline]
301
-pub fn is_domain_port_str(id: &str) -> bool {
302
-    // modified regex for RFC1123 hostname. check https://stackoverflow.com/a/106223 for original version for hostname.
303
-    // according to [TLD List](https://data.iana.org/TLD/tlds-alpha-by-domain.txt) version 2023011700,
304
-    // there is no digits in TLD, and length is 2~63.
305
-    regex::Regex::new(
306
-        r"(?i)^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z-]{0,61}[a-z]:\d{1,5}$",
307
-    )
308
-    .unwrap()
309
-    .is_match(id)
310
-}
311
-
312
-#[cfg(test)]
313
-mod test {
314
-    use super::*;
315
-
316
-    #[test]
317
-    fn test_mangle() {
318
-        let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 16, 32), 21116));
319
-        assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr)));
320
-
321
-        let addr = "[2001:db8::1]:8080".parse::<SocketAddr>().unwrap();
322
-        assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr)));
323
-
324
-        let addr = "[2001:db8:ff::1111]:80".parse::<SocketAddr>().unwrap();
325
-        assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr)));
326
-    }
327
-
328
-    #[test]
329
-    fn test_allow_err() {
330
-        allow_err!(Err("test err") as Result<(), &str>);
331
-        allow_err!(
332
-            Err("test err with msg") as Result<(), &str>,
333
-            "prompt {}",
334
-            "failed"
335
-        );
336
-    }
337
-
338
-    #[test]
339
-    fn test_ipv6() {
340
-        assert!(is_ipv6_str("1:2:3"));
341
-        assert!(is_ipv6_str("[ab:2:3]:12"));
342
-        assert!(is_ipv6_str("[ABEF:2a:3]:12"));
343
-        assert!(!is_ipv6_str("[ABEG:2a:3]:12"));
344
-        assert!(!is_ipv6_str("1[ab:2:3]:12"));
345
-        assert!(!is_ipv6_str("1.1.1.1"));
346
-        assert!(is_ip_str("1.1.1.1"));
347
-        assert!(!is_ipv6_str("1:2:"));
348
-        assert!(is_ipv6_str("1:2::0"));
349
-        assert!(is_ipv6_str("[1:2::0]:1"));
350
-        assert!(!is_ipv6_str("[1:2::0]:"));
351
-        assert!(!is_ipv6_str("1:2::0]:1"));
352
-    }
353
-
354
-    #[test]
355
-    fn test_hostname_port() {
356
-        assert!(!is_domain_port_str("a:12"));
357
-        assert!(!is_domain_port_str("a.b.c:12"));
358
-        assert!(is_domain_port_str("test.com:12"));
359
-        assert!(is_domain_port_str("test-UPPER.com:12"));
360
-        assert!(is_domain_port_str("some-other.domain.com:12"));
361
-        assert!(!is_domain_port_str("under_score:12"));
362
-        assert!(!is_domain_port_str("a@bc:12"));
363
-        assert!(!is_domain_port_str("1.1.1.1:12"));
364
-        assert!(!is_domain_port_str("1.2.3:12"));
365
-        assert!(!is_domain_port_str("1.2.3.45:12"));
366
-        assert!(!is_domain_port_str("a.b.c:123456"));
367
-        assert!(!is_domain_port_str("---:12"));
368
-        assert!(!is_domain_port_str(".:12"));
369
-        // todo: should we also check for these edge cases?
370
-        // out-of-range port
371
-        assert!(is_domain_port_str("test.com:0"));
372
-        assert!(is_domain_port_str("test.com:98989"));
373
-    }
374
-
375
-    #[test]
376
-    fn test_mangle2() {
377
-        let addr = "[::ffff:127.0.0.1]:8080".parse().unwrap();
378
-        let addr_v4 = "127.0.0.1:8080".parse().unwrap();
379
-        assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr)), addr_v4);
380
-        assert_eq!(
381
-            AddrMangle::decode(&AddrMangle::encode("[::127.0.0.1]:8080".parse().unwrap())),
382
-            addr_v4
383
-        );
384
-        assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr_v4)), addr_v4);
385
-        let addr_v6 = "[ef::fe]:8080".parse().unwrap();
386
-        assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr_v6)), addr_v6);
387
-        let addr_v6 = "[::1]:8080".parse().unwrap();
388
-        assert_eq!(AddrMangle::decode(&AddrMangle::encode(addr_v6)), addr_v6);
389
-    }
390
-}

+ 0 - 242
libs/hbb_common/src/password_security.rs

@@ -1,242 +0,0 @@
1
-use crate::config::Config;
2
-use sodiumoxide::base64;
3
-use std::sync::{Arc, RwLock};
4
-
5
-lazy_static::lazy_static! {
6
-    pub static ref TEMPORARY_PASSWORD:Arc<RwLock<String>> = Arc::new(RwLock::new(Config::get_auto_password(temporary_password_length())));
7
-}
8
-
9
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10
-enum VerificationMethod {
11
-    OnlyUseTemporaryPassword,
12
-    OnlyUsePermanentPassword,
13
-    UseBothPasswords,
14
-}
15
-
16
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17
-pub enum ApproveMode {
18
-    Both,
19
-    Password,
20
-    Click,
21
-}
22
-
23
-// Should only be called in server
24
-pub fn update_temporary_password() {
25
-    *TEMPORARY_PASSWORD.write().unwrap() = Config::get_auto_password(temporary_password_length());
26
-}
27
-
28
-// Should only be called in server
29
-pub fn temporary_password() -> String {
30
-    TEMPORARY_PASSWORD.read().unwrap().clone()
31
-}
32
-
33
-fn verification_method() -> VerificationMethod {
34
-    let method = Config::get_option("verification-method");
35
-    if method == "use-temporary-password" {
36
-        VerificationMethod::OnlyUseTemporaryPassword
37
-    } else if method == "use-permanent-password" {
38
-        VerificationMethod::OnlyUsePermanentPassword
39
-    } else {
40
-        VerificationMethod::UseBothPasswords // default
41
-    }
42
-}
43
-
44
-pub fn temporary_password_length() -> usize {
45
-    let length = Config::get_option("temporary-password-length");
46
-    if length == "8" {
47
-        8
48
-    } else if length == "10" {
49
-        10
50
-    } else {
51
-        6 // default
52
-    }
53
-}
54
-
55
-pub fn temporary_enabled() -> bool {
56
-    verification_method() != VerificationMethod::OnlyUsePermanentPassword
57
-}
58
-
59
-pub fn permanent_enabled() -> bool {
60
-    verification_method() != VerificationMethod::OnlyUseTemporaryPassword
61
-}
62
-
63
-pub fn has_valid_password() -> bool {
64
-    temporary_enabled() && !temporary_password().is_empty()
65
-        || permanent_enabled() && !Config::get_permanent_password().is_empty()
66
-}
67
-
68
-pub fn approve_mode() -> ApproveMode {
69
-    let mode = Config::get_option("approve-mode");
70
-    if mode == "password" {
71
-        ApproveMode::Password
72
-    } else if mode == "click" {
73
-        ApproveMode::Click
74
-    } else {
75
-        ApproveMode::Both
76
-    }
77
-}
78
-
79
-pub fn hide_cm() -> bool {
80
-    approve_mode() == ApproveMode::Password
81
-        && verification_method() == VerificationMethod::OnlyUsePermanentPassword
82
-        && !Config::get_option("allow-hide-cm").is_empty()
83
-}
84
-
85
-const VERSION_LEN: usize = 2;
86
-
87
-pub fn encrypt_str_or_original(s: &str, version: &str) -> String {
88
-    if decrypt_str_or_original(s, version).1 {
89
-        log::error!("Duplicate encryption!");
90
-        return s.to_owned();
91
-    }
92
-    if version == "00" {
93
-        if let Ok(s) = encrypt(s.as_bytes()) {
94
-            return version.to_owned() + &s;
95
-        }
96
-    }
97
-    s.to_owned()
98
-}
99
-
100
-// String: password
101
-// bool: whether decryption is successful
102
-// bool: whether should store to re-encrypt when load
103
-pub fn decrypt_str_or_original(s: &str, current_version: &str) -> (String, bool, bool) {
104
-    if s.len() > VERSION_LEN {
105
-        let version = &s[..VERSION_LEN];
106
-        if version == "00" {
107
-            if let Ok(v) = decrypt(s[VERSION_LEN..].as_bytes()) {
108
-                return (
109
-                    String::from_utf8_lossy(&v).to_string(),
110
-                    true,
111
-                    version != current_version,
112
-                );
113
-            }
114
-        }
115
-    }
116
-
117
-    (s.to_owned(), false, !s.is_empty())
118
-}
119
-
120
-pub fn encrypt_vec_or_original(v: &[u8], version: &str) -> Vec<u8> {
121
-    if decrypt_vec_or_original(v, version).1 {
122
-        log::error!("Duplicate encryption!");
123
-        return v.to_owned();
124
-    }
125
-    if version == "00" {
126
-        if let Ok(s) = encrypt(v) {
127
-            let mut version = version.to_owned().into_bytes();
128
-            version.append(&mut s.into_bytes());
129
-            return version;
130
-        }
131
-    }
132
-    v.to_owned()
133
-}
134
-
135
-// Vec<u8>: password
136
-// bool: whether decryption is successful
137
-// bool: whether should store to re-encrypt when load
138
-pub fn decrypt_vec_or_original(v: &[u8], current_version: &str) -> (Vec<u8>, bool, bool) {
139
-    if v.len() > VERSION_LEN {
140
-        let version = String::from_utf8_lossy(&v[..VERSION_LEN]);
141
-        if version == "00" {
142
-            if let Ok(v) = decrypt(&v[VERSION_LEN..]) {
143
-                return (v, true, version != current_version);
144
-            }
145
-        }
146
-    }
147
-
148
-    (v.to_owned(), false, !v.is_empty())
149
-}
150
-
151
-fn encrypt(v: &[u8]) -> Result<String, ()> {
152
-    if !v.is_empty() {
153
-        symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
154
-    } else {
155
-        Err(())
156
-    }
157
-}
158
-
159
-fn decrypt(v: &[u8]) -> Result<Vec<u8>, ()> {
160
-    if !v.is_empty() {
161
-        base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false))
162
-    } else {
163
-        Err(())
164
-    }
165
-}
166
-
167
-fn symmetric_crypt(data: &[u8], encrypt: bool) -> Result<Vec<u8>, ()> {
168
-    use sodiumoxide::crypto::secretbox;
169
-    use std::convert::TryInto;
170
-
171
-    let mut keybuf = crate::get_uuid();
172
-    keybuf.resize(secretbox::KEYBYTES, 0);
173
-    let key = secretbox::Key(keybuf.try_into().map_err(|_| ())?);
174
-    let nonce = secretbox::Nonce([0; secretbox::NONCEBYTES]);
175
-
176
-    if encrypt {
177
-        Ok(secretbox::seal(data, &nonce, &key))
178
-    } else {
179
-        secretbox::open(data, &nonce, &key)
180
-    }
181
-}
182
-
183
-mod test {
184
-
185
-    #[test]
186
-    fn test() {
187
-        use super::*;
188
-
189
-        let version = "00";
190
-
191
-        println!("test str");
192
-        let data = "Hello World";
193
-        let encrypted = encrypt_str_or_original(data, version);
194
-        let (decrypted, succ, store) = decrypt_str_or_original(&encrypted, version);
195
-        println!("data: {data}");
196
-        println!("encrypted: {encrypted}");
197
-        println!("decrypted: {decrypted}");
198
-        assert_eq!(data, decrypted);
199
-        assert_eq!(version, &encrypted[..2]);
200
-        assert!(succ);
201
-        assert!(!store);
202
-        let (_, _, store) = decrypt_str_or_original(&encrypted, "99");
203
-        assert!(store);
204
-        assert!(!decrypt_str_or_original(&decrypted, version).1);
205
-        assert_eq!(encrypt_str_or_original(&encrypted, version), encrypted);
206
-
207
-        println!("test vec");
208
-        let data: Vec<u8> = vec![1, 2, 3, 4, 5, 6];
209
-        let encrypted = encrypt_vec_or_original(&data, version);
210
-        let (decrypted, succ, store) = decrypt_vec_or_original(&encrypted, version);
211
-        println!("data: {data:?}");
212
-        println!("encrypted: {encrypted:?}");
213
-        println!("decrypted: {decrypted:?}");
214
-        assert_eq!(data, decrypted);
215
-        assert_eq!(version.as_bytes(), &encrypted[..2]);
216
-        assert!(!store);
217
-        assert!(succ);
218
-        let (_, _, store) = decrypt_vec_or_original(&encrypted, "99");
219
-        assert!(store);
220
-        assert!(!decrypt_vec_or_original(&decrypted, version).1);
221
-        assert_eq!(encrypt_vec_or_original(&encrypted, version), encrypted);
222
-
223
-        println!("test original");
224
-        let data = version.to_string() + "Hello World";
225
-        let (decrypted, succ, store) = decrypt_str_or_original(&data, version);
226
-        assert_eq!(data, decrypted);
227
-        assert!(store);
228
-        assert!(!succ);
229
-        let verbytes = version.as_bytes();
230
-        let data: Vec<u8> = vec![verbytes[0], verbytes[1], 1, 2, 3, 4, 5, 6];
231
-        let (decrypted, succ, store) = decrypt_vec_or_original(&data, version);
232
-        assert_eq!(data, decrypted);
233
-        assert!(store);
234
-        assert!(!succ);
235
-        let (_, succ, store) = decrypt_str_or_original("", version);
236
-        assert!(!store);
237
-        assert!(!succ);
238
-        let (_, succ, store) = decrypt_vec_or_original(&[], version);
239
-        assert!(!store);
240
-        assert!(!succ);
241
-    }
242
-}

+ 0 - 1
libs/hbb_common/src/protos/mod.rs

@@ -1 +0,0 @@
1
-include!(concat!(env!("OUT_DIR"), "/protos/mod.rs"));

+ 0 - 135
libs/hbb_common/src/quic.rs

@@ -1,135 +0,0 @@
1
-use crate::{allow_err, anyhow::anyhow, ResultType};
2
-use protobuf::Message;
3
-use std::{net::SocketAddr, sync::Arc};
4
-use tokio::{self, stream::StreamExt, sync::mpsc};
5
-
6
-const QUIC_HBB: &[&[u8]] = &[b"hbb"];
7
-const SERVER_NAME: &str = "hbb";
8
-
9
-type Sender = mpsc::UnboundedSender<Value>;
10
-type Receiver = mpsc::UnboundedReceiver<Value>;
11
-
12
-pub fn new_server(socket: std::net::UdpSocket) -> ResultType<(Server, SocketAddr)> {
13
-    let mut transport_config = quinn::TransportConfig::default();
14
-    transport_config.stream_window_uni(0);
15
-    let mut server_config = quinn::ServerConfig::default();
16
-    server_config.transport = Arc::new(transport_config);
17
-    let mut server_config = quinn::ServerConfigBuilder::new(server_config);
18
-    server_config.protocols(QUIC_HBB);
19
-    // server_config.enable_keylog();
20
-    // server_config.use_stateless_retry(true);
21
-    let mut endpoint = quinn::Endpoint::builder();
22
-    endpoint.listen(server_config.build());
23
-    let (end, incoming) = endpoint.with_socket(socket)?;
24
-    Ok((Server { incoming }, end.local_addr()?))
25
-}
26
-
27
-pub async fn new_client(local_addr: &SocketAddr, peer: &SocketAddr) -> ResultType<Connection> {
28
-    let mut endpoint = quinn::Endpoint::builder();
29
-    let mut client_config = quinn::ClientConfigBuilder::default();
30
-    client_config.protocols(QUIC_HBB);
31
-    //client_config.enable_keylog();
32
-    endpoint.default_client_config(client_config.build());
33
-    let (endpoint, _) = endpoint.bind(local_addr)?;
34
-    let new_conn = endpoint.connect(peer, SERVER_NAME)?.await?;
35
-    Connection::new_for_client(new_conn.connection).await
36
-}
37
-
38
-pub struct Server {
39
-    incoming: quinn::Incoming,
40
-}
41
-
42
-impl Server {
43
-    #[inline]
44
-    pub async fn next(&mut self) -> ResultType<Option<Connection>> {
45
-        Connection::new_for_server(&mut self.incoming).await
46
-    }
47
-}
48
-
49
-pub struct Connection {
50
-    conn: quinn::Connection,
51
-    tx: quinn::SendStream,
52
-    rx: Receiver,
53
-}
54
-
55
-type Value = ResultType<Vec<u8>>;
56
-
57
-impl Connection {
58
-    async fn new_for_server(incoming: &mut quinn::Incoming) -> ResultType<Option<Self>> {
59
-        if let Some(conn) = incoming.next().await {
60
-            let quinn::NewConnection {
61
-                connection: conn,
62
-                // uni_streams,
63
-                mut bi_streams,
64
-                ..
65
-            } = conn.await?;
66
-            let (tx, rx) = mpsc::unbounded_channel::<Value>();
67
-            tokio::spawn(async move {
68
-                loop {
69
-                    let stream = bi_streams.next().await;
70
-                    if let Some(stream) = stream {
71
-                        let stream = match stream {
72
-                            Err(e) => {
73
-                                tx.send(Err(e.into())).ok();
74
-                                break;
75
-                            }
76
-                            Ok(s) => s,
77
-                        };
78
-                        let cloned = tx.clone();
79
-                        tokio::spawn(async move {
80
-                            allow_err!(handle_request(stream.1, cloned).await);
81
-                        });
82
-                    } else {
83
-                        tx.send(Err(anyhow!("Reset by the peer"))).ok();
84
-                        break;
85
-                    }
86
-                }
87
-                log::info!("Exit connection outer loop");
88
-            });
89
-            let tx = conn.open_uni().await?;
90
-            Ok(Some(Self { conn, tx, rx }))
91
-        } else {
92
-            Ok(None)
93
-        }
94
-    }
95
-
96
-    async fn new_for_client(conn: quinn::Connection) -> ResultType<Self> {
97
-        let (tx, rx_quic) = conn.open_bi().await?;
98
-        let (tx_mpsc, rx) = mpsc::unbounded_channel::<Value>();
99
-        tokio::spawn(async move {
100
-            allow_err!(handle_request(rx_quic, tx_mpsc).await);
101
-        });
102
-        Ok(Self { conn, tx, rx })
103
-    }
104
-
105
-    #[inline]
106
-    pub async fn next(&mut self) -> Option<Value> {
107
-        // None is returned when all Sender halves have dropped,
108
-        // indicating that no further values can be sent on the channel.
109
-        self.rx.recv().await
110
-    }
111
-
112
-    #[inline]
113
-    pub fn remote_address(&self) -> SocketAddr {
114
-        self.conn.remote_address()
115
-    }
116
-
117
-    #[inline]
118
-    pub async fn send_raw(&mut self, bytes: &[u8]) -> ResultType<()> {
119
-        self.tx.write_all(bytes).await?;
120
-        Ok(())
121
-    }
122
-
123
-    #[inline]
124
-    pub async fn send(&mut self, msg: &dyn Message) -> ResultType<()> {
125
-        match msg.write_to_bytes() {
126
-            Ok(bytes) => self.send_raw(&bytes).await?,
127
-            err => allow_err!(err),
128
-        }
129
-        Ok(())
130
-    }
131
-}
132
-
133
-async fn handle_request(rx: quinn::RecvStream, tx: Sender) -> ResultType<()> {
134
-    Ok(())
135
-}

+ 0 - 281
libs/hbb_common/src/socket_client.rs

@@ -1,281 +0,0 @@
1
-use crate::{
2
-    config::{Config, NetworkType},
3
-    tcp::FramedStream,
4
-    udp::FramedSocket,
5
-    ResultType,
6
-};
7
-use anyhow::Context;
8
-use std::net::SocketAddr;
9
-use tokio::net::ToSocketAddrs;
10
-use tokio_socks::{IntoTargetAddr, TargetAddr};
11
-
12
-#[inline]
13
-pub fn check_port<T: std::string::ToString>(host: T, port: i32) -> String {
14
-    let host = host.to_string();
15
-    if crate::is_ipv6_str(&host) {
16
-        if host.starts_with('[') {
17
-            return host;
18
-        }
19
-        return format!("[{host}]:{port}");
20
-    }
21
-    if !host.contains(':') {
22
-        return format!("{host}:{port}");
23
-    }
24
-    host
25
-}
26
-
27
-#[inline]
28
-pub fn increase_port<T: std::string::ToString>(host: T, offset: i32) -> String {
29
-    let host = host.to_string();
30
-    if crate::is_ipv6_str(&host) {
31
-        if host.starts_with('[') {
32
-            let tmp: Vec<&str> = host.split("]:").collect();
33
-            if tmp.len() == 2 {
34
-                let port: i32 = tmp[1].parse().unwrap_or(0);
35
-                if port > 0 {
36
-                    return format!("{}]:{}", tmp[0], port + offset);
37
-                }
38
-            }
39
-        }
40
-    } else if host.contains(':') {
41
-        let tmp: Vec<&str> = host.split(':').collect();
42
-        if tmp.len() == 2 {
43
-            let port: i32 = tmp[1].parse().unwrap_or(0);
44
-            if port > 0 {
45
-                return format!("{}:{}", tmp[0], port + offset);
46
-            }
47
-        }
48
-    }
49
-    host
50
-}
51
-
52
-pub fn test_if_valid_server(host: &str) -> String {
53
-    let host = check_port(host, 0);
54
-
55
-    use std::net::ToSocketAddrs;
56
-    match Config::get_network_type() {
57
-        NetworkType::Direct => match host.to_socket_addrs() {
58
-            Err(err) => err.to_string(),
59
-            Ok(_) => "".to_owned(),
60
-        },
61
-        NetworkType::ProxySocks => match &host.into_target_addr() {
62
-            Err(err) => err.to_string(),
63
-            Ok(_) => "".to_owned(),
64
-        },
65
-    }
66
-}
67
-
68
-pub trait IsResolvedSocketAddr {
69
-    fn resolve(&self) -> Option<&SocketAddr>;
70
-}
71
-
72
-impl IsResolvedSocketAddr for SocketAddr {
73
-    fn resolve(&self) -> Option<&SocketAddr> {
74
-        Some(self)
75
-    }
76
-}
77
-
78
-impl IsResolvedSocketAddr for String {
79
-    fn resolve(&self) -> Option<&SocketAddr> {
80
-        None
81
-    }
82
-}
83
-
84
-impl IsResolvedSocketAddr for &str {
85
-    fn resolve(&self) -> Option<&SocketAddr> {
86
-        None
87
-    }
88
-}
89
-
90
-#[inline]
91
-pub async fn connect_tcp<
92
-    't,
93
-    T: IntoTargetAddr<'t> + ToSocketAddrs + IsResolvedSocketAddr + std::fmt::Display,
94
->(
95
-    target: T,
96
-    ms_timeout: u64,
97
-) -> ResultType<FramedStream> {
98
-    connect_tcp_local(target, None, ms_timeout).await
99
-}
100
-
101
-pub async fn connect_tcp_local<
102
-    't,
103
-    T: IntoTargetAddr<'t> + ToSocketAddrs + IsResolvedSocketAddr + std::fmt::Display,
104
->(
105
-    target: T,
106
-    local: Option<SocketAddr>,
107
-    ms_timeout: u64,
108
-) -> ResultType<FramedStream> {
109
-    if let Some(conf) = Config::get_socks() {
110
-        return FramedStream::connect(
111
-            conf.proxy.as_str(),
112
-            target,
113
-            local,
114
-            conf.username.as_str(),
115
-            conf.password.as_str(),
116
-            ms_timeout,
117
-        )
118
-        .await;
119
-    }
120
-    if let Some(target) = target.resolve() {
121
-        if let Some(local) = local {
122
-            if local.is_ipv6() && target.is_ipv4() {
123
-                let target = query_nip_io(target).await?;
124
-                return FramedStream::new(target, Some(local), ms_timeout).await;
125
-            }
126
-        }
127
-    }
128
-    FramedStream::new(target, local, ms_timeout).await
129
-}
130
-
131
-#[inline]
132
-pub fn is_ipv4(target: &TargetAddr<'_>) -> bool {
133
-    match target {
134
-        TargetAddr::Ip(addr) => addr.is_ipv4(),
135
-        _ => true,
136
-    }
137
-}
138
-
139
-#[inline]
140
-pub async fn query_nip_io(addr: &SocketAddr) -> ResultType<SocketAddr> {
141
-    tokio::net::lookup_host(format!("{}.nip.io:{}", addr.ip(), addr.port()))
142
-        .await?
143
-        .find(|x| x.is_ipv6())
144
-        .context("Failed to get ipv6 from nip.io")
145
-}
146
-
147
-#[inline]
148
-pub fn ipv4_to_ipv6(addr: String, ipv4: bool) -> String {
149
-    if !ipv4 && crate::is_ipv4_str(&addr) {
150
-        if let Some(ip) = addr.split(':').next() {
151
-            return addr.replace(ip, &format!("{ip}.nip.io"));
152
-        }
153
-    }
154
-    addr
155
-}
156
-
157
-async fn test_target(target: &str) -> ResultType<SocketAddr> {
158
-    if let Ok(Ok(s)) = super::timeout(1000, tokio::net::TcpStream::connect(target)).await {
159
-        if let Ok(addr) = s.peer_addr() {
160
-            return Ok(addr);
161
-        }
162
-    }
163
-    tokio::net::lookup_host(target)
164
-        .await?
165
-        .next()
166
-        .context(format!("Failed to look up host for {target}"))
167
-}
168
-
169
-#[inline]
170
-pub async fn new_udp_for(
171
-    target: &str,
172
-    ms_timeout: u64,
173
-) -> ResultType<(FramedSocket, TargetAddr<'static>)> {
174
-    let (ipv4, target) = if NetworkType::Direct == Config::get_network_type() {
175
-        let addr = test_target(target).await?;
176
-        (addr.is_ipv4(), addr.into_target_addr()?)
177
-    } else {
178
-        (true, target.into_target_addr()?)
179
-    };
180
-    Ok((
181
-        new_udp(Config::get_any_listen_addr(ipv4), ms_timeout).await?,
182
-        target.to_owned(),
183
-    ))
184
-}
185
-
186
-async fn new_udp<T: ToSocketAddrs>(local: T, ms_timeout: u64) -> ResultType<FramedSocket> {
187
-    match Config::get_socks() {
188
-        None => Ok(FramedSocket::new(local).await?),
189
-        Some(conf) => {
190
-            let socket = FramedSocket::new_proxy(
191
-                conf.proxy.as_str(),
192
-                local,
193
-                conf.username.as_str(),
194
-                conf.password.as_str(),
195
-                ms_timeout,
196
-            )
197
-            .await?;
198
-            Ok(socket)
199
-        }
200
-    }
201
-}
202
-
203
-pub async fn rebind_udp_for(
204
-    target: &str,
205
-) -> ResultType<Option<(FramedSocket, TargetAddr<'static>)>> {
206
-    if Config::get_network_type() != NetworkType::Direct {
207
-        return Ok(None);
208
-    }
209
-    let addr = test_target(target).await?;
210
-    let v4 = addr.is_ipv4();
211
-    Ok(Some((
212
-        FramedSocket::new(Config::get_any_listen_addr(v4)).await?,
213
-        addr.into_target_addr()?.to_owned(),
214
-    )))
215
-}
216
-
217
-#[cfg(test)]
218
-mod tests {
219
-    use std::net::ToSocketAddrs;
220
-
221
-    use super::*;
222
-
223
-    #[test]
224
-    fn test_nat64() {
225
-        test_nat64_async();
226
-    }
227
-
228
-    #[tokio::main(flavor = "current_thread")]
229
-    async fn test_nat64_async() {
230
-        assert_eq!(ipv4_to_ipv6("1.1.1.1".to_owned(), true), "1.1.1.1");
231
-        assert_eq!(ipv4_to_ipv6("1.1.1.1".to_owned(), false), "1.1.1.1.nip.io");
232
-        assert_eq!(
233
-            ipv4_to_ipv6("1.1.1.1:8080".to_owned(), false),
234
-            "1.1.1.1.nip.io:8080"
235
-        );
236
-        assert_eq!(
237
-            ipv4_to_ipv6("rustdesk.com".to_owned(), false),
238
-            "rustdesk.com"
239
-        );
240
-        if ("rustdesk.com:80")
241
-            .to_socket_addrs()
242
-            .unwrap()
243
-            .next()
244
-            .unwrap()
245
-            .is_ipv6()
246
-        {
247
-            assert!(query_nip_io(&"1.1.1.1:80".parse().unwrap())
248
-                .await
249
-                .unwrap()
250
-                .is_ipv6());
251
-            return;
252
-        }
253
-        assert!(query_nip_io(&"1.1.1.1:80".parse().unwrap()).await.is_err());
254
-    }
255
-
256
-    #[test]
257
-    fn test_test_if_valid_server() {
258
-        assert!(!test_if_valid_server("a").is_empty());
259
-        // on Linux, "1" is resolved to "0.0.0.1"
260
-        assert!(test_if_valid_server("1.1.1.1").is_empty());
261
-        assert!(test_if_valid_server("1.1.1.1:1").is_empty());
262
-    }
263
-
264
-    #[test]
265
-    fn test_check_port() {
266
-        assert_eq!(check_port("[1:2]:12", 32), "[1:2]:12");
267
-        assert_eq!(check_port("1:2", 32), "[1:2]:32");
268
-        assert_eq!(check_port("z1:2", 32), "z1:2");
269
-        assert_eq!(check_port("1.1.1.1", 32), "1.1.1.1:32");
270
-        assert_eq!(check_port("1.1.1.1:32", 32), "1.1.1.1:32");
271
-        assert_eq!(check_port("test.com:32", 0), "test.com:32");
272
-        assert_eq!(increase_port("[1:2]:12", 1), "[1:2]:13");
273
-        assert_eq!(increase_port("1.2.2.4:12", 1), "1.2.2.4:13");
274
-        assert_eq!(increase_port("1.2.2.4", 1), "1.2.2.4");
275
-        assert_eq!(increase_port("test.com", 1), "test.com");
276
-        assert_eq!(increase_port("test.com:13", 4), "test.com:17");
277
-        assert_eq!(increase_port("1:13", 4), "1:13");
278
-        assert_eq!(increase_port("22:1:13", 4), "22:1:13");
279
-        assert_eq!(increase_port("z1:2", 1), "z1:3");
280
-    }
281
-}

+ 0 - 335
libs/hbb_common/src/tcp.rs

@@ -1,335 +0,0 @@
1
-use crate::{bail, bytes_codec::BytesCodec, ResultType};
2
-use anyhow::Context as AnyhowCtx;
3
-use bytes::{BufMut, Bytes, BytesMut};
4
-use futures::{SinkExt, StreamExt};
5
-use protobuf::Message;
6
-use sodiumoxide::crypto::secretbox::{self, Key, Nonce};
7
-use std::{
8
-    io::{self, Error, ErrorKind},
9
-    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
10
-    ops::{Deref, DerefMut},
11
-    pin::Pin,
12
-    task::{Context, Poll},
13
-};
14
-use tokio::{
15
-    io::{AsyncRead, AsyncWrite, ReadBuf},
16
-    net::{lookup_host, TcpListener, TcpSocket, ToSocketAddrs},
17
-};
18
-use tokio_socks::{tcp::Socks5Stream, IntoTargetAddr, ToProxyAddrs};
19
-use tokio_util::codec::Framed;
20
-
21
-pub trait TcpStreamTrait: AsyncRead + AsyncWrite + Unpin {}
22
-pub struct DynTcpStream(Box<dyn TcpStreamTrait + Send + Sync>);
23
-
24
-pub struct FramedStream(
25
-    Framed<DynTcpStream, BytesCodec>,
26
-    SocketAddr,
27
-    Option<(Key, u64, u64)>,
28
-    u64,
29
-);
30
-
31
-impl Deref for FramedStream {
32
-    type Target = Framed<DynTcpStream, BytesCodec>;
33
-
34
-    fn deref(&self) -> &Self::Target {
35
-        &self.0
36
-    }
37
-}
38
-
39
-impl DerefMut for FramedStream {
40
-    fn deref_mut(&mut self) -> &mut Self::Target {
41
-        &mut self.0
42
-    }
43
-}
44
-
45
-impl Deref for DynTcpStream {
46
-    type Target = Box<dyn TcpStreamTrait + Send + Sync>;
47
-
48
-    fn deref(&self) -> &Self::Target {
49
-        &self.0
50
-    }
51
-}
52
-
53
-impl DerefMut for DynTcpStream {
54
-    fn deref_mut(&mut self) -> &mut Self::Target {
55
-        &mut self.0
56
-    }
57
-}
58
-
59
-fn new_socket(addr: std::net::SocketAddr, reuse: bool) -> Result<TcpSocket, std::io::Error> {
60
-    let socket = match addr {
61
-        std::net::SocketAddr::V4(..) => TcpSocket::new_v4()?,
62
-        std::net::SocketAddr::V6(..) => TcpSocket::new_v6()?,
63
-    };
64
-    if reuse {
65
-        // windows has no reuse_port, but its reuse_address
66
-        // almost equals to unix's reuse_port + reuse_address,
67
-        // though may introduce nondeterministic behavior.
68
-        // illumos has no support for SO_REUSEPORT
69
-        #[cfg(all(unix, not(target_os = "illumos")))]
70
-        socket.set_reuseport(true)?;
71
-        socket.set_reuseaddr(true)?;
72
-    }
73
-    socket.bind(addr)?;
74
-    Ok(socket)
75
-}
76
-
77
-impl FramedStream {
78
-    pub async fn new<T: ToSocketAddrs + std::fmt::Display>(
79
-        remote_addr: T,
80
-        local_addr: Option<SocketAddr>,
81
-        ms_timeout: u64,
82
-    ) -> ResultType<Self> {
83
-        for remote_addr in lookup_host(&remote_addr).await? {
84
-            let local = if let Some(addr) = local_addr {
85
-                addr
86
-            } else {
87
-                crate::config::Config::get_any_listen_addr(remote_addr.is_ipv4())
88
-            };
89
-            if let Ok(socket) = new_socket(local, true) {
90
-                if let Ok(Ok(stream)) =
91
-                    super::timeout(ms_timeout, socket.connect(remote_addr)).await
92
-                {
93
-                    stream.set_nodelay(true).ok();
94
-                    let addr = stream.local_addr()?;
95
-                    return Ok(Self(
96
-                        Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()),
97
-                        addr,
98
-                        None,
99
-                        0,
100
-                    ));
101
-                }
102
-            }
103
-        }
104
-        bail!(format!("Failed to connect to {remote_addr}"));
105
-    }
106
-
107
-    pub async fn connect<'a, 't, P, T>(
108
-        proxy: P,
109
-        target: T,
110
-        local_addr: Option<SocketAddr>,
111
-        username: &'a str,
112
-        password: &'a str,
113
-        ms_timeout: u64,
114
-    ) -> ResultType<Self>
115
-    where
116
-        P: ToProxyAddrs,
117
-        T: IntoTargetAddr<'t>,
118
-    {
119
-        if let Some(Ok(proxy)) = proxy.to_proxy_addrs().next().await {
120
-            let local = if let Some(addr) = local_addr {
121
-                addr
122
-            } else {
123
-                crate::config::Config::get_any_listen_addr(proxy.is_ipv4())
124
-            };
125
-            let stream =
126
-                super::timeout(ms_timeout, new_socket(local, true)?.connect(proxy)).await??;
127
-            stream.set_nodelay(true).ok();
128
-            let stream = if username.trim().is_empty() {
129
-                super::timeout(
130
-                    ms_timeout,
131
-                    Socks5Stream::connect_with_socket(stream, target),
132
-                )
133
-                .await??
134
-            } else {
135
-                super::timeout(
136
-                    ms_timeout,
137
-                    Socks5Stream::connect_with_password_and_socket(
138
-                        stream, target, username, password,
139
-                    ),
140
-                )
141
-                .await??
142
-            };
143
-            let addr = stream.local_addr()?;
144
-            return Ok(Self(
145
-                Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()),
146
-                addr,
147
-                None,
148
-                0,
149
-            ));
150
-        }
151
-        bail!("could not resolve to any address");
152
-    }
153
-
154
-    pub fn local_addr(&self) -> SocketAddr {
155
-        self.1
156
-    }
157
-
158
-    pub fn set_send_timeout(&mut self, ms: u64) {
159
-        self.3 = ms;
160
-    }
161
-
162
-    pub fn from(stream: impl TcpStreamTrait + Send + Sync + 'static, addr: SocketAddr) -> Self {
163
-        Self(
164
-            Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()),
165
-            addr,
166
-            None,
167
-            0,
168
-        )
169
-    }
170
-
171
-    pub fn set_raw(&mut self) {
172
-        self.0.codec_mut().set_raw();
173
-        self.2 = None;
174
-    }
175
-
176
-    pub fn is_secured(&self) -> bool {
177
-        self.2.is_some()
178
-    }
179
-
180
-    #[inline]
181
-    pub async fn send(&mut self, msg: &impl Message) -> ResultType<()> {
182
-        self.send_raw(msg.write_to_bytes()?).await
183
-    }
184
-
185
-    #[inline]
186
-    pub async fn send_raw(&mut self, msg: Vec<u8>) -> ResultType<()> {
187
-        let mut msg = msg;
188
-        if let Some(key) = self.2.as_mut() {
189
-            key.1 += 1;
190
-            let nonce = Self::get_nonce(key.1);
191
-            msg = secretbox::seal(&msg, &nonce, &key.0);
192
-        }
193
-        self.send_bytes(bytes::Bytes::from(msg)).await?;
194
-        Ok(())
195
-    }
196
-
197
-    #[inline]
198
-    pub async fn send_bytes(&mut self, bytes: Bytes) -> ResultType<()> {
199
-        if self.3 > 0 {
200
-            super::timeout(self.3, self.0.send(bytes)).await??;
201
-        } else {
202
-            self.0.send(bytes).await?;
203
-        }
204
-        Ok(())
205
-    }
206
-
207
-    #[inline]
208
-    pub async fn next(&mut self) -> Option<Result<BytesMut, Error>> {
209
-        let mut res = self.0.next().await;
210
-        if let Some(key) = self.2.as_mut() {
211
-            if let Some(Ok(bytes)) = res.as_mut() {
212
-                key.2 += 1;
213
-                let nonce = Self::get_nonce(key.2);
214
-                match secretbox::open(bytes, &nonce, &key.0) {
215
-                    Ok(res) => {
216
-                        bytes.clear();
217
-                        bytes.put_slice(&res);
218
-                    }
219
-                    Err(()) => {
220
-                        return Some(Err(Error::new(ErrorKind::Other, "decryption error")));
221
-                    }
222
-                }
223
-            }
224
-        }
225
-        res
226
-    }
227
-
228
-    #[inline]
229
-    pub async fn next_timeout(&mut self, ms: u64) -> Option<Result<BytesMut, Error>> {
230
-        if let Ok(res) = super::timeout(ms, self.next()).await {
231
-            res
232
-        } else {
233
-            None
234
-        }
235
-    }
236
-
237
-    pub fn set_key(&mut self, key: Key) {
238
-        self.2 = Some((key, 0, 0));
239
-    }
240
-
241
-    fn get_nonce(seqnum: u64) -> Nonce {
242
-        let mut nonce = Nonce([0u8; secretbox::NONCEBYTES]);
243
-        nonce.0[..std::mem::size_of_val(&seqnum)].copy_from_slice(&seqnum.to_le_bytes());
244
-        nonce
245
-    }
246
-}
247
-
248
-const DEFAULT_BACKLOG: u32 = 128;
249
-
250
-pub async fn new_listener<T: ToSocketAddrs>(addr: T, reuse: bool) -> ResultType<TcpListener> {
251
-    if !reuse {
252
-        Ok(TcpListener::bind(addr).await?)
253
-    } else {
254
-        let addr = lookup_host(&addr)
255
-            .await?
256
-            .next()
257
-            .context("could not resolve to any address")?;
258
-        new_socket(addr, true)?
259
-            .listen(DEFAULT_BACKLOG)
260
-            .map_err(anyhow::Error::msg)
261
-    }
262
-}
263
-
264
-pub async fn listen_any(port: u16, reuse: bool) -> ResultType<TcpListener> {
265
-    if let Ok(mut socket) = TcpSocket::new_v6() {
266
-        if reuse {
267
-            // windows has no reuse_port, but its reuse_address
268
-            // almost equals to unix's reuse_port + reuse_address,
269
-            // though may introduce nondeterministic behavior.
270
-            // illumos has no support for SO_REUSEPORT
271
-            #[cfg(all(unix, not(target_os = "illumos")))]
272
-            socket.set_reuseport(true).ok();
273
-            socket.set_reuseaddr(true).ok();
274
-        }
275
-        #[cfg(unix)]
276
-        {
277
-            use std::os::unix::io::{FromRawFd, IntoRawFd};
278
-            let raw_fd = socket.into_raw_fd();
279
-            let sock2 = unsafe { socket2::Socket::from_raw_fd(raw_fd) };
280
-            sock2.set_only_v6(false).ok();
281
-            socket = unsafe { TcpSocket::from_raw_fd(sock2.into_raw_fd()) };
282
-        }
283
-        #[cfg(windows)]
284
-        {
285
-            use std::os::windows::prelude::{FromRawSocket, IntoRawSocket};
286
-            let raw_socket = socket.into_raw_socket();
287
-            let sock2 = unsafe { socket2::Socket::from_raw_socket(raw_socket) };
288
-            sock2.set_only_v6(false).ok();
289
-            socket = unsafe { TcpSocket::from_raw_socket(sock2.into_raw_socket()) };
290
-        }
291
-        if socket
292
-            .bind(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port))
293
-            .is_ok()
294
-        {
295
-            if let Ok(l) = socket.listen(DEFAULT_BACKLOG) {
296
-                return Ok(l);
297
-            }
298
-        }
299
-    }
300
-    let s = TcpSocket::new_v4()?;
301
-    s.bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port))?;
302
-    Ok(s.listen(DEFAULT_BACKLOG)?)
303
-}
304
-
305
-impl Unpin for DynTcpStream {}
306
-
307
-impl AsyncRead for DynTcpStream {
308
-    fn poll_read(
309
-        mut self: Pin<&mut Self>,
310
-        cx: &mut Context<'_>,
311
-        buf: &mut ReadBuf<'_>,
312
-    ) -> Poll<io::Result<()>> {
313
-        AsyncRead::poll_read(Pin::new(&mut self.0), cx, buf)
314
-    }
315
-}
316
-
317
-impl AsyncWrite for DynTcpStream {
318
-    fn poll_write(
319
-        mut self: Pin<&mut Self>,
320
-        cx: &mut Context<'_>,
321
-        buf: &[u8],
322
-    ) -> Poll<io::Result<usize>> {
323
-        AsyncWrite::poll_write(Pin::new(&mut self.0), cx, buf)
324
-    }
325
-
326
-    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
327
-        AsyncWrite::poll_flush(Pin::new(&mut self.0), cx)
328
-    }
329
-
330
-    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
331
-        AsyncWrite::poll_shutdown(Pin::new(&mut self.0), cx)
332
-    }
333
-}
334
-
335
-impl<R: AsyncRead + AsyncWrite + Unpin> TcpStreamTrait for R {}

+ 0 - 171
libs/hbb_common/src/udp.rs

@@ -1,171 +0,0 @@
1
-use crate::ResultType;
2
-use anyhow::{anyhow, Context};
3
-use bytes::{Bytes, BytesMut};
4
-use futures::{SinkExt, StreamExt};
5
-use protobuf::Message;
6
-use socket2::{Domain, Socket, Type};
7
-use std::net::SocketAddr;
8
-use tokio::net::{lookup_host, ToSocketAddrs, UdpSocket};
9
-use tokio_socks::{udp::Socks5UdpFramed, IntoTargetAddr, TargetAddr, ToProxyAddrs};
10
-use tokio_util::{codec::BytesCodec, udp::UdpFramed};
11
-
12
-pub enum FramedSocket {
13
-    Direct(UdpFramed<BytesCodec>),
14
-    ProxySocks(Socks5UdpFramed),
15
-}
16
-
17
-fn new_socket(addr: SocketAddr, reuse: bool, buf_size: usize) -> Result<Socket, std::io::Error> {
18
-    let socket = match addr {
19
-        SocketAddr::V4(..) => Socket::new(Domain::ipv4(), Type::dgram(), None),
20
-        SocketAddr::V6(..) => Socket::new(Domain::ipv6(), Type::dgram(), None),
21
-    }?;
22
-    if reuse {
23
-        // windows has no reuse_port, but its reuse_address
24
-        // almost equals to unix's reuse_port + reuse_address,
25
-        // though may introduce nondeterministic behavior.
26
-        // illumos has no support for SO_REUSEPORT
27
-        #[cfg(all(unix, not(target_os = "illumos")))]
28
-        socket.set_reuse_port(true)?;
29
-        socket.set_reuse_address(true)?;
30
-    }
31
-    // only nonblocking work with tokio, https://stackoverflow.com/questions/64649405/receiver-on-tokiompscchannel-only-receives-messages-when-buffer-is-full
32
-    socket.set_nonblocking(true)?;
33
-    if buf_size > 0 {
34
-        socket.set_recv_buffer_size(buf_size).ok();
35
-    }
36
-    log::info!(
37
-        "Receive buf size of udp {}: {:?}",
38
-        addr,
39
-        socket.recv_buffer_size()
40
-    );
41
-    if addr.is_ipv6() && addr.ip().is_unspecified() && addr.port() > 0 {
42
-        socket.set_only_v6(false).ok();
43
-    }
44
-    socket.bind(&addr.into())?;
45
-    Ok(socket)
46
-}
47
-
48
-impl FramedSocket {
49
-    pub async fn new<T: ToSocketAddrs>(addr: T) -> ResultType<Self> {
50
-        Self::new_reuse(addr, false, 0).await
51
-    }
52
-
53
-    pub async fn new_reuse<T: ToSocketAddrs>(
54
-        addr: T,
55
-        reuse: bool,
56
-        buf_size: usize,
57
-    ) -> ResultType<Self> {
58
-        let addr = lookup_host(&addr)
59
-            .await?
60
-            .next()
61
-            .context("could not resolve to any address")?;
62
-        Ok(Self::Direct(UdpFramed::new(
63
-            UdpSocket::from_std(new_socket(addr, reuse, buf_size)?.into_udp_socket())?,
64
-            BytesCodec::new(),
65
-        )))
66
-    }
67
-
68
-    pub async fn new_proxy<'a, 't, P: ToProxyAddrs, T: ToSocketAddrs>(
69
-        proxy: P,
70
-        local: T,
71
-        username: &'a str,
72
-        password: &'a str,
73
-        ms_timeout: u64,
74
-    ) -> ResultType<Self> {
75
-        let framed = if username.trim().is_empty() {
76
-            super::timeout(ms_timeout, Socks5UdpFramed::connect(proxy, Some(local))).await??
77
-        } else {
78
-            super::timeout(
79
-                ms_timeout,
80
-                Socks5UdpFramed::connect_with_password(proxy, Some(local), username, password),
81
-            )
82
-            .await??
83
-        };
84
-        log::trace!(
85
-            "Socks5 udp connected, local addr: {:?}, target addr: {}",
86
-            framed.local_addr(),
87
-            framed.socks_addr()
88
-        );
89
-        Ok(Self::ProxySocks(framed))
90
-    }
91
-
92
-    #[inline]
93
-    pub async fn send(
94
-        &mut self,
95
-        msg: &impl Message,
96
-        addr: impl IntoTargetAddr<'_>,
97
-    ) -> ResultType<()> {
98
-        let addr = addr.into_target_addr()?.to_owned();
99
-        let send_data = Bytes::from(msg.write_to_bytes()?);
100
-        match self {
101
-            Self::Direct(f) => {
102
-                if let TargetAddr::Ip(addr) = addr {
103
-                    f.send((send_data, addr)).await?
104
-                }
105
-            }
106
-            Self::ProxySocks(f) => f.send((send_data, addr)).await?,
107
-        };
108
-        Ok(())
109
-    }
110
-
111
-    // https://stackoverflow.com/a/68733302/1926020
112
-    #[inline]
113
-    pub async fn send_raw(
114
-        &mut self,
115
-        msg: &'static [u8],
116
-        addr: impl IntoTargetAddr<'static>,
117
-    ) -> ResultType<()> {
118
-        let addr = addr.into_target_addr()?.to_owned();
119
-
120
-        match self {
121
-            Self::Direct(f) => {
122
-                if let TargetAddr::Ip(addr) = addr {
123
-                    f.send((Bytes::from(msg), addr)).await?
124
-                }
125
-            }
126
-            Self::ProxySocks(f) => f.send((Bytes::from(msg), addr)).await?,
127
-        };
128
-        Ok(())
129
-    }
130
-
131
-    #[inline]
132
-    pub async fn next(&mut self) -> Option<ResultType<(BytesMut, TargetAddr<'static>)>> {
133
-        match self {
134
-            Self::Direct(f) => match f.next().await {
135
-                Some(Ok((data, addr))) => {
136
-                    Some(Ok((data, addr.into_target_addr().ok()?.to_owned())))
137
-                }
138
-                Some(Err(e)) => Some(Err(anyhow!(e))),
139
-                None => None,
140
-            },
141
-            Self::ProxySocks(f) => match f.next().await {
142
-                Some(Ok((data, _))) => Some(Ok((data.data, data.dst_addr))),
143
-                Some(Err(e)) => Some(Err(anyhow!(e))),
144
-                None => None,
145
-            },
146
-        }
147
-    }
148
-
149
-    #[inline]
150
-    pub async fn next_timeout(
151
-        &mut self,
152
-        ms: u64,
153
-    ) -> Option<ResultType<(BytesMut, TargetAddr<'static>)>> {
154
-        if let Ok(res) =
155
-            tokio::time::timeout(std::time::Duration::from_millis(ms), self.next()).await
156
-        {
157
-            res
158
-        } else {
159
-            None
160
-        }
161
-    }
162
-
163
-    pub fn local_addr(&self) -> Option<SocketAddr> {
164
-        if let FramedSocket::Direct(x) = self {
165
-            if let Ok(v) = x.get_ref().local_addr() {
166
-                return Some(v);
167
-            }
168
-        }
169
-        None
170
-    }
171
-}

+ 29 - 2
src/common.rs

@@ -1,7 +1,6 @@
1 1
 use clap::App;
2 2
 use hbb_common::{
3
-    anyhow::{Context, Result},
4
-    log, ResultType,
3
+    allow_err, anyhow::{Context, Result}, get_version_number, log, tokio, ResultType
5 4
 };
6 5
 use ini::Ini;
7 6
 use sodiumoxide::crypto::sign;
@@ -189,3 +188,31 @@ pub async fn listen_signal() -> Result<()> {
189 188
     let () = std::future::pending().await;
190 189
     unreachable!();
191 190
 }
191
+
192
+
193
+pub fn check_software_update() {
194
+    const ONE_DAY_IN_SECONDS: u64 = 60 * 60 * 24;
195
+    std::thread::spawn(move || loop {
196
+        std::thread::spawn(move || allow_err!(check_software_update_()));
197
+        std::thread::sleep(std::time::Duration::from_secs(ONE_DAY_IN_SECONDS));
198
+    });
199
+}
200
+
201
+#[tokio::main(flavor = "current_thread")]
202
+async fn check_software_update_() -> hbb_common::ResultType<()> {
203
+    let (request, url) = hbb_common::version_check_request(hbb_common::VER_TYPE_RUSTDESK_SERVER.to_string());
204
+    let latest_release_response = reqwest::Client::builder().build()?
205
+        .post(url)
206
+        .json(&request)
207
+        .send()
208
+        .await?;
209
+
210
+    let bytes = latest_release_response.bytes().await?;
211
+    let resp: hbb_common::VersionCheckResponse = serde_json::from_slice(&bytes)?;
212
+    let response_url = resp.url;
213
+    let latest_release_version = response_url.rsplit('/').next().unwrap_or_default();
214
+    if get_version_number(&latest_release_version) > get_version_number(crate::version::VERSION) {
215
+       log::info!("new version is available: {}", latest_release_version);
216
+    }
217
+    Ok(())
218
+}

+ 1 - 0
src/main.rs

@@ -31,6 +31,7 @@ fn main() -> ResultType<()> {
31 31
     }
32 32
     let rmem = get_arg("rmem").parse::<usize>().unwrap_or(RMEM);
33 33
     let serial: i32 = get_arg("serial").parse().unwrap_or(0);
34
+    crate::common::check_software_update();
34 35
     RendezvousServer::start(port, serial, &get_arg_or("key", "-".to_owned()), rmem)?;
35 36
     Ok(())
36 37
 }

+ 1 - 1
src/relay_server.rs

@@ -85,7 +85,7 @@ pub async fn start(port: &str, key: &str) -> ResultType<()> {
85 85
     let main_task = async move {
86 86
         loop {
87 87
             log::info!("Start");
88
-            io_loop(listen_any(port, true).await?, listen_any(port2, true).await?, &key).await;
88
+            io_loop(listen_any(port).await?, listen_any(port2).await?, &key).await;
89 89
         }
90 90
     };
91 91
     let listen_signal = crate::common::listen_signal();

+ 1 - 1
src/rendezvous_server.rs

@@ -1319,7 +1319,7 @@ async fn create_udp_listener(port: i32, rmem: usize) -> ResultType<FramedSocket>
1319 1319
 
1320 1320
 #[inline]
1321 1321
 async fn create_tcp_listener(port: i32) -> ResultType<TcpListener> {
1322
-    let s = listen_any(port as _, true).await?;
1322
+    let s = listen_any(port as _).await?;
1323 1323
     log::debug!("listen on tcp {:?}", s.local_addr());
1324 1324
     Ok(s)
1325 1325
 }