From 3816f3ca6e28653e143459f6364983004d22dbbb Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 22 Oct 2023 20:30:36 +0200 Subject: [PATCH] adding server --- .gitignore | 2 + LICENCE.txt | 18 ++ server/Cargo.lock | 609 +++++++++++++++++++++++++++++++++++++++ server/Cargo.toml | 13 + server/src/main.rs | 656 ++++++++++++++++++++++++++++++++++++++++++ start-bazar-server.sh | 113 ++++++++ 6 files changed, 1411 insertions(+) create mode 100644 .gitignore create mode 100644 LICENCE.txt create mode 100644 server/Cargo.lock create mode 100644 server/Cargo.toml create mode 100644 server/src/main.rs create mode 100755 start-bazar-server.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5cfae44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.rust/ +server/target/ diff --git a/LICENCE.txt b/LICENCE.txt new file mode 100644 index 0000000..4cde7e4 --- /dev/null +++ b/LICENCE.txt @@ -0,0 +1,18 @@ + + Server Rust/Client Godot - Simple Multiplayer + + Copyright (C) 2023 AleaJactaEst + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + diff --git a/server/Cargo.lock b/server/Cargo.lock new file mode 100644 index 0000000..1ce74a0 --- /dev/null +++ b/server/Cargo.lock @@ -0,0 +1,609 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[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 = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[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.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "enet" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd5c84ebdecb28194d15e063436a4b7863546a9dea268aee131ca23dbb2a21ac" +dependencies = [ + "enet-sys", + "thiserror", +] + +[[package]] +name = "enet-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4580f5cb34ba20a73d05e26876f05fd3830a8959fb594b1ecb4d9ddac2eec77" +dependencies = [ + "bindgen", + "cmake", +] + +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +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.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "server" +version = "0.1.0" +dependencies = [ + "anyhow", + "byteorder", + "chrono", + "enet", + "log", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +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 = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[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.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[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_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[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_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 0000000..23c5d26 --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +enet = "0.3.0" +anyhow = "1.0.56" +log = "0.4.20" +chrono = "0.4.31" +byteorder = "1.5.0" diff --git a/server/src/main.rs b/server/src/main.rs new file mode 100644 index 0000000..28d602e --- /dev/null +++ b/server/src/main.rs @@ -0,0 +1,656 @@ +extern crate enet; + +/* + + Server minimal + + Author : Aleajactaest + Created : 10 October 2023 + + Build: + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + source $HOME/.cargo/env + cargo build + target/debug/server-rust +*/ + +use std::net::Ipv4Addr; +use log::{debug, error, info, trace, warn, Level, LevelFilter, Metadata, Record, SetLoggerError}; + + +use anyhow::Context; +use enet::*; +use std::*; +use chrono::Utc; +use byteorder::{ByteOrder, LittleEndian, ReadBytesExt}; + + +struct ServerLogger; + +impl log::Log for ServerLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= Level::Info + } + + fn log(&self, record: &Record) { + //if self.enabled(record.metadata()) { + println!("{} [ {:5} ] {}", Utc::now().format("%Y-%m-%dT%H:%M:%SZ"), record.level(), record.args()); + //} + } + + fn flush(&self) {} +} + +static LOGGER: ServerLogger = ServerLogger; + +pub fn loginit(level:LevelFilter) -> Result<(), SetLoggerError> { + log::set_logger(&LOGGER) + .map(|()| log::set_max_level(level)) +} + +//const MAX_USER:usize = 100; + +fn push_u64(data:&mut Vec, value:u64) { + let mut buf = [0; 8]; + LittleEndian::write_u64(&mut buf, value); + data.push(buf[0]); + data.push(buf[1]); + data.push(buf[2]); + data.push(buf[3]); + data.push(buf[4]); + data.push(buf[5]); + data.push(buf[6]); + data.push(buf[7]); +} +fn push_f64(data:&mut Vec, value:f64) { + let mut buf = [0; 8]; + LittleEndian::write_f64(&mut buf, value); + data.push(buf[0]); + data.push(buf[1]); + data.push(buf[2]); + data.push(buf[3]); + data.push(buf[4]); + data.push(buf[5]); + data.push(buf[6]); + data.push(buf[7]); +} + +/* +enum Simple { + Error(String), + Okay, + Foo([u32; 5]), +} + +impl Clone for Simple { + fn clone(&self) -> Simple { + match self { + Error(a) => Error(a.to_string()), + Okay => Okay, + Foo(a) => Foo(a.clone()), + } + } +} +*/ + +enum StateUsers { + NotDefined, + Inactive, + UpdateUser, + UpdateAddress, + Error, + Done, +} + +struct Position { + x: f64, + y: f64, + z: f64, +} + +/* + * User + */ +struct User { + active: bool, + username: String, + address: Address, + id: u64, + x: f64, + y: f64, + z: f64, + position_updated: bool +} + +impl User { +/* + pub fn new() -> User { + Self { + active: false, + username: "".to_string(), + address: Address::new( Ipv4Addr::new(0,0,0,0), 0 ) + } + } +*/ + pub fn set_inactive(&mut self) { + self.active = false; + } + pub fn set_active(&mut self) { + self.active = true; + } + pub fn update_username(&mut self, username: String, id:u64) { + self.username = username; + self.id = id; + } + pub fn update_address(&mut self, address: Address, id:u64) { + self.address = address; + self.id = id; + } + pub fn clear_username(&mut self) { + self.username = "".to_string(); + } + pub fn clear_address(&mut self) { + self.address = Address::new(Ipv4Addr::new(0, 0, 0, 0), 0); + } + pub fn clear_position_updated(&mut self) { + self.position_updated = false; + } + pub fn update_pos(&mut self, x:f64, y:f64, z:f64) { + if self.x != x { + self.x = x; + self.position_updated = true; + } + if self.y != y { + self.y = y; + self.position_updated = true; + } + if self.z != z { + self.z = z; + self.position_updated = true; + } + } + pub fn get_position(&mut self) -> Position { + let pos:Position = Position{x: self.x, y: self.y, z: self.z}; + return pos; + } + pub fn push_packet(&self, data:&mut Vec) { + push_u64(data, self.id); + push_f64(data, self.x); + push_f64(data, self.y); + push_f64(data, self.z); + } + /* + pub fn get_packet(&mut self) -> Vec { + let mut data:Vec = Vec::new(); + push_u64(&mut data, self.id); + push_f64(&mut data, self.x); + push_f64(&mut data, self.y); + push_f64(&mut data, self.z); + data + } + */ +} + +impl std::fmt::Display for User { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "id:{} user:{} active:{} address:{}:{} ({}:{}:{})", self.id, self.username, self.active, self.address.ip(), self.address.port(), self.x, self.y, self.z) + } +} + +/* + * Users + */ +struct Users { + users: Vec, + lastid: u64, +} + +impl Users { + pub fn new() -> Users { + Self { + lastid: 0, + users: Vec::new() + } + } + /* + pub fn search(&self, username:String) -> bool { + for user in &self.users { + println!("{}", user); + if user.username == username { + return true; + } + } + return false; + } + */ + pub fn search_me(&self, username:String, address: Address) -> StateUsers { + let mut nb_user:u8 = 0; + let mut nb_address:u8 = 0; + let mut user_address:bool = false; + //let mut is_active:bool = false; + let mut user_active:bool = false; + let mut address_active:bool = false; + let mut cur:StateUsers = StateUsers::NotDefined; + // check user & address + for user in &self.users { + if user.username == username { + nb_user+=1; + if user.active { + user_active = true; + } + if user.address == address { + user_address = true; + cur = match cur { + StateUsers::NotDefined => { + if user.active { + trace!("User:Ok, Address:Ok, Active:True"); + StateUsers::Done + } else { + trace!("User:Ok, Address:Ok, Active:False"); + StateUsers::Inactive + } + } + _ => { + trace!("User:Ok, Address:Ok, But already checked ?"); + StateUsers::Error + } + }; + } + } + if user.address == address { + nb_address+=1; + if user.active { + address_active = true; + } + } + } + // check + if nb_user == 0 && nb_address == 0 { + trace!("NotDefined: User: not define, Address: not define"); + return StateUsers::NotDefined; + } else if nb_user == 1 && nb_address == 0 { + trace!("UpdateAddress: User: {}, Address: {}", nb_user, nb_address); + return StateUsers::UpdateAddress; + } else if nb_user == 0 && nb_address == 1 { + trace!("UpdateUser: User: {}, Address: {}", nb_user, nb_address); + return StateUsers::UpdateUser; + } else if nb_user == 1 && nb_address == 1 { + if user_address { + return cur; + } else if user_active && ! address_active { + trace!("UpdateUser: User: not define, Address: Ok"); + return StateUsers::UpdateUser; + } else if address_active && ! user_active { + trace!("UpdateAddress: User: Ok, Address: not define"); + return StateUsers::UpdateAddress; + } else { + trace!("Error: User: {}, Address: {}", nb_user, nb_address); + return StateUsers::Error; + } + } + trace!("? User: {}, Address: {}", nb_user, nb_address); + return StateUsers::Error; + } + pub fn get_new_id(&mut self) -> u64 { + self.lastid += 1; + self.lastid + } + pub fn add(&mut self, username:String, address: Address) -> u64 { + let id = self.get_new_id(); + self.users.push( User { active: true, username:username, address: address, id: id, x: 0.0, y: 10.0, z:0.0, position_updated:true} ); + id + } + pub fn update_pos(&mut self, address: Address, x:f64, y:f64, z:f64) { + for user in self.users.iter_mut() { + if user.address == address { + user.update_pos(x, y, z); + } + } + } + pub fn set_inactive(&mut self, address: Address) -> u64 { + for user in self.users.iter_mut() { + if user.address == address { + user.set_inactive(); + return user.id; + } + } + return 0; + } + pub fn set_active(&mut self, address: Address) -> u64 { + for user in self.users.iter_mut() { + if user.address == address { + user.set_active(); + return user.id; + } + } + return 0; + } + pub fn update_username(&mut self, username:String, address: Address) -> u64 { + let id = self.get_new_id(); + for user in self.users.iter_mut() { + if user.address == address { + user.update_username(username.clone(), id); + user.set_active(); + } else if user.username == username { + user.clear_username(); + } + } + id + } + pub fn update_address(&mut self, username:String, address: Address) -> u64 { + let id = self.get_new_id(); + for user in self.users.iter_mut() { + if user.username == username { + user.update_address(address.clone(), id); + user.set_active(); + } else if user.address == address { + user.clear_address(); + } + } + id + } + pub fn get_id(&mut self, address: Address) -> u64 { + for user in &self.users { + if user.address == address { + return user.id; + } + } + return 0; + } + pub fn get_user(&mut self, address: Address) -> Result<&User, &'static str> { + for user in &self.users { + if user.address == address { + return Ok(user.clone()); + } + } + error!("invalid address {}:{}", address.ip(), address.port()); + Err("invalid address") + } + pub fn push_packet(&self, data:&mut Vec) -> u8 { + let mut nb:u8 = 0; + for user in &self.users { + if user.active && user.position_updated { + user.push_packet(data); + nb += 1; + } + } + nb + } + pub fn clear_position_updated(&mut self) { + for user in self.users.iter_mut() { + if user.position_updated { + user.clear_position_updated(); + } + } + } +} + +impl std::fmt::Display for Users { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "len: {} -- ", self.users.len()).unwrap(); + for user in self.users.iter() { + write!(f, "[{}] ", user).unwrap(); + } + Ok(()) + } +} + +/* +impl std::fmt::Display for Vec { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for user in self.users.iter() { + write!(f, "{}, ", self.users) + } + } +} +*/ + +/* +impl Users { + pub fn print(&self) { + println!("len: {}", self.users.len()); + for user in self.users { + println!("active:{} (user:{} address:{}:{})",user.active, user.username, user.address.ip(), user.address.port()); + } + } +} +*/ +/* +impl Copy for User { } + +impl Clone for User { + fn clone(&self) -> User { + match self { + active => active.clone(), + username => username.clone(), + address => address.clone(), + } + } +} +*/ + +/* + * Send a message + */ + +fn send_message(sender:Peer<()>, data: &[u8] ) -> Result<(), Error> { + let mut peer = sender.clone(); + peer.send_packet ( + Packet::new(data, PacketMode::ReliableSequenced).unwrap(), + 1, + ) +} +/* +fn send_message_connect_ok(sender:Peer<()>, id:u64, x:f64, y:f64, z:f64) -> Result<(), Error> { + let mut data:Vec = Vec::new(); + data.push(1); // return connexion request + data.push(0); // return ok + // get_packet + push_u64(&mut data, id); + push_f64(&mut data, x); + push_f64(&mut data, y); + push_f64(&mut data, z); + let c: &[u8] = &data; + send_message(sender, c) +} +*/ + +fn send_message_connect_ok(sender:Peer<()>, user: &User) -> Result<(), Error> { + let mut data:Vec = Vec::new(); + data.push(1); // return connexion request + data.push(0); // return ok + user.push_packet(&mut data); + let c: &[u8] = &data; + send_message(sender, c) +} + +fn send_message_connect_ko(sender:Peer<()>) -> Result<(), Error> { + let mut data:Vec = Vec::new(); + data.push(1); // return connexion request + data.push(2); // return ko + let c: &[u8] = &data; + send_message(sender, c) +} + +fn show(data: &[u8]) -> String { + data.iter().map(|b| format!("{:02X}", b)).collect::>().join(", ") +} + + +/* + * Main + */ +fn main() -> anyhow::Result<()> { + let enet = Enet::new().context("could not initialize ENet")?; + + //env_logger::init(); + loginit(LevelFilter::Trace).unwrap(); + + // simple_logging::log_to_stderr(LevelFilter::Info); + /* + debug!("Debug"); + trace!("Trace"); + info!("Enet initialized"); + warn!("Enet initialized"); + error!("Enet initialized"); + */ + let local_addr = Address::new(Ipv4Addr::LOCALHOST, 33333); + + let mut host = enet + .create_host::<()>( + Some(&local_addr), + 10, + ChannelLimit::Maximum, + BandwidthLimit::Unlimited, + BandwidthLimit::Unlimited, + ) + .context("could not create host")?; + //let mut users: [User; MAX_USER] = [User { active: false, username:"".to_string(), address: Address::new( Ipv4Addr::new(0,0,0,0), 0)}; MAX_USER]; + let mut users:Users = Users::new() ; + info!("Started"); + loop { + trace!("users: {}", users); + match host.service(1000).context("service failed")? { + Some(Event::Connect(_)) => debug!("new connection!"), + Some(Event::Disconnect(ref sender, _)) => { + users.set_inactive(sender.address()); + debug!("disconnect!"); + }, + Some(Event::Receive { + ref sender, + channel_id, + ref packet + }) => { + debug!( + "got packet on channel {}, len: '{}' (who:{}:{})", + channel_id, + packet.data().len(), + sender.address().ip(), + sender.address().port() + ); + match channel_id { + 1 => { + let cmd = packet.data()[0]; + let size = packet.data()[1] as usize; + let player_name = &packet.data()[2..=size+1]; + + let s = match str::from_utf8(player_name) { + Ok(v) => v, + Err(_e) => "", + }; + trace!("cmd: {} size:{} name:{} '{}'", cmd, size, player_name.len(), s); + if s.to_string() == "Interdit" || s.to_string() == "" { + warn!("Received forbidden account '{}'", s); + send_message_connect_ko(sender.clone()).unwrap(); + continue; + } + let check = users.search_me(s.to_string(), sender.address()); + match check { + StateUsers::NotDefined => { + debug!("NotDefined"); + let _id = users.add(s.to_string(), sender.address()); + let ret = users.get_user(sender.address()); + match ret { + Ok(user) => send_message_connect_ok(sender.clone(), user).unwrap(), + Err(_e) => {}, + }; + } + StateUsers::Inactive => { + debug!("Inactive"); + let _id = users.set_active(sender.address()); + let ret = users.get_user(sender.address()); + match ret { + Ok(user) => send_message_connect_ok(sender.clone(), user).unwrap(), + Err(_e) => {}, + }; + } + StateUsers::UpdateUser => { + debug!("UpdateUser"); + let _id = users.update_username(s.to_string(), sender.address()); + let ret = users.get_user(sender.address()); + match ret { + Ok(user) => send_message_connect_ok(sender.clone(), user).unwrap(), + Err(_e) => {}, + }; + } + StateUsers::UpdateAddress => { + debug!("UpdateAddress"); + let _id = users.update_address(s.to_string(), sender.address()); + let ret = users.get_user(sender.address()); + match ret { + Ok(user) => send_message_connect_ok(sender.clone(), user).unwrap(), + Err(_e) => {}, + }; + } + StateUsers::Error => { + error!("Bad request from {}:{}", sender.address().ip(),sender.address().port()); + send_message_connect_ko(sender.clone()).unwrap(); + } + StateUsers::Done => { + debug!("Done"); + let _id = users.get_id(sender.address()); + let ret = users.get_user(sender.address()); + match ret { + Ok(user) => send_message_connect_ok(sender.clone(), user).unwrap(), + Err(_e) => {}, + }; + } + } + } + 2 => { + let mut xbytes: &[u8] = &packet.data()[0..8]; + let x = xbytes.read_f64::().unwrap(); + let mut ybytes: &[u8] = &packet.data()[8..16]; + let y = ybytes.read_f64::().unwrap(); + let mut zbytes: &[u8] = &packet.data()[16..24]; + let z = zbytes.read_f64::().unwrap(); + users.update_pos(sender.address(), x, y, z); + } + _ => { + let mut peer = sender.clone(); + peer.send_packet ( + Packet::new(b"youpia", PacketMode::ReliableSequenced).unwrap(), + 1, + ) + .context("sending packet failed")?; + } + } + }, + _ => (), + } + // Send all player, position other player + { + let mut data:Vec = Vec::new(); + let mut data2:Vec = Vec::new(); + data.push(3); // return connexion request + let nb:u8 = users.push_packet(&mut data2); + data.push(nb); // number user + data.append(&mut data2); + let c: &[u8] = &data; + if nb > 0 { + for peer in host.peers() { + if peer.state() == PeerState::Connected { + trace!("peer: {}:{}", peer.address().ip(), peer.address().port()); + send_message(peer, c); + } + } + users.clear_position_updated(); + } + } + /* + for peer in host.peers() { + if peer.state() == PeerState::Connected { + trace!("peer: {}:{}", peer.address().ip(), peer.address().port()); + let mut data:Vec = Vec::new(); + let mut data2:Vec = Vec::new(); + data.push(3); // return connexion request + let nb:u8 = users.push_packet(&mut data2); + data.push(nb); // number user + data.append(&mut data2); + let c: &[u8] = &data; + send_message(peer, c); + } + } + */ + } +} diff --git a/start-bazar-server.sh b/start-bazar-server.sh new file mode 100755 index 0000000..9db8db2 --- /dev/null +++ b/start-bazar-server.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# +# Script to launch server +# +# Copyright (C) 2023 AleaJactaEst +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +declare DEBUG=0 +declare HELP=0 +declare BUILD=0 +declare WORKDIR="$(dirname $(readlink -f $0))" +declare RUSTDIR="$WORKDIR/.rust" +declare SERVERDIR="$WORKDIR/server" + +function msg_debug() +{ + if [ $DEBUG -ne 0 ] + then + echo "### DEBUG : $*" >&2 + fi +} + +function msg_info() +{ + echo "--- INFO : $*" >&2 +} + +function msg_error() +{ + echo "*** ERROR : $*" >&2 +} + +function byebye() +{ + local CODE=$? + if [ $CODE -ne 0 ] + then + msg_error "return code:$code" + else + msg_info "End" + fi + exit $CODE +} + +while getopts hdb flag +do + case "${flag}" in + h) HELP=1;; + d) DEBUG=1;; + b) BUILD=1;; + *) HELP=1;; + esac +done + +if [[ $HELP -ne 0 ]] +then + cat << EOF +$(basename $0) [Option] : Donwload Launch Godot + Option: + -h : Show help + -d : Show debug message + -b : (re)build program +EOF + exit 1 +fi + +trap byebye EXIT + +msg_info "Start" +msg_debug "WORKDIR:$WORKDIR" + + +if [[ ($BUILD -ne 0) || (! -x $SERVERDIR/target/debug/server) ]] +then + export CARGO_HOME="$RUSTDIR/.cargo" + export RUSTUP_HOME="$RUSTDIR/.rustup" + + mkdir -p $RUSTDIR + if [ ! -f $RUSTDIR/install.sh ] + then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > $RUSTDIR/install.sh + fi + if [ ! -f $RUSTDIR/.cargo/env ] + then + sh .rust/install.sh -t $RUSTDIR/.cargo --no-modify-path -y + # curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -h + fi + if [ -f $RUSTDIR/.cargo/env ] + then + source $RUSTDIR/.cargo/env + cd $SERVERDIR + cargo build + else + msg_error "Error to load envi rust" + exit 2 + fi +fi + +$SERVERDIR/target/debug/server + +# END (call function byebye)