From 7130f872bc1d5eacb0b7e848cbd9d163653d7852 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Sat, 18 May 2024 01:43:53 +0300 Subject: [PATCH] init commit --- Cargo.lock | 629 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 13 + LICENSE | 13 + README.md | 12 + src/chat/chat_client.rs | 172 +++++++++++ src/chat/chat_packet.rs | 87 ++++++ src/chat/chat_server.rs | 177 +++++++++++ src/chat/mod.rs | 7 + src/main.rs | 104 +++++++ 9 files changed, 1214 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/chat/chat_client.rs create mode 100644 src/chat/chat_packet.rs create mode 100644 src/chat/chat_server.rs create mode 100644 src/chat/mod.rs create mode 100644 src/main.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..b35e3e3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,629 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytebuffer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7bfaf7cd08cacd74cdc6b521c37ac39cbc92692e5ab5c21ed5657a749b577c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "clearscreen" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8c93eb5f77c9050c7750e14f13ef1033a40a0aac70c6371535b6763a01438c" +dependencies = [ + "nix", + "terminfo", + "thiserror", + "which", + "winapi", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "easymsg" +version = "0.1.0" +dependencies = [ + "bytebuffer", + "byteorder", + "chrono", + "clearscreen", + "getch", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13990e2d5b29e1770ddf7fc000afead4acb9bd8f8a9602de63bf189e261b1ba8" +dependencies = [ + "libc", + "termios", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "syn" +version = "2.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminfo" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666cd3a6681775d22b200409aad3b089c5b99fb11ecdd8a204d9d62f8148498f" +dependencies = [ + "dirs", + "fnv", + "nom", + "phf", + "phf_codegen", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "thiserror" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "which" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6ef4f16 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "easymsg" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bytebuffer = "2.2.0" +byteorder = "1.5.0" +chrono = "0.4.38" +getch = "0.3.1" +clearscreen = "3.0.0" \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..07b7a81 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document, and changing it is allowed as long +as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..46dff43 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# easy_msg +simple cli messenger on rust + +# how to use +start server: +``` +./easymsg server SERVER_NAME IP:PORT +``` +connect server: +``` +./easymsg client CLIENT_NAME IP:PORT +``` \ No newline at end of file diff --git a/src/chat/chat_client.rs b/src/chat/chat_client.rs new file mode 100644 index 0000000..ceea721 --- /dev/null +++ b/src/chat/chat_client.rs @@ -0,0 +1,172 @@ +use std::cell::RefCell; +use std::io::{Error, Write}; +use std::net::TcpStream; +use std::sync::{Arc, Mutex}; +use chrono::prelude::*; + +use super::chat_packet::*; + +#[derive(Debug)] +pub struct Console { + pub input: String, + pub lines: Vec +} + +impl Console { + pub fn new() -> Console { + Console { + input: String::new(), + lines: Vec::new() + } + } + + pub fn meow(&mut self) { + self.lines.push("meow".to_string()); + self.update(); + } + + pub fn add_line(&mut self, text: String) { + self.lines.push(text); + self.update(); + } + + pub fn run_input_loop(this: Arc>, on_enter: fn(&mut TcpStream, String) -> (), client: &mut TcpStream) -> Result<(), Error> { + let ge = getch::Getch::new(); + loop { + match ge.getch() { + Ok(i) => { + let mut th = this.lock().unwrap(); + + match i { + 127 => { + if th.input.len() > 0 { + th.input = (&th.input[..th.input.len()-1]).to_string(); + } + th.update(); + }, 10 => { + // th.meow(); + on_enter(client, th.input.clone()); + th.input = String::new(); + th.update(); + }, _ => { + let ch = &String::from_utf8(vec![i]).unwrap(); + // let was = th.input.clone(); + th.input.push_str(ch); + th.update(); + } + } + }, + Err(_) => {}, + } + }; + } + + pub fn update(&mut self) { + clearscreen::clear().unwrap(); + + let mut text = "\n".to_string(); + + for l in self.lines.as_slice() { + text += &(l.to_string() + "\n"); + } + + text += &("> ".to_string() + self.input.as_str()); + + std::io::stdout() + .write_all(text.as_bytes()) + .unwrap(); + + std::io::stdout() + .flush() + .unwrap(); + } +} + +#[derive(Debug)] +pub struct ChatClient { + pub me: String, + pub messages: Vec, + pub chat_name: String, + pub stream: Option, + pub console: Arc> +} + +impl ChatClient { + pub fn new(name: String, console: Arc>) -> Self { + ChatClient { + me: name, + messages: Vec::new(), + chat_name: String::from("Chat"), + stream: None, + console: console + } + } + + pub fn on_enter(stream: &mut TcpStream, text: String) { + Self::send_message(stream, text).unwrap(); + } + + pub fn on_message(&mut self, msg: &Message) { + self.console.lock().unwrap().add_line(format!("{} | {} > {}", msg.sent_at, msg.author, msg.text)); + } + + pub fn communicate(&mut self) -> Result<(), Error> { + Self::send_join(&mut self.stream.as_mut().unwrap(), &self.me)?; + + loop { + let mut packet = read_packet(&mut self.stream.as_mut().unwrap())?; + + // dbg!(&packet); + + match packet.id { + b'm' => { + let msg = Message::new( + packet.buffer.read_string()?, + packet.buffer.read_string()?, + DateTime::from_timestamp(packet.buffer.read_i64()?,0).unwrap() + ); + + self.on_message(&msg); + + self.messages.push(msg); + }, b'n' => { + self.chat_name = packet.buffer.read_string()?; + }, _ => { + println!("packet error"); + break; + } + } + } + + close_stream(&mut self.stream.as_mut().unwrap())?; + Ok(()) + } + + pub fn connect(&mut self, host: String) -> Result<(), Error> { + self.stream = Some(TcpStream::connect(host.clone())?); + + Ok(()) + } + + pub fn send_message(stream: &mut TcpStream, text: String) -> Result<(), Error> { + let packet = ChatPacket::build(b's', &|p| { + p.buffer.write_string(&text); + }); + + send_packet(stream, &packet) + } + + pub fn send_join(stream: &mut TcpStream, name: &String) -> Result<(), Error> { + let packet = ChatPacket::build(b'j', &|p| { + p.buffer.write_string(&name); + }); + + send_packet(stream, &packet) + } + + pub fn send_quit(stream: &mut TcpStream) -> Result<(), Error> { + let packet = ChatPacket::empty(b'q'); + + send_packet(stream, &packet) + } +} \ No newline at end of file diff --git a/src/chat/chat_packet.rs b/src/chat/chat_packet.rs new file mode 100644 index 0000000..c61cc73 --- /dev/null +++ b/src/chat/chat_packet.rs @@ -0,0 +1,87 @@ +use std::io::{Read, Write, Error}; +use std::net::{TcpStream, Shutdown}; + +use bytebuffer::ByteBuffer; +use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; + +use chrono::DateTime; +use chrono::Utc; + +#[derive(Clone, Debug)] +pub struct Message { + pub author: String, + pub text: String, + pub sent_at: DateTime +} + +impl Message { + pub fn new(text: String, + author: String, + sent_at: DateTime) -> Message { + Message { + author, + text, + sent_at + } + } + + pub fn at_now(text: String, author: String) -> Message { + Message { + author, + text, + sent_at: Utc::now() + } + } +} + +pub fn close_stream(stream: &mut TcpStream) -> Result<(), Error> { + stream.shutdown(Shutdown::Both) +} + +#[derive(Debug)] +pub struct ChatPacket { + pub id: u8, + pub buffer: ByteBuffer +} + +impl ChatPacket { + pub fn new(id: u8, buffer: ByteBuffer) -> ChatPacket { + ChatPacket { id, buffer } + } + + pub fn empty(id: u8) -> ChatPacket { + ChatPacket { id, buffer: ByteBuffer::new() } + } + + pub fn from_bytes(id: u8, bytes: &[u8]) -> ChatPacket { + ChatPacket { id, buffer: ByteBuffer::from_bytes(bytes) } + } + + pub fn build(id: u8, builder: &dyn Fn(&mut ChatPacket) -> ()) -> ChatPacket { + let mut packet = Self::empty(id); + builder(&mut packet); + packet + } +} + +pub fn read_packet(stream: &mut TcpStream) -> Result { + let length = stream.read_u64::()? as usize; + + let packet_id = stream.read_u8()?; + let mut data: Vec = vec![0; length - 1]; + stream.read(&mut data)?; + + Ok(ChatPacket::from_bytes(packet_id, &data)) +} + +pub fn send_packet(stream: &mut TcpStream, packet: &ChatPacket) -> Result<(), Error> { + let mut buf = ByteBuffer::new(); + + buf.write_u8(packet.id); + buf.write(packet.buffer.as_bytes())?; + + stream.write_u64::(buf.len() as u64)?; + stream.write(&buf.as_bytes())?; + + Ok(()) +} \ No newline at end of file diff --git a/src/chat/chat_server.rs b/src/chat/chat_server.rs new file mode 100644 index 0000000..18efc23 --- /dev/null +++ b/src/chat/chat_server.rs @@ -0,0 +1,177 @@ +use std::net::{TcpListener, TcpStream}; +use std::sync::Mutex; +use std::sync::Arc; +use std::thread; +use std::io::Error; +use std::time::Duration; + +use super::chat_packet::*; + +pub struct ChatServer { + pub host: String, + pub name: String, + pub messages: Vec, + pub conns: Vec +} + +pub fn send_packet_all(server: &mut ChatServer, packet: ChatPacket) -> Result<(), Error> { + for stream in &mut server.conns { + send_packet(stream, &packet)?; + } + Ok(()) +} + +static mut MEOW_TIME: u32 = 0; + +fn meow() { + unsafe { + MEOW_TIME += 1; + println!("meow {}", MEOW_TIME); + } +} + +impl ChatServer { + pub fn new(host: String, name: String) -> Self { + ChatServer { + host: host, + name: name, + messages: Vec::new(), + conns: Vec::new() + } + } + + pub fn send_message(&mut self, msg: Message) -> Result<(), Error> { + println!("{} | {} > {}", msg.sent_at, msg.author, msg.text); + + let packet = ChatPacket::build(b'm', &|p| { + p.buffer.write_string(&msg.text); + p.buffer.write_string(&msg.author); + p.buffer.write_i64(msg.sent_at.timestamp()); + }); + + send_packet_all(self, packet)?; + self.messages.push(msg); + + Ok(()) + } + + pub fn send_message_packet(&mut self, stream: &mut TcpStream, msg: &Message) -> Result<(), Error> { + let packet = ChatPacket::build(b'm', &|p| { + p.buffer.write_string(&msg.text); + p.buffer.write_string(&msg.author); + p.buffer.write_i64(msg.sent_at.timestamp()); + }); + + send_packet(stream, &packet)?; + + // println!("send message packet"); + + Ok(()) + } + + pub fn send_chat_name(&mut self, stream: &mut TcpStream) -> Result<(), Error> { + let packet = ChatPacket::build(b'n', &|p| { + p.buffer.write_string(&self.name); + }); + + send_packet(stream, &packet)?; + + // println!("send chat name"); + + Ok(()) + } + + pub fn join_client(this: Arc>, stream: &mut TcpStream, name: String) -> Result<(), Error> { + println!("connected lol {}", name.clone()); + + // dbg!(&this.lock().unwrap().messages); + + this.lock().unwrap().send_chat_name(stream)?; + + let messages = &this.lock().unwrap().messages.clone(); + + for m in messages { + this.lock().unwrap().send_message_packet(stream, m)?; + } + + loop { + let mut packet = read_packet(stream)?; + + match packet.id { + b's' => { + this.lock().unwrap().send_message(Message::at_now(packet.buffer.read_string()?, name.clone()))?; + }, + _ => { + break; + } + } + } + + close_stream(stream)?; + Ok(()) + } + + pub fn accept_client(this: Arc>, stream: &mut TcpStream) -> Result<(), Error> { + println!("stream got!!! lol {:?}", &stream); + + let mut packet: ChatPacket = read_packet(stream)?; + + println!("packet got!!! lol {:?}", &packet); + + match packet.id { + b'j' => { + Self::join_client(this, stream, packet.buffer.read_string()?) + }, _ => { + + close_stream(stream)?; + Ok(()) + } + } + } + + pub fn run(self) { + let listener: TcpListener = TcpListener::bind(self.host.clone()).expect("bind error"); + + println!("binded lol {}", self.host.clone()); + + let arc_self = Arc::new(Mutex::new(self)); + + loop { + let (mut socket, _) = listener.accept().expect("accept error"); + + let local_self = arc_self.clone(); + + thread::spawn(move || { + meow(); + + let socket_clone = match socket.try_clone() { + Ok(i) => i, + Err(_) => { return }, + }; + + meow(); + + let mut ind: usize = 0; + + { + let mut se = local_self.lock().unwrap(); + ind = se.conns.len(); + se.conns.push(socket_clone); + } + + meow(); + + match Self::accept_client(local_self.clone(), &mut socket) { + Ok(_) => { println!("disconnected normally") }, + Err(_) => { println!("trahnutiy disconnect XDDDDDDDDDDD))))))000)0)0)))") }, + }; + + meow(); + + local_self.lock().unwrap().conns.remove(ind); + + meow(); + }); + } + } +} \ No newline at end of file diff --git a/src/chat/mod.rs b/src/chat/mod.rs new file mode 100644 index 0000000..ed52919 --- /dev/null +++ b/src/chat/mod.rs @@ -0,0 +1,7 @@ +pub mod chat_client; +pub mod chat_server; +pub mod chat_packet; + +pub use chat_client::*; +pub use chat_server::*; +pub use chat_packet::*; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..381adf7 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,104 @@ +mod chat; +use chat::*; + +use std::env; +use chrono::Utc; +use std::sync::{Arc, Mutex}; +use std::cell::{RefCell}; +use std::thread; +use std::pin::pin; + + +fn main() { + let args: Vec = Vec::from_iter(env::args()); + + if args.len() > 1 { + if args[1].as_str() == "server" { + let mut server = ChatServer::new( + args[3].clone(), + args[2].clone()); + server.messages.push(Message { + author: "avtor".to_string(), + text: "text".to_string(), + sent_at: Utc::now() + }); + server.run(); + } else if args[1].as_str() == "client" { + let console = Arc::new(Mutex::new(Console::new())); + + console.lock().unwrap().update(); + + let mut client = ChatClient::new(args[2].clone(), console.clone()); + + let console_copy = console.clone(); + + client.connect(args[3].clone()).unwrap(); + + let mut input_stream = client.stream.as_mut().unwrap().try_clone().unwrap(); + thread::spawn(move || { + Console::run_input_loop( + console_copy, + ChatClient::on_enter, + &mut input_stream); + }); + + client.communicate().unwrap(); + } + } + + // let моя_коза = МояГоворящаяКоза::создать(true); + // моя_коза.финты_ушами(); + // моя_коза.поздароваться(); + // моя_коза.привет("Товарищ Сталин".to_string()); +} + +// struct МояГоворящаяКоза { +// здоровье: u128, +// еда_в_холодильнике: u8, +// возраст: u128, +// коммунист: bool, +// кличка: String +// } + +// impl МояГоворящаяКоза { +// fn создать(коммунист: bool) -> МояГоворящаяКоза { +// МояГоворящаяКоза { +// здоровье: 9999999999999999999, +// еда_в_холодильнике: 0, +// возраст: 9, +// коммунист: коммунист, +// кличка: "Ленин".to_string() +// } +// } + +// fn финты_ушами(&self) { +// println!("{} крутит финты ушами", self.кличка); +// } + +// fn поздароваться(&self) { +// println!("{} поздаровался", self.кличка); +// } +// } + + +// trait ГоворящееЧтото { +// fn моя_кличка(&self) -> &String; + +// fn привет(&self, имя: String) { +// println!("{} сказал привет {}", self.моя_кличка(), имя); +// } +// } + +// impl ГоворящееЧтото for МояГоворящаяКоза { +// fn моя_кличка(&self) -> &String { +// &self.кличка +// } +// } + +// console.run_event_loop(): +// on_enter: +// client.send_message() + +// client.connect(): +// on_message: +// console.print() \ No newline at end of file