diff --git a/Cargo.lock b/Cargo.lock index c9bd052..d646d98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,18 +58,50 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -116,6 +148,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] + [[package]] name = "clap" version = "4.6.1" @@ -156,6 +199,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + [[package]] name = "colorchoice" version = "1.0.5" @@ -177,8 +226,10 @@ name = "confetti" version = "0.1.0" dependencies = [ "clap", + "ctrlc-async", "diesel", - "fedichat-lib", + "diesel-async", + "fedichat", "quinn", "serde", "thiserror 2.0.18", @@ -188,6 +239,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "core-foundation" version = "0.10.1" @@ -204,6 +261,44 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctrlc-async" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598e9d68e769aa1283460a3b0ec0d049ccfb6170277aea37089fa3f58fd721a1" +dependencies = [ + "nix", + "tokio", + "winapi", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "darling" version = "0.21.3" @@ -239,18 +334,59 @@ dependencies = [ "syn", ] +[[package]] +name = "deadpool" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883466cb8db62725aee5f4a6011e8a5d42912b42632df32aad57fc91127c6e04" +dependencies = [ + "deadpool-runtime", + "num_cpus", + "tokio", +] + +[[package]] +name = "deadpool-runtime" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2657f61fb1dd8bf37a8d51093cc7cee4e77125b22f7753f49b289f831bec2bae" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", + "serde_core", +] + [[package]] name = "diesel" version = "2.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9940fb8467a0a06312218ed384185cb8536aa10d8ec017d0ce7fad2c1bd882d5" dependencies = [ - "bitflags", + "bitflags 2.11.1", "byteorder", "diesel_derives", "downcast-rs", "itoa", - "pq-sys", +] + +[[package]] +name = "diesel-async" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c20ddcc6737cecdaef3dfecb2796bdfe3002456521189d30be8e4c5a1bc821d" +dependencies = [ + "deadpool", + "diesel", + "futures-core", + "futures-util", + "pin-project-lite", + "tokio", + "tokio-postgres", ] [[package]] @@ -275,6 +411,18 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "ctutils", +] + [[package]] name = "downcast-rs" version = "2.0.2" @@ -317,6 +465,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fastbloom" version = "0.14.1" @@ -325,17 +479,19 @@ checksum = "4e7f34442dbe69c60fe8eaf58a8cafff81a1f278816d8ab4db255b3bef4ac3c4" dependencies = [ "getrandom 0.3.4", "libm", - "rand", + "rand 0.9.4", "siphasher", ] [[package]] -name = "fedichat-lib" +name = "fedichat" version = "0.1.0" +source = "git+https://git.firechicken.net/fedichat/fedichat-lib#ba358085728410eb76681dc675a126871b5bd5da" dependencies = [ "rmp-serde", "serde", "serde_bytes", + "time", "uuid", ] @@ -357,12 +513,28 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + [[package]] name = "futures-task" version = "0.3.32" @@ -376,6 +548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-core", + "futures-sink", "futures-task", "pin-project-lite", "slab", @@ -390,7 +563,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -417,6 +590,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -442,6 +616,30 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest", +] + +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "id-arena" version = "2.3.0" @@ -558,6 +756,15 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "libc", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -579,12 +786,31 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "mio" version = "1.2.0" @@ -592,10 +818,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -605,6 +844,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + [[package]] name = "num-traits" version = "0.2.19" @@ -614,6 +859,34 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "objc2-core-foundation", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -655,6 +928,31 @@ dependencies = [ "windows-link", ] +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_shared", + "serde", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -662,10 +960,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] -name = "pkg-config" -version = "0.3.33" +name = "postgres-protocol" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "56201207dac53e2f38e848e31b4b91616a6bb6e0c7205b77718994a7f49e70fc" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand 0.10.1", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc729a129e682e8d24170cd30ae1aa01b336b096cbb56df6d534ffec133d186" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-protocol", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" @@ -676,17 +1003,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "pq-sys" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" -dependencies = [ - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -736,7 +1052,7 @@ dependencies = [ "fastbloom", "getrandom 0.3.4", "lru-slab", - "rand", + "rand 0.9.4", "ring", "rustc-hash", "rustls", @@ -791,7 +1107,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -801,7 +1128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -813,13 +1140,19 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.11.1", ] [[package]] @@ -971,7 +1304,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.11.1", "core-foundation", "core-foundation-sys", "libc", @@ -1056,6 +1389,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1109,6 +1453,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -1181,6 +1536,36 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinyvec" version = "1.11.0" @@ -1224,6 +1609,45 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-postgres" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd8df5ef180f6364759a6f00f7aadda4fbbac86cdee37480826a6ff9f3574ce" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand 0.10.1", + "socket2", + "tokio", + "tokio-util", + "whoami", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "1.1.2+spec-1.1.0" @@ -1321,12 +1745,39 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -1353,6 +1804,7 @@ checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", + "serde_core", "wasm-bindgen", ] @@ -1362,12 +1814,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "walkdir" version = "2.5.0" @@ -1384,6 +1830,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + [[package]] name = "wasip2" version = "1.0.3+wasi-0.2.9" @@ -1402,6 +1857,15 @@ dependencies = [ "wit-bindgen 0.51.0", ] +[[package]] +name = "wasite" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" +dependencies = [ + "wasi 0.14.7+wasi-0.2.4", +] + [[package]] name = "wasm-bindgen" version = "0.2.121" @@ -1475,12 +1939,22 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags", + "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap", "semver", ] +[[package]] +name = "web-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" @@ -1500,6 +1974,35 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "whoami" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" +dependencies = [ + "libc", + "libredox", + "objc2-system-configuration", + "wasite", + "web-sys", +] + +[[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-util" version = "0.1.11" @@ -1509,6 +2012,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[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-link" version = "0.2.1" @@ -1807,7 +2316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.11.1", "indexmap", "log", "serde", diff --git a/Cargo.toml b/Cargo.toml index 29fe270..40333b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2024" [dependencies] -diesel = { version = "2.3.9", features = ["postgres"] } +diesel = { version = "2.3.9" } quinn = "0.11.9" -fedichat-lib = {path = "../fedichat-lib"} +fedichat = {git = "https://git.firechicken.net/fedichat/fedichat-lib"} tracing = "0.1.44" tracing-subscriber = "0.3.23" clap = { version = "4.6.1", features = ["derive"] } @@ -14,3 +14,5 @@ tokio = { version = "1", features = ["full"] } serde = { version = "1.0.228", features = ["derive"] } thiserror = "2.0.18" toml = "1.1.2" +diesel-async = { version = "0.9.0", features = ["postgres","deadpool"] } +ctrlc-async = { version = "3.2.2", features = ["termination"] } diff --git a/confetti.toml.example b/confetti.toml.example index e19f617..2716108 100644 --- a/confetti.toml.example +++ b/confetti.toml.example @@ -1,10 +1,15 @@ hostname = "confetti.example.com" port = 53512 +federation_port = 53513 listen_address = "0.0.0.0" certfile = "/etc/letsencrypt/confetti/fullchain.pem" keyfile = "/etc/letsencrypt/confetti/privkey.pem" +media_directory = "/srv/confetti/media" +statefile = "./confetti.state" +loglevel = "debug" [database] url = "my.db.server" user = "confetti" password = "my_secret_password" +num_connections = 8 diff --git a/src/client.rs b/src/client.rs new file mode 100644 index 0000000..aafa07b --- /dev/null +++ b/src/client.rs @@ -0,0 +1,91 @@ +use fedichat::RoomId; +use fedichat::client::TaggedClientMessage; +use fedichat::state::StatePath; + +use diesel_async::AsyncPgConnection; +use diesel_async::pooled_connection::deadpool::Pool; +use tokio::sync::{broadcast,mpsc,RwLock}; +use tokio::select; +use std::collections::HashSet; +use std::sync::{Arc}; +use quinn::{SendStream,RecvStream}; +use crate::state::State; + +pub enum MessageId { + State(RoomId,StatePath), + Messages(RoomId) +} + +pub struct Client { + statehandle: Arc>, + // Channel for local messages, all are broadcast to all + // Every client gets to filter based on name + // Same with state changes + // Potentially could be turned into a more efficient localised filter maybe + // Remote messages can come through the same channel maybe? + message_send: broadcast::Sender, + // This probably could be a more specific type + // But we should be filtering and sending back only stuff that matters + message_recv: broadcast::Receiver, + // Sends back match if anything filtered matched the client filters + // Connections are closed after a period of inactivity so this should be fine, + // if client is connected acks are sent, if inactive connection is closed + message_ack: mpsc::Sender, + db_handle: Pool, + // Filled once user is authed + username: Option, + // how do I keep track of activity??? maybe there's a hashmap that gets updated + subscriptions: HashSet, + + quic_connection: quinn::Connection, + close_handle: broadcast::Receiver<()> +} +impl Client { + pub fn new( + statehandle: Arc>, + (message_send,message_recv): ( + broadcast::Sender, + broadcast::Receiver), + message_ack: mpsc::Sender, + db_handle: Pool, + quic_connection: quinn::Connection, + close_handle: broadcast::Receiver<()> + ) -> Self { + Client { + statehandle, + message_send, + message_recv, + message_ack, + db_handle, + username: None, + subscriptions: HashSet::new(), + quic_connection, + close_handle + } + + } + + pub async fn run(mut self) { + let mut chunk_arr = [0u8; 1024]; + let mut serde_buf: Vec = Vec::new(); + + loop { + + select!{ + //result = self.quic_recv.read(&mut chunk_arr) => { + // unimplemented!() + //} + result = self.message_recv.recv() => { + unimplemented!() + } + _result = self.close_handle.recv() => { + // Maybe TODO do I need to check the result? + break; + } + } + + } + // Do any cleanup that needs done + + } +} diff --git a/src/config.rs b/src/config.rs index a1b8905..b2ab5a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,21 +3,26 @@ use std::io::{Read,self}; use serde::{Serialize,Deserialize}; use thiserror::Error; -#[derive(Default,Clone,Serialize,Deserialize)] +// TODO: config file defaults instead of having to specify everything +#[derive(Clone,Serialize,Deserialize)] pub struct Config { pub hostname: String, pub port: u16, + pub federation_port: u16, pub listen_address: String, pub database: DBConfig, pub certfile: String, pub keyfile: String, - + pub statefile: String, + pub loglevel: String, + pub media_directory: String } -#[derive(Default,Clone,Serialize,Deserialize)] +#[derive(Clone,Serialize,Deserialize)] pub struct DBConfig { pub url: String, pub user: String, pub password: String, + pub num_connections: usize } const LOCATIONS: [&'static str; 3] = [ diff --git a/src/connection.rs b/src/connection.rs new file mode 100644 index 0000000..dd8ebe1 --- /dev/null +++ b/src/connection.rs @@ -0,0 +1,64 @@ +use crate::client::{Client,MessageId}; +use crate::state::State; +use tokio::sync::{mpsc,RwLock,broadcast}; +use std::sync::Arc; +use fedichat::client::TaggedClientMessage; +use diesel_async::pooled_connection::deadpool::Pool; +use diesel_async::{AsyncPgConnection}; +use tracing::{instrument,warn}; + +#[instrument(skip_all)] +pub async fn client_handler( + statehandle: Arc>, + (message_send,message_recv): ( + broadcast::Sender, + broadcast::Receiver), + message_ack_send: mpsc::Sender, + db_handle: Pool, + endpoint: quinn::Endpoint, + close_handle: broadcast::Receiver<()> + ) { + let mut thread_handles = Vec::new(); + + // Start iterating over incoming connections. + while let Some(conn) = endpoint.accept().await { + let connection = match conn.await { + Ok(conn) => conn, + Err(e) => { + warn!("Error while processing client connection"); + warn!("{:?}",e); + continue + + } + }; + + + let statehandle = statehandle.clone(); + let message_send = message_send.clone(); + let message_recv = message_recv.resubscribe(); + let close_handle = close_handle.resubscribe(); + let db_handle = db_handle.clone(); + let message_ack_send = message_ack_send.clone(); + + thread_handles.push(tokio::spawn(async move { + // listen for the first bidirectional stream + // create client + let client = Client::new( + statehandle, + (message_send,message_recv), + message_ack_send, + db_handle, + connection, + close_handle + ); + // run client + client.run() + })); + } + + +} + +pub fn federation_handler() { + +} diff --git a/src/main.rs b/src/main.rs index ea4ec73..f9a0a84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,29 @@ +mod client; mod config; +mod connection; +mod state; -use diesel::{Connection,PgConnection}; +use diesel_async::pooled_connection::AsyncDieselConnectionManager; +use diesel_async::pooled_connection::deadpool::Pool; +use diesel_async::{AsyncConnection,AsyncPgConnection}; use quinn::rustls::pki_types::{PrivateKeyDer,CertificateDer,pem::PemObject}; - -use std::net::{IpAddr,SocketAddr}; -use std::str::FromStr; use quinn::Endpoint; -use tracing::{error,instrument}; - - +use std::io; +use std::fs; +use std::net::{IpAddr,SocketAddr}; use std::process::ExitCode; +use std::str::FromStr; +use std::sync::Arc; +use serde::{Deserialize,Serialize}; +use tracing::{error,instrument,warn,debug}; +use tokio::sync::{RwLock,broadcast,mpsc}; + + use crate::config::Config; +use crate::state::State; + +#[derive(Hash,Eq,PartialEq,Clone,Serialize,Deserialize)] +pub struct Coordinate(Vec); #[tokio::main] #[instrument] @@ -22,12 +35,19 @@ async fn main() -> ExitCode { error!("Problem while reading config file"); error!("{:?}",e); return ExitCode::FAILURE; - } }; // Set up database connection - let db_connection = PgConnection::establish(&config.database.url); + let db_config = AsyncDieselConnectionManager::::new(config.database.url.clone()); + let db_pool = match Pool::builder(db_config).build() { + Ok(val) => val, + Err(e) => { + error!("Error while creating database connection pool"); + error!("{:?}",e); + return ExitCode::FAILURE; + } + }; // Read certificate file @@ -66,14 +86,99 @@ async fn main() -> ExitCode { } }; + // Load or create new state + let state = match State::load_from_file(&config.statefile) { + Ok(state) => state, + // Create file if it does not exist + Err(e) => { + match e.kind() { + io::ErrorKind::NotFound => { + match fs::File::create(&config.statefile) { + // If the statefile is writable then create an empty state + // and use that + Ok(_) => State::new(), + Err(e) => { + error!("Could not open or create statefile. Check your config."); + error!("{:?}",e); + return ExitCode::FAILURE; - // Start iterating over incoming connections. - while let Some(conn) = endpoint.accept().await { - let connection = conn.await; + } + } - // Save connection somewhere, start transferring, receiving data, see DataTransfer tutorial. + }, + _ => { + error!("Could not open or create statefile. Check your config."); + error!("{:?}",e); + return ExitCode::FAILURE; + } + } + }, + }; + let statehandle = Arc::new(RwLock::new(state)); + + // Global connections + let (close_send,close_recv) = broadcast::channel(1); + let (message_send,message_recv) = broadcast::channel(128); + let (message_ack_send,message_ack_recv) = mpsc::channel(128); + + match ctrlc_async::set_async_handler( + async move { match close_send.send(()) { + Ok(_val) => (), + Err(e) => { + error!("Shutdown handler is broken. Cannot gracefully exit."); + error!("{:?}",e); + } + } + } + ) { + Ok(()) => (), + Err(e) => { + error!("Could not set up signal handler"); + error!("{:?}",e); + return ExitCode::FAILURE; + } + + }; + + + let mut join_handles = Vec::new(); + + // Create client listener + + let statehandle_cloned = statehandle.clone(); + join_handles.push(tokio::spawn(async move { + connection::client_handler( + statehandle_cloned, + (message_send.clone(),message_recv.resubscribe()), + message_ack_send, + db_pool, + endpoint, + close_recv.resubscribe() + ).await; + } )); + + // Wait for child threads to exit + for handle in join_handles { + match handle.await { + Ok(()) => (), + Err(e) => { + warn!("Problem while cleaning up threads"); + warn!("{:?}",e); + } + } } + //Save state + match statehandle.write().await.write_to_file(&config.statefile) { + Ok(()) => debug!("Successfully wrote state to {:?}",config.statefile), + Err(e) => { + error!("Problem while writing to statefile"); + error!("{:?}",e); + } + } + + + // Should never reach this // How should I gracefully shutdown? Can I trap ctrlc ExitCode::SUCCESS diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..b804236 --- /dev/null +++ b/src/state.rs @@ -0,0 +1,87 @@ +use serde::{Deserialize,Serialize}; +use crate::Coordinate; +use tokio::sync::RwLock; +use std::collections::HashMap; +use std::io; +use std::sync::Arc; + +// Is there a way to guarantee that creating a state will create a permission +// at the same time in the event of a crash? +#[derive(Serialize,Deserialize)] +pub struct LoadableState { + room_states: HashMap, + perms: HashMap +} +impl LoadableState { + pub fn new(room_states: HashMap, perms: HashMap) -> Self { + LoadableState{ + room_states, + perms + } + + } +} + +// This whole thing needs to be RWLock protected to be able to add new rooms +pub struct State { + room_states: HashMap>>, + perms: HashMap>> +} + +impl State { + pub fn new() -> Self { + State { + room_states: HashMap::new(), + perms: HashMap::new() + } + } + pub fn from_loadable_state(other: LoadableState) -> Self { + unimplemented!() + + } + pub fn write_to_file(&mut self, path: &str) -> Result<(),io::Error> { + unimplemented!() + } + pub fn load_from_file(path: &str) -> Result { + unimplemented!() + } + pub async fn to_loadable_state(&self) -> LoadableState { + let mut room_states = HashMap::new(); + let mut perms = HashMap::new(); + //NOTE: This clone can be really heavy, I wonder if I can just lock the whole + //state to avoid copying it + for (coordinate,state) in self.room_states.iter() { + room_states.insert(coordinate.clone(),state.read().await.clone()); + } + for (coordinate,perm) in self.perms.iter() { + perms.insert(coordinate.clone(),perm.read().await.clone()); + } + LoadableState::new(room_states,perms) + } + // This traverses to the right leaf node and gets all permissions for an object + pub async fn get_required_permissions(&self, path: fedichat::state::StatePath) + -> HashMap + { + unimplemented!() + + } + + // Make a wrapper for this that allows the client to request a state value + pub async fn get_state_value(&self, path: fedichat::state::StatePath) + -> fedichat::state::StateValue + { + unimplemented!() + } +} + +#[derive(Serialize,Deserialize,Clone)] +pub enum StateNode { + Directory(HashMap), + Value(fedichat::state::StateValue) +} + +#[derive(Serialize,Deserialize,Clone)] +pub enum PermNode { + Directory(HashMap), + Permission(HashMap) +}