diff options
-rw-r--r-- | Cargo.lock | 260 | ||||
-rw-r--r-- | client-native-export-track/Cargo.toml | 2 | ||||
-rw-r--r-- | client-native-export-track/src/main.rs | 12 | ||||
-rw-r--r-- | client-native-gui/Cargo.toml | 2 | ||||
-rw-r--r-- | client-native-gui/src/chat.rs | 2 | ||||
-rw-r--r-- | client-native-gui/src/main.rs | 38 | ||||
-rw-r--r-- | client-native-lib/Cargo.toml | 2 | ||||
-rw-r--r-- | client-native-lib/src/peer.rs | 5 | ||||
-rw-r--r-- | client-native-rift/Cargo.toml | 7 | ||||
-rw-r--r-- | client-native-rift/src/file.rs | 109 | ||||
-rw-r--r-- | client-native-rift/src/main.rs | 524 | ||||
-rw-r--r-- | client-native-rift/src/port.rs | 99 |
12 files changed, 683 insertions, 379 deletions
@@ -184,7 +184,7 @@ dependencies = [ "cesu8", "jni", "jni-sys", - "libc 0.2.152", + "libc 0.2.153", "log", "ndk", "ndk-context", @@ -249,9 +249,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arboard" @@ -259,7 +259,7 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac57f2b058a76363e357c056e4f74f1945bf734d37b8b3ef49066c4787dde0fc" dependencies = [ - "clipboard-win", + "clipboard-win 4.5.0", "log", "objc", "objc-foundation", @@ -631,7 +631,7 @@ dependencies = [ "addr2line", "cc", "cfg-if", - "libc 0.2.152", + "libc 0.2.153", "miniz_oxide", "object", "rustc-demangle", @@ -848,7 +848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -887,7 +887,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -941,39 +941,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] -name = "client-native-lib" -version = "0.2.3" -dependencies = [ - "aes-gcm", - "base64 0.21.7", - "bytes", - "fastpbkdf2", - "futures-util", - "hex", - "log", - "rand", - "rand_chacha", - "serde", - "serde_json", - "sha2", - "tokio", - "tokio-tungstenite 0.15.0", - "url", - "webrtc", -] - -[[package]] name = "clipboard-win" version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" dependencies = [ - "error-code", + "error-code 2.3.1", "str-buf", "winapi", ] [[package]] +name = "clipboard-win" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d517d4b86184dbb111d3556a10f1c8a04da7428d2987bf1081602bf11c3aa9ee" +dependencies = [ + "error-code 3.2.0", +] + +[[package]] name = "cocoa" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -985,7 +972,7 @@ dependencies = [ "core-foundation", "core-graphics", "foreign-types 0.5.0", - "libc 0.2.152", + "libc 0.2.153", "objc", ] @@ -1000,7 +987,7 @@ dependencies = [ "core-foundation", "core-graphics-types", "foreign-types 0.3.2", - "libc 0.2.152", + "libc 0.2.153", "objc", ] @@ -1049,7 +1036,7 @@ checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", - "libc 0.2.152", + "libc 0.2.153", "unicode-width", "windows-sys 0.45.0", ] @@ -1067,7 +1054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -1086,7 +1073,7 @@ dependencies = [ "core-foundation", "core-graphics-types", "foreign-types 0.5.0", - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -1097,7 +1084,7 @@ checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -1106,7 +1093,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -1452,6 +1439,12 @@ dependencies = [ ] [[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] name = "enumflags2" version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1536,7 +1529,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "windows-sys 0.52.0", ] @@ -1546,11 +1539,17 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "str-buf", ] [[package]] +name = "error-code" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" + +[[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1614,6 +1613,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix 0.38.30", + "windows-sys 0.52.0", +] + +[[package]] name = "fdeflate" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1845,7 +1855,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "winapi", ] @@ -1855,7 +1865,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "windows-targets 0.48.5", ] @@ -1866,7 +1876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", - "libc 0.2.152", + "libc 0.2.153", "wasi", ] @@ -2335,7 +2345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", - "libc 0.2.152", + "libc 0.2.153", "windows-sys 0.48.0", ] @@ -2390,7 +2400,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -2409,11 +2419,11 @@ dependencies = [ "anyhow", "async-std", "clap", - "client-native-lib", "crossbeam-channel", "eframe", "egui", "env_logger 0.11.1", + "libkeks", "libmpv", "log", "tokio", @@ -2426,8 +2436,8 @@ dependencies = [ "anyhow", "bytes", "clap", - "client-native-lib", "env_logger 0.11.1", + "libkeks", "log", "tokio", ] @@ -2488,9 +2498,31 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libkeks" +version = "0.2.3" +dependencies = [ + "aes-gcm", + "base64 0.21.7", + "bytes", + "fastpbkdf2", + "futures-util", + "hex", + "log", + "rand", + "rand_chacha", + "serde", + "serde_json", + "sha2", + "tokio", + "tokio-tungstenite 0.15.0", + "url", + "webrtc", +] [[package]] name = "libloading" @@ -2539,7 +2571,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0500463acd96259d219abb05dc57e5a076ef04b2db9a2112846929b5f174c96" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "uuid", "winapi", ] @@ -2569,7 +2601,7 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -2593,7 +2625,7 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -2652,7 +2684,7 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "wasi", "windows-sys 0.48.0", ] @@ -2707,6 +2739,15 @@ dependencies = [ ] [[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] name = "nix" version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2714,7 +2755,7 @@ checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags 1.3.2", "cfg-if", - "libc 0.2.152", + "libc 0.2.153", "memoffset 0.6.5", ] @@ -2726,12 +2767,24 @@ checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", - "libc 0.2.152", + "libc 0.2.153", "memoffset 0.7.1", "pin-utils", ] [[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "cfg_aliases", + "libc 0.2.153", +] + +[[package]] name = "nohash-hasher" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2784,7 +2837,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -3002,7 +3055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", - "libc 0.2.152", + "libc 0.2.153", "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", @@ -3160,7 +3213,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "concurrent-queue", - "libc 0.2.152", + "libc 0.2.153", "log", "pin-project-lite", "windows-sys 0.48.0", @@ -3205,6 +3258,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger 0.10.2", + "log", +] + +[[package]] name = "primeorder" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3257,12 +3320,22 @@ dependencies = [ ] [[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "rand_chacha", "rand_core", ] @@ -3372,13 +3445,16 @@ dependencies = [ name = "rift" version = "1.0.0" dependencies = [ + "anyhow", "bytes", "clap", - "client-native-lib", - "env_logger 0.11.1", "humansize", "indicatif", + "libkeks", "log", + "pretty_env_logger", + "rustyline", + "shlex", "tokio", "users", ] @@ -3390,7 +3466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", - "libc 0.2.152", + "libc 0.2.153", "once_cell", "spin 0.5.2", "untrusted 0.7.1", @@ -3406,7 +3482,7 @@ checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", "getrandom", - "libc 0.2.152", + "libc 0.2.153", "spin 0.9.8", "untrusted 0.9.0", "windows-sys 0.48.0", @@ -3469,7 +3545,7 @@ dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", - "libc 0.2.152", + "libc 0.2.153", "linux-raw-sys 0.3.8", "windows-sys 0.48.0", ] @@ -3482,7 +3558,7 @@ checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.2", "errno", - "libc 0.2.152", + "libc 0.2.153", "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] @@ -3544,6 +3620,28 @@ dependencies = [ ] [[package]] +name = "rustyline" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e8936da37efd9b6d4478277f4b2b9bb5cdb37a113e8d63222e58da647e63" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "clipboard-win 5.3.0", + "fd-lock", + "home", + "libc 0.2.153", + "log", + "memchr", + "nix 0.28.0", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "windows-sys 0.52.0", +] + +[[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3647,7 +3745,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-foundation-sys", - "libc 0.2.152", + "libc 0.2.153", "security-framework-sys", ] @@ -3658,7 +3756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" dependencies = [ "core-foundation-sys", - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -3766,12 +3864,18 @@ dependencies = [ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "signal-hook-registry" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", ] [[package]] @@ -3830,7 +3934,7 @@ dependencies = [ "calloop", "calloop-wayland-source", "cursor-icon", - "libc 0.2.152", + "libc 0.2.153", "log", "memmap2", "rustix 0.38.30", @@ -3851,7 +3955,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb62b280ce5a5cba847669933a0948d00904cf83845c944eae96a4738cea1a6" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "smithay-client-toolkit", "wayland-backend", ] @@ -3871,7 +3975,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "winapi", ] @@ -3881,7 +3985,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "windows-sys 0.48.0", ] @@ -4116,7 +4220,7 @@ checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", - "libc 0.2.152", + "libc 0.2.153", "mio", "num_cpus", "parking_lot", @@ -4461,7 +4565,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "log", ] @@ -4995,7 +5099,7 @@ dependencies = [ "cc", "ipnet", "lazy_static", - "libc 0.2.152", + "libc 0.2.153", "log", "nix 0.26.4", "rand", @@ -5308,7 +5412,7 @@ dependencies = [ "cursor-icon", "icrate", "js-sys", - "libc 0.2.152", + "libc 0.2.153", "log", "memmap2", "ndk", @@ -5354,7 +5458,7 @@ version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" dependencies = [ - "libc 0.2.152", + "libc 0.2.153", "once_cell", "pkg-config", ] @@ -5380,7 +5484,7 @@ checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" dependencies = [ "as-raw-xcb-connection", "gethostname 0.4.3", - "libc 0.2.152", + "libc 0.2.153", "libloading", "once_cell", "rustix 0.38.30", @@ -5596,7 +5700,7 @@ checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" dependencies = [ "byteorder", "enumflags2", - "libc 0.2.152", + "libc 0.2.153", "serde", "static_assertions", "zvariant_derive", diff --git a/client-native-export-track/Cargo.toml b/client-native-export-track/Cargo.toml index 83da0d8..1eccbdb 100644 --- a/client-native-export-track/Cargo.toml +++ b/client-native-export-track/Cargo.toml @@ -4,7 +4,7 @@ version = "0.2.3" edition = "2021" [dependencies] -client-native-lib = { path = "../client-native-lib" } +libkeks = { path = "../client-native-lib" } clap = { version = "4.4.18", features = ["derive"] } env_logger = "0.11.1" diff --git a/client-native-export-track/src/main.rs b/client-native-export-track/src/main.rs index 617d46a..7198c30 100644 --- a/client-native-export-track/src/main.rs +++ b/client-native-export-track/src/main.rs @@ -5,7 +5,7 @@ */ use clap::Parser; -use client_native_lib::{ +use libkeks::{ instance::Instance, peer::{Peer, TransportChannel}, protocol::ProvideInfo, @@ -29,7 +29,7 @@ use std::{ fn main() { env_logger::builder() .filter_module("keks_meet_export_track", log::LevelFilter::Info) - .filter_module("client_native_lib", log::LevelFilter::Info) + .filter_module("libkeks", log::LevelFilter::Info) .filter_module("webrtc", log::LevelFilter::Error) .parse_env("LOG") .init(); @@ -87,18 +87,18 @@ struct Handler { } impl EventHandler for Handler { - fn peer_join(&self, _peer: Arc<Peer>) -> client_native_lib::DynFut<()> { + fn peer_join(&self, _peer: Arc<Peer>) -> libkeks::DynFut<()> { Box::pin(async move {}) } - fn peer_leave(&self, _peer: Arc<Peer>) -> client_native_lib::DynFut<()> { + fn peer_leave(&self, _peer: Arc<Peer>) -> libkeks::DynFut<()> { Box::pin(async move {}) } fn resource_added( &self, peer: Arc<Peer>, - info: client_native_lib::protocol::ProvideInfo, + info: libkeks::protocol::ProvideInfo, ) -> DynFut<()> { let id = info.id.clone(); let r = self.requested_track.clone(); @@ -120,7 +120,7 @@ impl EventHandler for Handler { peer: Arc<Peer>, _resource: &ProvideInfo, channel: TransportChannel, - ) -> client_native_lib::DynFut<()> { + ) -> libkeks::DynFut<()> { let peer = Arc::downgrade(&peer); let args = Arc::downgrade(&self._args); Box::pin(async move { diff --git a/client-native-gui/Cargo.toml b/client-native-gui/Cargo.toml index 346343c..573f69a 100644 --- a/client-native-gui/Cargo.toml +++ b/client-native-gui/Cargo.toml @@ -4,7 +4,7 @@ version = "0.2.3" edition = "2021" [dependencies] -client-native-lib = { path = "../client-native-lib" } +libkeks = { path = "../client-native-lib" } clap = { version = "4.4.18", features = ["derive"] } async-std = "1.12.0" diff --git a/client-native-gui/src/chat.rs b/client-native-gui/src/chat.rs index b76c67a..ebfc5a1 100644 --- a/client-native-gui/src/chat.rs +++ b/client-native-gui/src/chat.rs @@ -5,7 +5,7 @@ */ use crate::GuiPeer; use async_std::task::block_on; -use client_native_lib::{ +use libkeks::{ instance::Instance, protocol::{ChatMesssage, RelayMessage}, }; diff --git a/client-native-gui/src/main.rs b/client-native-gui/src/main.rs index d8543d4..13aa9ae 100644 --- a/client-native-gui/src/main.rs +++ b/client-native-gui/src/main.rs @@ -10,7 +10,7 @@ use anyhow::bail; use async_std::task::block_on; use chat::Chat; use clap::Parser; -use client_native_lib::{ +use libkeks::{ instance::Instance, peer::Peer, protocol::{ProvideInfo, RelayMessage}, @@ -55,7 +55,7 @@ struct Args { async fn main() { env_logger::builder() .filter_module("keks_meet", log::LevelFilter::Info) - .filter_module("client_native_lib", log::LevelFilter::Info) + .filter_module("libkeks", log::LevelFilter::Info) .parse_env("LOG") .init(); @@ -264,8 +264,8 @@ impl GuiPeer { impl EventHandler for Handler { fn peer_join( &self, - peer: std::sync::Arc<client_native_lib::peer::Peer>, - ) -> client_native_lib::DynFut<()> { + peer: std::sync::Arc<libkeks::peer::Peer>, + ) -> libkeks::DynFut<()> { self.peers.write().unwrap().insert( peer.id, Arc::new(RwLock::new(GuiPeer { @@ -279,17 +279,17 @@ impl EventHandler for Handler { fn peer_leave( &self, - peer: std::sync::Arc<client_native_lib::peer::Peer>, - ) -> client_native_lib::DynFut<()> { + peer: std::sync::Arc<libkeks::peer::Peer>, + ) -> libkeks::DynFut<()> { self.peers.write().unwrap().remove(&peer.id); Box::pin(async move {}) } fn resource_added( &self, - peer: std::sync::Arc<client_native_lib::peer::Peer>, - info: client_native_lib::protocol::ProvideInfo, - ) -> client_native_lib::DynFut<()> { + peer: std::sync::Arc<libkeks::peer::Peer>, + info: libkeks::protocol::ProvideInfo, + ) -> libkeks::DynFut<()> { if let Some(gp) = self.peers.write().unwrap().get_mut(&peer.id) { gp.write().unwrap().resources.insert( info.id.clone(), @@ -304,9 +304,9 @@ impl EventHandler for Handler { fn resource_removed( &self, - peer: std::sync::Arc<client_native_lib::peer::Peer>, + peer: std::sync::Arc<libkeks::peer::Peer>, id: String, - ) -> client_native_lib::DynFut<()> { + ) -> libkeks::DynFut<()> { if let Some(gp) = self.peers.write().unwrap().get_mut(&peer.id) { gp.write().unwrap().resources.remove(&id); } @@ -315,10 +315,10 @@ impl EventHandler for Handler { fn resource_connected( &self, - peer: std::sync::Arc<client_native_lib::peer::Peer>, - resource: &client_native_lib::protocol::ProvideInfo, - channel: client_native_lib::peer::TransportChannel, - ) -> client_native_lib::DynFut<()> { + peer: std::sync::Arc<libkeks::peer::Peer>, + resource: &libkeks::protocol::ProvideInfo, + channel: libkeks::peer::TransportChannel, + ) -> libkeks::DynFut<()> { if let Some(gp) = self.peers.write().unwrap().get(&peer.id) { let mut gp = gp.write().unwrap(); let peer = gp.peer.clone(); @@ -326,13 +326,13 @@ impl EventHandler for Handler { let state = gr.state.clone(); *gr.state.write().unwrap() = GuiResourceState::Connected; match channel { - client_native_lib::peer::TransportChannel::Track(track) => { + libkeks::peer::TransportChannel::Track(track) => { tokio::task::spawn_blocking(move || { play(peer, track); *state.write().unwrap() = GuiResourceState::Available; }); } - client_native_lib::peer::TransportChannel::DataChannel(_) => { + libkeks::peer::TransportChannel::DataChannel(_) => { warn!("cant handle data channel yet") } } @@ -344,8 +344,8 @@ impl EventHandler for Handler { fn on_relay( &self, peer: Arc<Peer>, - message: &client_native_lib::protocol::RelayMessage, - ) -> client_native_lib::DynFut<()> { + message: &libkeks::protocol::RelayMessage, + ) -> libkeks::DynFut<()> { let guard = self.peers.read().unwrap(); let mut p = guard.get(&peer.id).unwrap().write().unwrap(); match message.clone() { diff --git a/client-native-lib/Cargo.toml b/client-native-lib/Cargo.toml index 617bdb7..70ad7b8 100644 --- a/client-native-lib/Cargo.toml +++ b/client-native-lib/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "client-native-lib" +name = "libkeks" version = "0.2.3" edition = "2021" diff --git a/client-native-lib/src/peer.rs b/client-native-lib/src/peer.rs index f3b6586..353de20 100644 --- a/client-native-lib/src/peer.rs +++ b/client-native-lib/src/peer.rs @@ -27,6 +27,7 @@ pub struct Peer { pub inst: Arc<Instance>, pub peer_connection: RTCPeerConnection, pub remote_provided: RwLock<HashMap<String, ProvideInfo>>, + pub username: RwLock<Option<String>>, pub id: usize, } @@ -63,6 +64,7 @@ impl Peer { remote_provided: Default::default(), inst: inst.clone(), peer_connection, + username: Default::default(), id, }); peer.peer_connection @@ -199,7 +201,8 @@ impl Peer { } RelayMessage::Chat(_) => (), RelayMessage::Identify { username } => { - info!("peer {} is known as {username:?}", self.id) + info!("peer {} is known as {username:?}", self.id); + *self.username.write().await = Some(username); } RelayMessage::Request { id } => { if let Some(res) = self.inst.local_resources.read().await.get(&id) { diff --git a/client-native-rift/Cargo.toml b/client-native-rift/Cargo.toml index f8d5811..d9a7915 100644 --- a/client-native-rift/Cargo.toml +++ b/client-native-rift/Cargo.toml @@ -4,10 +4,10 @@ version = "1.0.0" edition = "2021" [dependencies] -client-native-lib = { path = "../client-native-lib" } +libkeks = { path = "../client-native-lib" } clap = { version = "4.4.18", features = ["derive"] } -env_logger = "0.11.1" +pretty_env_logger = "0.5.0" log = "0.4" tokio = { version = "1.35", features = ["full"] } @@ -16,3 +16,6 @@ bytes = "1.5.0" indicatif = "0.17.7" humansize = "2.1.3" users = "0.11.0" +anyhow = "1.0.81" +shlex = "1.3.0" +rustyline = "14.0.0" diff --git a/client-native-rift/src/file.rs b/client-native-rift/src/file.rs new file mode 100644 index 0000000..bfe32fd --- /dev/null +++ b/client-native-rift/src/file.rs @@ -0,0 +1,109 @@ +use bytes::Bytes; +use humansize::DECIMAL; +use libkeks::{peer::Peer, protocol::ProvideInfo, DynFut, LocalResource}; +use log::{debug, error, info}; +use std::{ + path::PathBuf, + pin::Pin, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, +}; +use tokio::{ + fs::File, + io::{AsyncRead, AsyncReadExt}, + sync::RwLock, +}; + +pub struct FileSender { + pub path: Arc<PathBuf>, + pub info: ProvideInfo, +} + +impl LocalResource for FileSender { + fn info(&self) -> ProvideInfo { + self.info.clone() + } + + fn on_request(&self, peer: Arc<Peer>) -> DynFut<()> { + let id = self.info().id.clone(); + let total_size = self.info().size.unwrap_or(0); + let path = self.path.clone(); + Box::pin(async move { + let channel = peer + .peer_connection + .create_data_channel(&id, None) + .await + .unwrap(); + let pos = Arc::new(AtomicUsize::new(0)); + let reader: Arc<RwLock<Option<Pin<Box<dyn AsyncRead + Send + Sync>>>>> = + Arc::new(RwLock::new(None)); + { + let reader = reader.clone(); + let path = path.clone(); + channel.on_open(Box::new(move || { + let reader = reader.clone(); + Box::pin(async move { + info!("channel open"); + *reader.write().await = Some(Box::pin(File::open(&*path).await.unwrap())); + }) + })) + } + { + let reader = reader.clone(); + channel.on_close(Box::new(move || { + let reader = reader.clone(); + Box::pin(async move { + info!("channel closed"); + *reader.write().await = None; + }) + })) + } + { + let reader = reader.clone(); + let pos = pos.clone(); + let channel2 = channel.clone(); + channel + .on_buffered_amount_low(Box::new(move || { + let pos = pos.clone(); + let reader = reader.clone(); + let channel = channel2.clone(); + Box::pin(async move { + debug!("buffered amount low"); + let mut buf = [0u8; 1 << 15]; + let size = reader + .write() + .await + .as_mut() + .unwrap() + .read(&mut buf) + .await + .unwrap(); + if size == 0 { + info!("reached EOF, closing channel"); + let _ = channel.send_text("end").await; + channel.close().await.unwrap(); + } else { + let progress_size = pos.fetch_add(size, Ordering::Relaxed); + info!( + "sending {size} bytes ({} of {})", + humansize::format_size(progress_size, DECIMAL), + humansize::format_size(total_size, DECIMAL), + ); + channel + .send(&Bytes::copy_from_slice(&buf[..size])) + .await + .unwrap(); + } + }) + })) + .await; + channel.set_buffered_amount_low_threshold(1).await; + } + channel.on_error(Box::new(move |err| { + Box::pin(async move { error!("channel error: {err}") }) + })) + }) + } +} diff --git a/client-native-rift/src/main.rs b/client-native-rift/src/main.rs index 0b6327f..57a4947 100644 --- a/client-native-rift/src/main.rs +++ b/client-native-rift/src/main.rs @@ -4,36 +4,28 @@ Copyright (C) 2023 metamuffin <metamuffin.org> */ -use bytes::Bytes; -use clap::{Parser, Subcommand}; -use client_native_lib::{ +pub mod file; +pub mod port; + +use clap::{ColorChoice, Parser}; +use file::FileSender; +use libkeks::{ instance::Instance, peer::{Peer, TransportChannel}, protocol::ProvideInfo, - Config, DynFut, EventHandler, LocalResource, -}; -use humansize::DECIMAL; -use log::{debug, error, info, warn}; -use std::{ - os::unix::prelude::MetadataExt, - pin::Pin, - process::exit, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, -}; -use tokio::{ - fs::{self, File}, - io::{stdin, stdout, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}, - sync::RwLock, + Config, DynFut, EventHandler, }; +use log::{info, warn}; +use port::PortExposer; +use rustyline::{error::ReadlineError, DefaultEditor}; +use std::{collections::HashMap, os::unix::prelude::MetadataExt, path::PathBuf, sync::Arc}; +use tokio::{fs, sync::RwLock}; use users::get_current_username; fn main() { - env_logger::builder() + pretty_env_logger::formatted_builder() .filter_module("rift", log::LevelFilter::Info) - .filter_module("client_native_lib", log::LevelFilter::Info) + .filter_module("libkeks", log::LevelFilter::Info) .parse_env("LOG") .init(); tokio::runtime::Builder::new_multi_thread() @@ -41,9 +33,11 @@ fn main() { .build() .unwrap() .block_on(run()) + .unwrap(); } #[derive(Parser, Clone)] +/// If no command is provided, rift will enter REPL-mode. pub struct Args { /// keks-meet server used for establishing p2p connection #[clap(long, default_value = "wss://meet.metamuffin.org")] @@ -53,11 +47,24 @@ pub struct Args { username: String, /// pre-shared secret (aka. room name) secret: String, - #[clap(subcommand)] - action: Action, - /// end after completion of the first transfer - #[clap(short, long)] - one_file: bool, + // /// Dispatch a single command after startup + // #[clap(subcommand)] + // command: Option<Command>, +} + +#[derive(Parser, Debug, Clone)] +#[clap(multicall = true, color = ColorChoice::Always)] +pub enum Command { + /// List all peers and their services. + List, + /// Provide a file for download to other peers + Provide { path: PathBuf, id: Option<String> }, + /// Download another peer's files. + Download { id: String, path: Option<PathBuf> }, + /// Expose a local TCP port to other peers. + Expose { port: u16, id: Option<String> }, + /// Forward TCP connections to local port to another peer. + Forward { id: String, port: Option<u16> }, } fn get_username() -> String { @@ -67,79 +74,161 @@ fn get_username() -> String { .to_owned() } -async fn run() { +async fn run() -> anyhow::Result<()> { let args = Args::parse(); - + let state = Arc::new(RwLock::new(State { + requested: Default::default(), + })); let inst = Instance::new( Config { signaling_uri: args.signaling_uri.clone(), username: args.username.clone(), }, Arc::new(Handler { - args: Arc::new(args.clone()), + state: state.clone(), }), ) .await; inst.join(Some(&args.secret)).await; - match &args.action { - Action::Send { filename } => { - inst.add_local_resource(Box::new(FileSender { - info: ProvideInfo { - id: "the-file".to_string(), // we only share a single file so its fine - kind: "file".to_string(), - track_kind: None, - label: Some(filename.clone().unwrap_or("stdin".to_string())), - size: if let Some(filename) = &filename { - Some(fs::metadata(filename).await.unwrap().size() as usize) - } else { - None - }, + inst.spawn_ping().await; + tokio::task::spawn(inst.clone().receive_loop()); + + let mut rl = DefaultEditor::new()?; + loop { + match rl.readline("> ") { + Ok(line) => match Command::try_parse_from(shlex::split(&line).unwrap()) { + Ok(command) => match command { + Command::List => { + let peers = inst.peers.read().await; + println!("{} clients available", peers.len()); + for p in peers.values() { + let username = p + .username + .read() + .await + .clone() + .unwrap_or("<unknown>".to_string()); + println!("{username}:"); + for (rid, r) in p.remote_provided.read().await.iter() { + println!( + "\t{rid:?}: {} {:?}", + r.kind, + r.label.clone().unwrap_or_default() + ) + } + } + } + Command::Provide { path, id } => { + inst.add_local_resource(Box::new(FileSender { + info: ProvideInfo { + id: id.unwrap_or("file".to_owned()), + kind: "file".to_string(), + track_kind: None, + label: Some( + path.file_name().unwrap().to_str().unwrap().to_string(), + ), + size: Some(fs::metadata(&path).await.unwrap().size() as usize), + }, + path: path.into(), + })) + .await; + } + Command::Download { id, path } => { + let peers = inst.peers.read().await; + 'outer: for p in peers.values() { + for (rid, r) in p.remote_provided.read().await.iter() { + if rid == &id { + if r.kind == "file" { + p.request_resource(id).await; + } else { + warn!("not a file"); + } + break 'outer; + } + } + } + } + Command::Expose { port, id } => { + inst.add_local_resource(Box::new(PortExposer { + port, + info: ProvideInfo { + kind: "port".to_string(), + id: id.unwrap_or(format!("p{port}")), + track_kind: None, + label: Some(format!("port {port}")), + size: None, + }, + })) + .await; + } + Command::Forward { id, port } => {} }, - reader_factory: args.action, - })) - .await; + Err(err) => err.print().unwrap(), + }, + Err(ReadlineError::Interrupted) => { + info!("interrupted; exiting..."); + break; + } + Err(e) => Err(e)?, } - _ => (), } - inst.spawn_ping().await; - inst.receive_loop().await; + // match &args.action { + // Action::Send { filename } => { + // inst.add_local_resource(Box::new(FileSender { + // info: ProvideInfo { + // id: "the-file".to_string(), // we only share a single file so its fine + // kind: "file".to_string(), + // track_kind: None, + // label: Some(filename.clone().unwrap_or("stdin".to_string())), + // size: if let Some(filename) = &filename { + // Some(fs::metadata(filename).await.unwrap().size() as usize) + // } else { + // None + // }, + // }, + // reader_factory: args.action, + // })) + // .await; + // } + // _ => (), + // } + Ok(()) +} - tokio::signal::ctrl_c().await.unwrap(); - error!("interrupt received, exiting"); +struct State { + requested: HashMap<String, Box<dyn RequestHandler>>, +} +pub trait RequestHandler: Send + Sync + 'static { + } #[derive(Clone)] struct Handler { - args: Arc<Args>, + state: Arc<RwLock<State>>, } impl EventHandler for Handler { - fn peer_join(&self, _peer: Arc<Peer>) -> client_native_lib::DynFut<()> { + fn peer_join(&self, _peer: Arc<Peer>) -> libkeks::DynFut<()> { Box::pin(async move {}) } - fn peer_leave(&self, _peer: Arc<Peer>) -> client_native_lib::DynFut<()> { + fn peer_leave(&self, _peer: Arc<Peer>) -> libkeks::DynFut<()> { Box::pin(async move {}) } - fn resource_added( - &self, - peer: Arc<Peer>, - info: client_native_lib::protocol::ProvideInfo, - ) -> DynFut<()> { + fn resource_added(&self, peer: Arc<Peer>, info: libkeks::protocol::ProvideInfo) -> DynFut<()> { let id = info.id.clone(); - let args = self.args.clone(); Box::pin(async move { - match &args.action { - Action::Receive { .. } => { - if info.kind == "file" { - peer.request_resource(id).await; - } - } - _ => (), - } + // match &args.action { + // Action::Receive { .. } => { + // if info.kind == "file" { + // peer.request_resource(id).await; + // } + // } + // _ => (), + // } }) } fn resource_removed(&self, _peer: Arc<Peer>, _id: String) -> DynFut<()> { @@ -151,211 +240,108 @@ impl EventHandler for Handler { _peer: Arc<Peer>, resource: &ProvideInfo, channel: TransportChannel, - ) -> client_native_lib::DynFut<()> { + ) -> libkeks::DynFut<()> { let resource = resource.clone(); let s = self.clone(); Box::pin(async move { - match channel { - TransportChannel::Track(_) => warn!("wrong type"), - TransportChannel::DataChannel(dc) => { - if resource.kind != "file" { - return error!("we got a non-file resource for some reason…"); - } - let pos = Arc::new(AtomicUsize::new(0)); - let writer: Arc<RwLock<Option<Pin<Box<dyn AsyncWrite + Send + Sync>>>>> = - Arc::new(RwLock::new(None)); - { - let writer = writer.clone(); - let s = s.clone(); - dc.on_open(Box::new(move || { - let s = s.clone(); - let writer = writer.clone(); - Box::pin(async move { - info!("channel opened"); - *writer.write().await = Some(s.args.action.create_writer().await) - }) - })); - } - { - let writer = writer.clone(); - let args = s.args.clone(); - dc.on_close(Box::new(move || { - let writer = writer.clone(); - let args = args.clone(); - Box::pin(async move { - info!("channel closed"); - *writer.write().await = None; - if args.one_file { - exit(0); - } - }) - })); - } - { - let writer = writer.clone(); - dc.on_message(Box::new(move |mesg| { - let writer = writer.clone(); - let pos = pos.clone(); - Box::pin(async move { - // TODO - if mesg.is_string { - let s = String::from_utf8((&mesg.data).to_vec()).unwrap(); - if &s == "end" { - info!("EOF reached") - } - } else { - let pos = pos.fetch_add(mesg.data.len(), Ordering::Relaxed); - info!( - "recv {:?} ({} of {})", - mesg.data.len(), - humansize::format_size(pos, DECIMAL), - humansize::format_size(resource.size.unwrap_or(0), DECIMAL), - ); - writer - .write() - .await - .as_mut() - .unwrap() - .write_all(&mesg.data) - .await - .unwrap(); - } - }) - })) - } - dc.on_error(Box::new(move |err| { - Box::pin(async move { - error!("data channel errored: {err}"); - }) - })); - } - } + // match channel { + // TransportChannel::Track(_) => warn!("wrong type"), + // TransportChannel::DataChannel(dc) => { + // if resource.kind != "file" { + // return error!("we got a non-file resource for some reason…"); + // } + // let pos = Arc::new(AtomicUsize::new(0)); + // let writer: Arc<RwLock<Option<Pin<Box<dyn AsyncWrite + Send + Sync>>>>> = + // Arc::new(RwLock::new(None)); + // { + // let writer = writer.clone(); + // let s = s.clone(); + // dc.on_open(Box::new(move || { + // let s = s.clone(); + // let writer = writer.clone(); + // Box::pin(async move { + // info!("channel opened"); + // *writer.write().await = Some(s.args.action.create_writer().await) + // }) + // })); + // } + // { + // let writer = writer.clone(); + // dc.on_close(Box::new(move || { + // let writer = writer.clone(); + // Box::pin(async move { + // info!("channel closed"); + // *writer.write().await = None; + // exit(0); + // }) + // })); + // } + // { + // let writer = writer.clone(); + // dc.on_message(Box::new(move |mesg| { + // let writer = writer.clone(); + // let pos = pos.clone(); + // Box::pin(async move { + // // TODO + // if mesg.is_string { + // let s = String::from_utf8((&mesg.data).to_vec()).unwrap(); + // if &s == "end" { + // info!("EOF reached") + // } + // } else { + // let pos = pos.fetch_add(mesg.data.len(), Ordering::Relaxed); + // info!( + // "recv {:?} ({} of {})", + // mesg.data.len(), + // humansize::format_size(pos, DECIMAL), + // humansize::format_size(resource.size.unwrap_or(0), DECIMAL), + // ); + // writer + // .write() + // .await + // .as_mut() + // .unwrap() + // .write_all(&mesg.data) + // .await + // .unwrap(); + // } + // }) + // })) + // } + // dc.on_error(Box::new(move |err| { + // Box::pin(async move { + // error!("data channel errored: {err}"); + // }) + // })); + // } + // } }) } } -#[derive(Subcommand, Clone)] -pub enum Action { - /// Send a file - Send { filename: Option<String> }, - /// Receive a file - Receive { filename: Option<String> }, -} - -impl Action { - pub async fn create_writer(&self) -> Pin<Box<dyn AsyncWrite + Send + Sync + 'static>> { - match self { - Action::Receive { filename } => { - if let Some(filename) = filename { - Box::pin(File::create(filename).await.unwrap()) - } else { - Box::pin(stdout()) - } - } - _ => unreachable!(), - } - } - pub async fn create_reader(&self) -> Pin<Box<dyn AsyncRead + Send + Sync + 'static>> { - match self { - Action::Send { filename } => { - if let Some(filename) = filename { - Box::pin(File::open(filename).await.unwrap()) - } else { - Box::pin(stdin()) - } - } - _ => unreachable!(), - } - } -} - -struct FileSender { - reader_factory: Action, // TODO use Box<dyn Fn() -> DynFut<dyn AsyncRead + Send + Sync> + Send + Sync>, - info: ProvideInfo, -} - -impl LocalResource for FileSender { - fn info(&self) -> ProvideInfo { - self.info.clone() - } - - fn on_request(&self, peer: Arc<Peer>) -> DynFut<()> { - let id = self.info().id.clone(); - let total_size = self.info().size.unwrap_or(0); - let reader_factory = self.reader_factory.clone(); - Box::pin(async move { - let channel = peer - .peer_connection - .create_data_channel(&id, None) - .await - .unwrap(); - let pos = Arc::new(AtomicUsize::new(0)); - let reader: Arc<RwLock<Option<Pin<Box<dyn AsyncRead + Send + Sync>>>>> = - Arc::new(RwLock::new(None)); - { - let reader = reader.clone(); - let reader_factory = reader_factory.clone(); - channel.on_open(Box::new(move || { - let reader = reader.clone(); - Box::pin(async move { - info!("channel open"); - *reader.write().await = Some(reader_factory.create_reader().await); - }) - })) - } - { - let reader = reader.clone(); - channel.on_close(Box::new(move || { - let reader = reader.clone(); - Box::pin(async move { - info!("channel closed"); - *reader.write().await = None; - }) - })) - } - { - let reader = reader.clone(); - let pos = pos.clone(); - let channel2 = channel.clone(); - channel - .on_buffered_amount_low(Box::new(move || { - let pos = pos.clone(); - let reader = reader.clone(); - let channel = channel2.clone(); - Box::pin(async move { - debug!("buffered amount low"); - let mut buf = [0u8; 1 << 15]; - let size = reader - .write() - .await - .as_mut() - .unwrap() - .read(&mut buf) - .await - .unwrap(); - if size == 0 { - info!("reached EOF, closing channel"); - channel.close().await.unwrap(); - } else { - let progress_size = pos.fetch_add(size, Ordering::Relaxed); - info!( - "sending {size} bytes ({} of {})", - humansize::format_size(progress_size, DECIMAL), - humansize::format_size(total_size, DECIMAL), - ); - channel - .send(&Bytes::copy_from_slice(&buf[..size])) - .await - .unwrap(); - } - }) - })) - .await; - channel.set_buffered_amount_low_threshold(1).await; - } - channel.on_error(Box::new(move |err| { - Box::pin(async move { error!("channel error: {err}") }) - })) - }) - } -} +// impl Action { +// pub async fn create_writer(&self) -> Pin<Box<dyn AsyncWrite + Send + Sync + 'static>> { +// match self { +// Action::Receive { filename } => { +// if let Some(filename) = filename { +// Box::pin(File::create(filename).await.unwrap()) +// } else { +// Box::pin(stdout()) +// } +// } +// _ => unreachable!(), +// } +// } +// pub async fn create_reader(&self) -> Pin<Box<dyn AsyncRead + Send + Sync + 'static>> { +// match self { +// Action::Send { filename } => { +// if let Some(filename) = filename { +// Box::pin(File::open(filename).await.unwrap()) +// } else { +// Box::pin(stdin()) +// } +// } +// _ => unreachable!(), +// } +// } +// } diff --git a/client-native-rift/src/port.rs b/client-native-rift/src/port.rs new file mode 100644 index 0000000..ae56f2c --- /dev/null +++ b/client-native-rift/src/port.rs @@ -0,0 +1,99 @@ +use bytes::Bytes; +use libkeks::{peer::Peer, protocol::ProvideInfo, DynFut, LocalResource}; +use log::{debug, error, info, warn}; +use std::{pin::Pin, sync::Arc}; +use tokio::{ + io::{AsyncRead, AsyncReadExt}, + net::TcpStream, + sync::RwLock, +}; + +pub struct PortExposer { + pub port: u16, + pub info: ProvideInfo, +} + +impl LocalResource for PortExposer { + fn info(&self) -> ProvideInfo { + self.info.clone() + } + + fn on_request(&self, peer: Arc<Peer>) -> DynFut<()> { + let id = self.info().id.clone(); + let port = self.port; + Box::pin(async move { + let channel = peer + .peer_connection + .create_data_channel(&id, None) + .await + .unwrap(); + let reader: Arc<RwLock<Option<Pin<Box<dyn AsyncRead + Send + Sync>>>>> = + Arc::new(RwLock::new(None)); + { + let reader = reader.clone(); + let channel2 = channel.clone(); + channel.on_open(Box::new(move || { + let reader = reader.clone(); + Box::pin(async move { + info!("channel open"); + match TcpStream::connect(("127.0.0.1", port)).await { + Ok(stream) => { + *reader.write().await = Some(Box::pin(stream)); + } + Err(e) => { + warn!("upstream connect failed: {e}"); + channel2.close().await.unwrap(); + } + } + }) + })) + } + { + let reader = reader.clone(); + channel.on_close(Box::new(move || { + let reader = reader.clone(); + Box::pin(async move { + info!("channel closed"); + *reader.write().await = None; + }) + })) + } + { + let reader = reader.clone(); + let channel2 = channel.clone(); + channel + .on_buffered_amount_low(Box::new(move || { + let reader = reader.clone(); + let channel = channel2.clone(); + Box::pin(async move { + debug!("buffered amount low"); + let mut buf = [0u8; 1 << 15]; + let size = reader + .write() + .await + .as_mut() + .unwrap() + .read(&mut buf) + .await + .unwrap(); + if size == 0 { + info!("reached EOF, closing channel"); + let _ = channel.send_text("end").await; + channel.close().await.unwrap(); + } else { + channel + .send(&Bytes::copy_from_slice(&buf[..size])) + .await + .unwrap(); + } + }) + })) + .await; + channel.set_buffered_amount_low_threshold(1).await; + } + channel.on_error(Box::new(move |err| { + Box::pin(async move { error!("channel error: {err}") }) + })) + }) + } +} |