diff --git a/.gitignore b/.gitignore index ea8c4bf..757fe15 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -/target +target/ +logs/ +test.png diff --git a/Cargo.lock b/Cargo.lock index 39961f0..3a3014b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,633 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "bytemuck" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" + +[[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 = "chrono" +version = "0.4.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.4", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "communication-layer" version = "0.1.0" +dependencies = [ + "chrono", + "fern", + "image", + "ipnet", + "local-ip-address", + "log", + "rand", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fern" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +dependencies = [ + "log", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + +[[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 = "image" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b4f005360d32e9325029b38ba47ebd7a56f3316df09249368939562d518645" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "gif", + "num-traits", + "png", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[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 = "local-ip-address" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136ef34e18462b17bf39a7826f8f3bbc223341f8e83822beb8b77db9a3d49696" +dependencies = [ + "libc", + "neli", + "thiserror", + "windows-sys", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "neli" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1100229e06604150b3becd61a4965d5c70f3be1759544ea7274166f4be41ef43" +dependencies = [ + "byteorder", + "libc", + "log", + "neli-proc-macros", +] + +[[package]] +name = "neli-proc-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4" +dependencies = [ + "either", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[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 = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[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 2.0.53", + "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 2.0.53", + "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 = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" diff --git a/Cargo.toml b/Cargo.toml index 5e05d0b..1d6ebb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = "0.4.35" +fern = "0.6.2" +image = { version = "0.25.0", default-features = false, features = ["png","ff","gif"] } +ipnet = "2.9.0" +local-ip-address = "0.6.1" +log = "0.4.21" +rand = "0.8.5" diff --git a/README.md b/README.md index a2f6cf6..074cdf6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ # virtual-camera -Library and server for dissemination of images obtained from the world server. \ No newline at end of file +Library and server for dissemination of images obtained from the world server. + +Currently uses TCP to stream images from the world server. Images are saved temporarily for testing purposes. + +## Development + +For development, you must first have Rust installed. This can be done by following the instructions found at [https://rustup.rs/](https://rustup.rs/). Once this is done, clone this repository, and in the root folder of the repository, run `cargo build --release`. This will both build the dependencies, install the correct toolchains, and create a final executable. + +## Testing + +To test this, first download the `comms-testing` branch of the World Server repository, open the `tennis` project, and run the project. Once this is done, build the latest version of this repository, as mentioned above. Finally, run this project, using `cargo run`. diff --git a/logScreeenshot.png b/logScreeenshot.png new file mode 100644 index 0000000..489ae56 Binary files /dev/null and b/logScreeenshot.png differ diff --git a/logs/2024-03-21_14.47.log b/logs/2024-03-21_14.47.log new file mode 100644 index 0000000..a209b31 --- /dev/null +++ b/logs/2024-03-21_14.47.log @@ -0,0 +1,7 @@ +2024-03-21T14:47:31.759962308-04:00 - [INFO, communication_layer] - aggregating all IPs... This may take several minutes... +2024-03-21T14:47:36.825148581-04:00 - [INFO, communication_layer] - Stream connected to address: Ok(192.168.0.80:55001) +2024-03-21T14:47:36.825292754-04:00 - [INFO, communication_layer] - Start reading... +2024-03-21T14:47:38.021199638-04:00 - [INFO, communication_layer] - Image successfully recieved +2024-03-21T14:47:38.021453459-04:00 - [INFO, communication_layer] - Building image... +2024-03-21T14:47:39.127447553-04:00 - [INFO, communication_layer] - Image built, saving to file... +2024-03-21T14:47:44.733286335-04:00 - [INFO, communication_layer] - image saved! diff --git a/notes.md b/notes.md index 3e724a4..9a9e5ca 100644 --- a/notes.md +++ b/notes.md @@ -1,5 +1,13 @@ +<<<<<<< HEAD +Communication layer: +Add image resolution to initial handshake + unity: send x and y resolution + SOC: send back colour bit depth + unity: check bitdepth before beginning image transfer +======= Rust Crate: `image-0.24.9` Read image using `ImageBuffer::from_raw(w,h,bytes)` image size: 4608 x 2592 x 3 [BGR] +>>>>>>> main diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c738108..c2fc50c 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] channel="1.76.0-2024-02-08" components = [ "rustc", "cargo", "rust-std", "rustfmt", "rust-docs", "rust-analyzer" ] -targets = [ "armv7-unknown-linux-musleabi" ] +targets = [ "armv7-unknown-linux-gnueabihf" ] profile = "default" diff --git a/src/main.rs b/src/main.rs index e7a11a9..8c30842 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,258 @@ +use std::{ fs, io::{Bytes, stdin, BufReader, Error, ErrorKind, Read, Write}, net::{IpAddr, Ipv4Addr, SocketAddrV4, TcpStream}, path::Path, thread::{self, JoinHandle}, time::Duration}; +use chrono::{DateTime, Local}; +use image::{Rgb, RgbImage}; +use ipnet::{Ipv4Net,PrefixLenError}; +use local_ip_address::linux::local_ip; +use log::{LevelFilter, trace,debug,warn,error,info}; +use fern::{log_file, Dispatch}; + +//RTSP port is 554; prepare for real world situations +const PORT_NUMBER:u16 = 55001; +const PORT_PROBE_TIMEOUT:Duration = Duration::new(5,0); +const SUBNET_SIZE:u8 = 24; + +//These subnets are well documented; +///RIT owns the subnet 129.21.0.0/16; probing by attempting to open thousands of TCP streams +///simultaneously is unwise. +const UNSAFE_SUBNET:Result = Ipv4Net::new(Ipv4Addr::new(129,21,0,0),16); + +///This subnet is universally considered the "local" subnet. This results in 256 addresses, and can +///be probed both safely and efficiently, and as long as the world server on the LAN is running it +///is functionally guaranteeed to be found. +const HOME_SUBNET:Result = Ipv4Net::new(Ipv4Addr::new(192,168,0,0),24); + fn main() { - println!("Hello, world!"); + setup_logs(&true); + //Get host IP + let host_ip = local_ip().expect("No real IP address!"); + trace!("Host IP: {:?}",host_ip); + + let mut thread_list:Vec>> = Vec::new(); + let mut port_list:Vec = Vec::new(); + if let IpAddr::V4(host_v4_ip) = host_ip{ + //Check current subnet + let net = Ipv4Net::new(host_v4_ip,SUBNET_SIZE); + + if let Ok(net) = net{ + //RIT owns 129.21.0.0/16; DO NOT SPAM THIS NETWORK + if UNSAFE_SUBNET.unwrap().contains(&net){ + //Request world server address from user + let address = manual_address_prompt(); + if address.is_ok(){ + port_list.push(address.unwrap()); + //thread_list won't be added to, so the thread for loop won't execute + } + } else if net.contains(&HOME_SUBNET.unwrap()){ + //Collect all Hosts on the current subnet + info!("aggregating all IPs... This may take several minutes..."); + for net_address in net.hosts(){ + thread_list.push( + thread::spawn(move ||{ + let ip_port = std::net::SocketAddr::V4(SocketAddrV4::new(net_address, PORT_NUMBER)); + //Attempt to open a TCP stream with this IP address, exit the thread + //returning the open TcpStream, or an error + return TcpStream::connect_timeout(&ip_port, PORT_PROBE_TIMEOUT); + }) + ); + } + } + } + } + + //Multithread the port-sniffing block, only save sucessful connections + for thread in thread_list{ + let output = thread.join().unwrap(); + if let Ok(real_output) = output{ + port_list.push(real_output); + } + } + + //For all available ports, try the custom communication protocol + for mut stream in port_list{ + info!("Stream connected to address: {:?}",stream.peer_addr()); + send_processing_time(&mut stream, 2.7f64); + read_response(&mut stream); + } + //TODO: Document/implement RTSP client-side comms + //Currently using custom port and custom protocol, but if real-world cameras will + //be in use, we will likely need to be portable to the RTSP protocol, or similar +} + +//Used to send the calculated time value to the world server +pub fn send_processing_time(stream:&mut TcpStream ,sent_value:f64){ + debug!("Begin handshake; sending timestamp float..."); + //Write the f64 value, in bytes, to the stream, and ensure it has been sent + stream.write(&sent_value.to_le_bytes()).unwrap(); + stream.flush().unwrap(); + debug!("Timestamp sent!"); +} + +//Used to recieve images from the world server +pub fn read_response(stream:&mut TcpStream){ + //Buffer the incoming stream + let reader = BufReader::new(stream.try_clone().expect("Failed clone")); + //Create a storage point for the bytes + let mut recieved_bytes:Vec = Vec::new(); + //Create an iterator over the stream's bytes + let mut iter = reader.bytes(); + + debug!("Continue handshake, read back image packet length..."); + //The first values sent will always be a u32 containing the length of the message (without the + //length counted), followed by the image width and height + let length = bytes_to_u32(&mut iter); + debug!("Image packet length read as {:?}!",length); + + debug!("Continue handshake, read back image width..."); + let image_width = bytes_to_u32(&mut iter); + debug!("Image width read as {:?}!",image_width); + + debug!("Continue handshake, read back image height..."); + let image_height = bytes_to_u32(&mut iter); + debug!("Image height read as {:?}!",image_height); + + //The length of the image is the total number of bytes + let byte_depth = length / (image_width * image_height); + debug!("Image bitdepth calculated as {:?}!", byte_depth); + + //Confirm to world server the correct number of bytes + stream.write(&byte_depth.to_le_bytes()).unwrap(); + stream.flush().unwrap(); + + //TODO: Remove assumption + //Always assumes world server will send image + info!("Start reading..."); + //Recieve the rest of the message + for _ in 0..length{ + recieved_bytes.push(iter.next().unwrap().unwrap_or(0)); + } + + info!("Image successfully recieved"); + + //Create a blank pane on which to store the read in pixels + let mut img = RgbImage::new(image_width,image_height); + + //Create a temporary storage point for u8s when generating pixels + let mut temp:Vec = Vec::new(); + + //Iterate over bytes + info!("Building image..."); + for i in 0..recieved_bytes.len(){ + let byte = recieved_bytes.get(i).expect("Index does not exist!"); + + temp.push(byte.clone()); + //Each pixel is composed of [byte_depth] u8s + if ((i as u32)+1) % byte_depth == 0{ + //Coordinate in the pane = i/3 + let pixel_number:u32 = (i as u32) /byte_depth; + //Insert the pixel into the pane + img.put_pixel( + //Pixels coming directly from Unity are sent "upside down", that is, + //starting at the bottom right, and iterating horizontally, then vertically. + //This line compensates and creates a properly-oriented image + (image_width-1)-(pixel_number%image_width), (image_height-1)-(pixel_number / image_width), + //Extract image from temporary storage, ang generate pixel + Rgb::{0:temp.clone().try_into().expect("bad vector length!")} + ); + //Clear temporary storage + temp.clear(); + } + } + //Dump image to file + //ONLY FOR EXPERIMENTATION AND TESTING PURPOSES + info!("Image built, saving to file..."); + _ = img.save("./test.png"); + info!("image saved!"); +} + +///Borrows an iterator over the bytes in a buffered-reader of a TcpStream; reads the next 4 bytes, +///outputs the generated u32 +fn bytes_to_u32(iter:&mut Bytes>) -> u32{ + let mut array:[u8;4] = [0;4]; + for i in 0..4{ + array[i] = iter.next().unwrap().unwrap(); + } + return u32::from_le_bytes(array); +} + +///Request the user to input the world server's address into stdin +fn manual_address_prompt() -> Result{ + let return_val:Result = Err(Error::new(ErrorKind::AddrNotAvailable,"Invalid Address")); + while return_val.is_err(){ + let mut user_input:String = String::default(); + match stdin().read_line(&mut user_input){ + Ok(_) => { + match user_input.trim().parse::(){ + Ok(address) => { + //Test if the address is accurate + let stream = TcpStream::connect_timeout(&std::net::SocketAddr::V4(address), PORT_PROBE_TIMEOUT); + if stream.is_ok(){ + return stream; + } else { + warn!("Address unavailable!"); + debug!("{:?}",stream.unwrap_err()); + } + }, + Err(error) => { + error!("Unable to properly parse user input!"); + debug!("{:?}",error); + } + } + }, + Err(error) => { + error!("Unable to read user input!"); + debug!("{:?}",error); + } + } + } + return return_val; +} + +///Set up logging macros to be used throughout the program +fn setup_logs(debug:&bool){ + //Get the current time + let chrono_now: DateTime = Local::now(); + //Create a log directory, if it does not exist + if ! Path::new("logs").is_dir(){ + _ = fs::create_dir("logs"); + }; + //Create a log macro listener + _ = fern::Dispatch::new() + //Format the output messages + .format(|out,message,record|{ + out.finish(format_args!( + "{} - [{}, {}] - {}", + Local::now().to_rfc3339(), + record.level(), + record.target(), + message + )) + }) + //Output to the file + .chain({ + let mut file_logger = Dispatch::new(); + let date_format = chrono_now.format("%Y-%m-%d_%H.%M").to_string(); + let local_log_file = log_file(format!("logs/{}.log",date_format)).unwrap(); + //Set filter based on whether the command is being run in "debug" mode + if *debug{ + file_logger = file_logger.level(LevelFilter::Trace); + } + else { + file_logger = file_logger.level(LevelFilter::Debug); + } + //Apply the filter and file formatting rules described above + file_logger.chain(local_log_file) + }) + .chain({ + //Also log to stdout + let mut stdout_logger = fern::Dispatch::new(); + if *debug { + stdout_logger = stdout_logger.level(LevelFilter::Debug); + } + else { + stdout_logger = stdout_logger.level(LevelFilter::Info); + } + stdout_logger.chain(std::io::stdout()) + }) + //Start listening to macros + .apply(); }