Live location tracking and playback for the game "manhunt"

Implement signaling server

bwc9876.dev ea8f119a 0b98ca2f

verified
+1695
+2
manhunt-signaling/.gitignore
··· 1 + target 2 + result
+1337
manhunt-signaling/Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "addr2line" 7 + version = "0.24.2" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 + dependencies = [ 11 + "gimli", 12 + ] 13 + 14 + [[package]] 15 + name = "adler2" 16 + version = "2.0.1" 17 + source = "registry+https://github.com/rust-lang/crates.io-index" 18 + checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 19 + 20 + [[package]] 21 + name = "aho-corasick" 22 + version = "1.1.3" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 + dependencies = [ 26 + "memchr", 27 + ] 28 + 29 + [[package]] 30 + name = "anstream" 31 + version = "0.6.19" 32 + source = "registry+https://github.com/rust-lang/crates.io-index" 33 + checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" 34 + dependencies = [ 35 + "anstyle", 36 + "anstyle-parse", 37 + "anstyle-query", 38 + "anstyle-wincon", 39 + "colorchoice", 40 + "is_terminal_polyfill", 41 + "utf8parse", 42 + ] 43 + 44 + [[package]] 45 + name = "anstyle" 46 + version = "1.0.11" 47 + source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 49 + 50 + [[package]] 51 + name = "anstyle-parse" 52 + version = "0.2.7" 53 + source = "registry+https://github.com/rust-lang/crates.io-index" 54 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 55 + dependencies = [ 56 + "utf8parse", 57 + ] 58 + 59 + [[package]] 60 + name = "anstyle-query" 61 + version = "1.1.3" 62 + source = "registry+https://github.com/rust-lang/crates.io-index" 63 + checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" 64 + dependencies = [ 65 + "windows-sys 0.59.0", 66 + ] 67 + 68 + [[package]] 69 + name = "anstyle-wincon" 70 + version = "3.0.9" 71 + source = "registry+https://github.com/rust-lang/crates.io-index" 72 + checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" 73 + dependencies = [ 74 + "anstyle", 75 + "once_cell_polyfill", 76 + "windows-sys 0.59.0", 77 + ] 78 + 79 + [[package]] 80 + name = "anyhow" 81 + version = "1.0.98" 82 + source = "registry+https://github.com/rust-lang/crates.io-index" 83 + checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 84 + 85 + [[package]] 86 + name = "async-trait" 87 + version = "0.1.88" 88 + source = "registry+https://github.com/rust-lang/crates.io-index" 89 + checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" 90 + dependencies = [ 91 + "proc-macro2", 92 + "quote", 93 + "syn", 94 + ] 95 + 96 + [[package]] 97 + name = "axum" 98 + version = "0.8.4" 99 + source = "registry+https://github.com/rust-lang/crates.io-index" 100 + checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" 101 + dependencies = [ 102 + "axum-core", 103 + "base64", 104 + "bytes", 105 + "form_urlencoded", 106 + "futures-util", 107 + "http", 108 + "http-body", 109 + "http-body-util", 110 + "hyper", 111 + "hyper-util", 112 + "itoa", 113 + "matchit", 114 + "memchr", 115 + "mime", 116 + "percent-encoding", 117 + "pin-project-lite", 118 + "rustversion", 119 + "serde", 120 + "serde_json", 121 + "serde_path_to_error", 122 + "serde_urlencoded", 123 + "sha1", 124 + "sync_wrapper", 125 + "tokio", 126 + "tokio-tungstenite", 127 + "tower", 128 + "tower-layer", 129 + "tower-service", 130 + "tracing", 131 + ] 132 + 133 + [[package]] 134 + name = "axum-core" 135 + version = "0.5.2" 136 + source = "registry+https://github.com/rust-lang/crates.io-index" 137 + checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" 138 + dependencies = [ 139 + "bytes", 140 + "futures-core", 141 + "http", 142 + "http-body", 143 + "http-body-util", 144 + "mime", 145 + "pin-project-lite", 146 + "rustversion", 147 + "sync_wrapper", 148 + "tower-layer", 149 + "tower-service", 150 + "tracing", 151 + ] 152 + 153 + [[package]] 154 + name = "backtrace" 155 + version = "0.3.75" 156 + source = "registry+https://github.com/rust-lang/crates.io-index" 157 + checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 158 + dependencies = [ 159 + "addr2line", 160 + "cfg-if", 161 + "libc", 162 + "miniz_oxide", 163 + "object", 164 + "rustc-demangle", 165 + "windows-targets", 166 + ] 167 + 168 + [[package]] 169 + name = "base64" 170 + version = "0.22.1" 171 + source = "registry+https://github.com/rust-lang/crates.io-index" 172 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 173 + 174 + [[package]] 175 + name = "bitflags" 176 + version = "2.9.1" 177 + source = "registry+https://github.com/rust-lang/crates.io-index" 178 + checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 179 + 180 + [[package]] 181 + name = "block-buffer" 182 + version = "0.10.4" 183 + source = "registry+https://github.com/rust-lang/crates.io-index" 184 + checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 185 + dependencies = [ 186 + "generic-array", 187 + ] 188 + 189 + [[package]] 190 + name = "bumpalo" 191 + version = "3.18.1" 192 + source = "registry+https://github.com/rust-lang/crates.io-index" 193 + checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" 194 + 195 + [[package]] 196 + name = "bytes" 197 + version = "1.10.1" 198 + source = "registry+https://github.com/rust-lang/crates.io-index" 199 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 200 + 201 + [[package]] 202 + name = "cfg-if" 203 + version = "1.0.1" 204 + source = "registry+https://github.com/rust-lang/crates.io-index" 205 + checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" 206 + 207 + [[package]] 208 + name = "colog" 209 + version = "1.3.0" 210 + source = "registry+https://github.com/rust-lang/crates.io-index" 211 + checksum = "2c426b7af8d5e0ad79de6713996632ce31f0d68ba84068fb0d654b396e519df0" 212 + dependencies = [ 213 + "colored", 214 + "env_logger", 215 + "log", 216 + ] 217 + 218 + [[package]] 219 + name = "colorchoice" 220 + version = "1.0.4" 221 + source = "registry+https://github.com/rust-lang/crates.io-index" 222 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 223 + 224 + [[package]] 225 + name = "colored" 226 + version = "2.2.0" 227 + source = "registry+https://github.com/rust-lang/crates.io-index" 228 + checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" 229 + dependencies = [ 230 + "lazy_static", 231 + "windows-sys 0.59.0", 232 + ] 233 + 234 + [[package]] 235 + name = "cpufeatures" 236 + version = "0.2.17" 237 + source = "registry+https://github.com/rust-lang/crates.io-index" 238 + checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 239 + dependencies = [ 240 + "libc", 241 + ] 242 + 243 + [[package]] 244 + name = "crypto-common" 245 + version = "0.1.6" 246 + source = "registry+https://github.com/rust-lang/crates.io-index" 247 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 248 + dependencies = [ 249 + "generic-array", 250 + "typenum", 251 + ] 252 + 253 + [[package]] 254 + name = "data-encoding" 255 + version = "2.9.0" 256 + source = "registry+https://github.com/rust-lang/crates.io-index" 257 + checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" 258 + 259 + [[package]] 260 + name = "derive_more" 261 + version = "2.0.1" 262 + source = "registry+https://github.com/rust-lang/crates.io-index" 263 + checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" 264 + dependencies = [ 265 + "derive_more-impl", 266 + ] 267 + 268 + [[package]] 269 + name = "derive_more-impl" 270 + version = "2.0.1" 271 + source = "registry+https://github.com/rust-lang/crates.io-index" 272 + checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" 273 + dependencies = [ 274 + "proc-macro2", 275 + "quote", 276 + "syn", 277 + "unicode-xid", 278 + ] 279 + 280 + [[package]] 281 + name = "digest" 282 + version = "0.10.7" 283 + source = "registry+https://github.com/rust-lang/crates.io-index" 284 + checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 285 + dependencies = [ 286 + "block-buffer", 287 + "crypto-common", 288 + ] 289 + 290 + [[package]] 291 + name = "env_filter" 292 + version = "0.1.3" 293 + source = "registry+https://github.com/rust-lang/crates.io-index" 294 + checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" 295 + dependencies = [ 296 + "log", 297 + "regex", 298 + ] 299 + 300 + [[package]] 301 + name = "env_logger" 302 + version = "0.11.8" 303 + source = "registry+https://github.com/rust-lang/crates.io-index" 304 + checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" 305 + dependencies = [ 306 + "anstream", 307 + "anstyle", 308 + "env_filter", 309 + "jiff", 310 + "log", 311 + ] 312 + 313 + [[package]] 314 + name = "fnv" 315 + version = "1.0.7" 316 + source = "registry+https://github.com/rust-lang/crates.io-index" 317 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 318 + 319 + [[package]] 320 + name = "form_urlencoded" 321 + version = "1.2.1" 322 + source = "registry+https://github.com/rust-lang/crates.io-index" 323 + checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 324 + dependencies = [ 325 + "percent-encoding", 326 + ] 327 + 328 + [[package]] 329 + name = "futures" 330 + version = "0.3.31" 331 + source = "registry+https://github.com/rust-lang/crates.io-index" 332 + checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 333 + dependencies = [ 334 + "futures-channel", 335 + "futures-core", 336 + "futures-executor", 337 + "futures-io", 338 + "futures-sink", 339 + "futures-task", 340 + "futures-util", 341 + ] 342 + 343 + [[package]] 344 + name = "futures-channel" 345 + version = "0.3.31" 346 + source = "registry+https://github.com/rust-lang/crates.io-index" 347 + checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 348 + dependencies = [ 349 + "futures-core", 350 + "futures-sink", 351 + ] 352 + 353 + [[package]] 354 + name = "futures-core" 355 + version = "0.3.31" 356 + source = "registry+https://github.com/rust-lang/crates.io-index" 357 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 358 + 359 + [[package]] 360 + name = "futures-executor" 361 + version = "0.3.31" 362 + source = "registry+https://github.com/rust-lang/crates.io-index" 363 + checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 364 + dependencies = [ 365 + "futures-core", 366 + "futures-task", 367 + "futures-util", 368 + ] 369 + 370 + [[package]] 371 + name = "futures-io" 372 + version = "0.3.31" 373 + source = "registry+https://github.com/rust-lang/crates.io-index" 374 + checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 375 + 376 + [[package]] 377 + name = "futures-macro" 378 + version = "0.3.31" 379 + source = "registry+https://github.com/rust-lang/crates.io-index" 380 + checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 381 + dependencies = [ 382 + "proc-macro2", 383 + "quote", 384 + "syn", 385 + ] 386 + 387 + [[package]] 388 + name = "futures-sink" 389 + version = "0.3.31" 390 + source = "registry+https://github.com/rust-lang/crates.io-index" 391 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 392 + 393 + [[package]] 394 + name = "futures-task" 395 + version = "0.3.31" 396 + source = "registry+https://github.com/rust-lang/crates.io-index" 397 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 398 + 399 + [[package]] 400 + name = "futures-util" 401 + version = "0.3.31" 402 + source = "registry+https://github.com/rust-lang/crates.io-index" 403 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 404 + dependencies = [ 405 + "futures-channel", 406 + "futures-core", 407 + "futures-io", 408 + "futures-macro", 409 + "futures-sink", 410 + "futures-task", 411 + "memchr", 412 + "pin-project-lite", 413 + "pin-utils", 414 + "slab", 415 + ] 416 + 417 + [[package]] 418 + name = "generic-array" 419 + version = "0.14.7" 420 + source = "registry+https://github.com/rust-lang/crates.io-index" 421 + checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 422 + dependencies = [ 423 + "typenum", 424 + "version_check", 425 + ] 426 + 427 + [[package]] 428 + name = "getrandom" 429 + version = "0.3.3" 430 + source = "registry+https://github.com/rust-lang/crates.io-index" 431 + checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 432 + dependencies = [ 433 + "cfg-if", 434 + "libc", 435 + "r-efi", 436 + "wasi 0.14.2+wasi-0.2.4", 437 + ] 438 + 439 + [[package]] 440 + name = "gimli" 441 + version = "0.31.1" 442 + source = "registry+https://github.com/rust-lang/crates.io-index" 443 + checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 444 + 445 + [[package]] 446 + name = "http" 447 + version = "1.3.1" 448 + source = "registry+https://github.com/rust-lang/crates.io-index" 449 + checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 450 + dependencies = [ 451 + "bytes", 452 + "fnv", 453 + "itoa", 454 + ] 455 + 456 + [[package]] 457 + name = "http-body" 458 + version = "1.0.1" 459 + source = "registry+https://github.com/rust-lang/crates.io-index" 460 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 461 + dependencies = [ 462 + "bytes", 463 + "http", 464 + ] 465 + 466 + [[package]] 467 + name = "http-body-util" 468 + version = "0.1.3" 469 + source = "registry+https://github.com/rust-lang/crates.io-index" 470 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 471 + dependencies = [ 472 + "bytes", 473 + "futures-core", 474 + "http", 475 + "http-body", 476 + "pin-project-lite", 477 + ] 478 + 479 + [[package]] 480 + name = "httparse" 481 + version = "1.10.1" 482 + source = "registry+https://github.com/rust-lang/crates.io-index" 483 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 484 + 485 + [[package]] 486 + name = "httpdate" 487 + version = "1.0.3" 488 + source = "registry+https://github.com/rust-lang/crates.io-index" 489 + checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 490 + 491 + [[package]] 492 + name = "hyper" 493 + version = "1.6.0" 494 + source = "registry+https://github.com/rust-lang/crates.io-index" 495 + checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 496 + dependencies = [ 497 + "bytes", 498 + "futures-channel", 499 + "futures-util", 500 + "http", 501 + "http-body", 502 + "httparse", 503 + "httpdate", 504 + "itoa", 505 + "pin-project-lite", 506 + "smallvec", 507 + "tokio", 508 + ] 509 + 510 + [[package]] 511 + name = "hyper-util" 512 + version = "0.1.14" 513 + source = "registry+https://github.com/rust-lang/crates.io-index" 514 + checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" 515 + dependencies = [ 516 + "bytes", 517 + "futures-core", 518 + "http", 519 + "http-body", 520 + "hyper", 521 + "pin-project-lite", 522 + "tokio", 523 + "tower-service", 524 + ] 525 + 526 + [[package]] 527 + name = "is_terminal_polyfill" 528 + version = "1.70.1" 529 + source = "registry+https://github.com/rust-lang/crates.io-index" 530 + checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 531 + 532 + [[package]] 533 + name = "itoa" 534 + version = "1.0.15" 535 + source = "registry+https://github.com/rust-lang/crates.io-index" 536 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 537 + 538 + [[package]] 539 + name = "jiff" 540 + version = "0.2.15" 541 + source = "registry+https://github.com/rust-lang/crates.io-index" 542 + checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" 543 + dependencies = [ 544 + "jiff-static", 545 + "log", 546 + "portable-atomic", 547 + "portable-atomic-util", 548 + "serde", 549 + ] 550 + 551 + [[package]] 552 + name = "jiff-static" 553 + version = "0.2.15" 554 + source = "registry+https://github.com/rust-lang/crates.io-index" 555 + checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" 556 + dependencies = [ 557 + "proc-macro2", 558 + "quote", 559 + "syn", 560 + ] 561 + 562 + [[package]] 563 + name = "js-sys" 564 + version = "0.3.77" 565 + source = "registry+https://github.com/rust-lang/crates.io-index" 566 + checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 567 + dependencies = [ 568 + "once_cell", 569 + "wasm-bindgen", 570 + ] 571 + 572 + [[package]] 573 + name = "lazy_static" 574 + version = "1.5.0" 575 + source = "registry+https://github.com/rust-lang/crates.io-index" 576 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 577 + 578 + [[package]] 579 + name = "libc" 580 + version = "0.2.173" 581 + source = "registry+https://github.com/rust-lang/crates.io-index" 582 + checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb" 583 + 584 + [[package]] 585 + name = "log" 586 + version = "0.4.27" 587 + source = "registry+https://github.com/rust-lang/crates.io-index" 588 + checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 589 + 590 + [[package]] 591 + name = "manhunt-signaling" 592 + version = "0.1.0" 593 + dependencies = [ 594 + "anyhow", 595 + "async-trait", 596 + "axum", 597 + "colog", 598 + "futures", 599 + "log", 600 + "matchbox_protocol", 601 + "matchbox_signaling", 602 + "tokio", 603 + ] 604 + 605 + [[package]] 606 + name = "matchbox_protocol" 607 + version = "0.12.0" 608 + source = "registry+https://github.com/rust-lang/crates.io-index" 609 + checksum = "f0cfe43dd6af96da1ea044838f59b8d7438971f85376be464ead11bbd7a01c27" 610 + dependencies = [ 611 + "cfg-if", 612 + "derive_more", 613 + "serde", 614 + "serde_json", 615 + "uuid", 616 + ] 617 + 618 + [[package]] 619 + name = "matchbox_signaling" 620 + version = "0.12.0" 621 + source = "registry+https://github.com/rust-lang/crates.io-index" 622 + checksum = "0f30f7e4302e1d80a824503c78b893bf0635ee864a7c0e4394d76b6dd61bab12" 623 + dependencies = [ 624 + "async-trait", 625 + "axum", 626 + "futures", 627 + "hyper", 628 + "matchbox_protocol", 629 + "serde", 630 + "serde_json", 631 + "thiserror", 632 + "tokio", 633 + "tokio-stream", 634 + "tower-http", 635 + "tracing", 636 + "uuid", 637 + ] 638 + 639 + [[package]] 640 + name = "matchit" 641 + version = "0.8.4" 642 + source = "registry+https://github.com/rust-lang/crates.io-index" 643 + checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" 644 + 645 + [[package]] 646 + name = "memchr" 647 + version = "2.7.5" 648 + source = "registry+https://github.com/rust-lang/crates.io-index" 649 + checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 650 + 651 + [[package]] 652 + name = "mime" 653 + version = "0.3.17" 654 + source = "registry+https://github.com/rust-lang/crates.io-index" 655 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 656 + 657 + [[package]] 658 + name = "miniz_oxide" 659 + version = "0.8.9" 660 + source = "registry+https://github.com/rust-lang/crates.io-index" 661 + checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 662 + dependencies = [ 663 + "adler2", 664 + ] 665 + 666 + [[package]] 667 + name = "mio" 668 + version = "1.0.4" 669 + source = "registry+https://github.com/rust-lang/crates.io-index" 670 + checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 671 + dependencies = [ 672 + "libc", 673 + "wasi 0.11.1+wasi-snapshot-preview1", 674 + "windows-sys 0.59.0", 675 + ] 676 + 677 + [[package]] 678 + name = "object" 679 + version = "0.36.7" 680 + source = "registry+https://github.com/rust-lang/crates.io-index" 681 + checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 682 + dependencies = [ 683 + "memchr", 684 + ] 685 + 686 + [[package]] 687 + name = "once_cell" 688 + version = "1.21.3" 689 + source = "registry+https://github.com/rust-lang/crates.io-index" 690 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 691 + 692 + [[package]] 693 + name = "once_cell_polyfill" 694 + version = "1.70.1" 695 + source = "registry+https://github.com/rust-lang/crates.io-index" 696 + checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 697 + 698 + [[package]] 699 + name = "percent-encoding" 700 + version = "2.3.1" 701 + source = "registry+https://github.com/rust-lang/crates.io-index" 702 + checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 703 + 704 + [[package]] 705 + name = "pin-project-lite" 706 + version = "0.2.16" 707 + source = "registry+https://github.com/rust-lang/crates.io-index" 708 + checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 709 + 710 + [[package]] 711 + name = "pin-utils" 712 + version = "0.1.0" 713 + source = "registry+https://github.com/rust-lang/crates.io-index" 714 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 715 + 716 + [[package]] 717 + name = "portable-atomic" 718 + version = "1.11.1" 719 + source = "registry+https://github.com/rust-lang/crates.io-index" 720 + checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" 721 + 722 + [[package]] 723 + name = "portable-atomic-util" 724 + version = "0.2.4" 725 + source = "registry+https://github.com/rust-lang/crates.io-index" 726 + checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" 727 + dependencies = [ 728 + "portable-atomic", 729 + ] 730 + 731 + [[package]] 732 + name = "ppv-lite86" 733 + version = "0.2.21" 734 + source = "registry+https://github.com/rust-lang/crates.io-index" 735 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 736 + dependencies = [ 737 + "zerocopy", 738 + ] 739 + 740 + [[package]] 741 + name = "proc-macro2" 742 + version = "1.0.95" 743 + source = "registry+https://github.com/rust-lang/crates.io-index" 744 + checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 745 + dependencies = [ 746 + "unicode-ident", 747 + ] 748 + 749 + [[package]] 750 + name = "quote" 751 + version = "1.0.40" 752 + source = "registry+https://github.com/rust-lang/crates.io-index" 753 + checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 754 + dependencies = [ 755 + "proc-macro2", 756 + ] 757 + 758 + [[package]] 759 + name = "r-efi" 760 + version = "5.2.0" 761 + source = "registry+https://github.com/rust-lang/crates.io-index" 762 + checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 763 + 764 + [[package]] 765 + name = "rand" 766 + version = "0.9.1" 767 + source = "registry+https://github.com/rust-lang/crates.io-index" 768 + checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" 769 + dependencies = [ 770 + "rand_chacha", 771 + "rand_core", 772 + ] 773 + 774 + [[package]] 775 + name = "rand_chacha" 776 + version = "0.9.0" 777 + source = "registry+https://github.com/rust-lang/crates.io-index" 778 + checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 779 + dependencies = [ 780 + "ppv-lite86", 781 + "rand_core", 782 + ] 783 + 784 + [[package]] 785 + name = "rand_core" 786 + version = "0.9.3" 787 + source = "registry+https://github.com/rust-lang/crates.io-index" 788 + checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 789 + dependencies = [ 790 + "getrandom", 791 + ] 792 + 793 + [[package]] 794 + name = "regex" 795 + version = "1.11.1" 796 + source = "registry+https://github.com/rust-lang/crates.io-index" 797 + checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 798 + dependencies = [ 799 + "aho-corasick", 800 + "memchr", 801 + "regex-automata", 802 + "regex-syntax", 803 + ] 804 + 805 + [[package]] 806 + name = "regex-automata" 807 + version = "0.4.9" 808 + source = "registry+https://github.com/rust-lang/crates.io-index" 809 + checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 810 + dependencies = [ 811 + "aho-corasick", 812 + "memchr", 813 + "regex-syntax", 814 + ] 815 + 816 + [[package]] 817 + name = "regex-syntax" 818 + version = "0.8.5" 819 + source = "registry+https://github.com/rust-lang/crates.io-index" 820 + checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 821 + 822 + [[package]] 823 + name = "rustc-demangle" 824 + version = "0.1.25" 825 + source = "registry+https://github.com/rust-lang/crates.io-index" 826 + checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" 827 + 828 + [[package]] 829 + name = "rustversion" 830 + version = "1.0.21" 831 + source = "registry+https://github.com/rust-lang/crates.io-index" 832 + checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" 833 + 834 + [[package]] 835 + name = "ryu" 836 + version = "1.0.20" 837 + source = "registry+https://github.com/rust-lang/crates.io-index" 838 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 839 + 840 + [[package]] 841 + name = "serde" 842 + version = "1.0.219" 843 + source = "registry+https://github.com/rust-lang/crates.io-index" 844 + checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 845 + dependencies = [ 846 + "serde_derive", 847 + ] 848 + 849 + [[package]] 850 + name = "serde_derive" 851 + version = "1.0.219" 852 + source = "registry+https://github.com/rust-lang/crates.io-index" 853 + checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 854 + dependencies = [ 855 + "proc-macro2", 856 + "quote", 857 + "syn", 858 + ] 859 + 860 + [[package]] 861 + name = "serde_json" 862 + version = "1.0.140" 863 + source = "registry+https://github.com/rust-lang/crates.io-index" 864 + checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 865 + dependencies = [ 866 + "itoa", 867 + "memchr", 868 + "ryu", 869 + "serde", 870 + ] 871 + 872 + [[package]] 873 + name = "serde_path_to_error" 874 + version = "0.1.17" 875 + source = "registry+https://github.com/rust-lang/crates.io-index" 876 + checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" 877 + dependencies = [ 878 + "itoa", 879 + "serde", 880 + ] 881 + 882 + [[package]] 883 + name = "serde_urlencoded" 884 + version = "0.7.1" 885 + source = "registry+https://github.com/rust-lang/crates.io-index" 886 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 887 + dependencies = [ 888 + "form_urlencoded", 889 + "itoa", 890 + "ryu", 891 + "serde", 892 + ] 893 + 894 + [[package]] 895 + name = "sha1" 896 + version = "0.10.6" 897 + source = "registry+https://github.com/rust-lang/crates.io-index" 898 + checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 899 + dependencies = [ 900 + "cfg-if", 901 + "cpufeatures", 902 + "digest", 903 + ] 904 + 905 + [[package]] 906 + name = "slab" 907 + version = "0.4.10" 908 + source = "registry+https://github.com/rust-lang/crates.io-index" 909 + checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" 910 + 911 + [[package]] 912 + name = "smallvec" 913 + version = "1.15.1" 914 + source = "registry+https://github.com/rust-lang/crates.io-index" 915 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 916 + 917 + [[package]] 918 + name = "socket2" 919 + version = "0.5.10" 920 + source = "registry+https://github.com/rust-lang/crates.io-index" 921 + checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 922 + dependencies = [ 923 + "libc", 924 + "windows-sys 0.52.0", 925 + ] 926 + 927 + [[package]] 928 + name = "syn" 929 + version = "2.0.103" 930 + source = "registry+https://github.com/rust-lang/crates.io-index" 931 + checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" 932 + dependencies = [ 933 + "proc-macro2", 934 + "quote", 935 + "unicode-ident", 936 + ] 937 + 938 + [[package]] 939 + name = "sync_wrapper" 940 + version = "1.0.2" 941 + source = "registry+https://github.com/rust-lang/crates.io-index" 942 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 943 + 944 + [[package]] 945 + name = "thiserror" 946 + version = "2.0.12" 947 + source = "registry+https://github.com/rust-lang/crates.io-index" 948 + checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 949 + dependencies = [ 950 + "thiserror-impl", 951 + ] 952 + 953 + [[package]] 954 + name = "thiserror-impl" 955 + version = "2.0.12" 956 + source = "registry+https://github.com/rust-lang/crates.io-index" 957 + checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 958 + dependencies = [ 959 + "proc-macro2", 960 + "quote", 961 + "syn", 962 + ] 963 + 964 + [[package]] 965 + name = "tokio" 966 + version = "1.45.1" 967 + source = "registry+https://github.com/rust-lang/crates.io-index" 968 + checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" 969 + dependencies = [ 970 + "backtrace", 971 + "bytes", 972 + "libc", 973 + "mio", 974 + "pin-project-lite", 975 + "socket2", 976 + "tokio-macros", 977 + "windows-sys 0.52.0", 978 + ] 979 + 980 + [[package]] 981 + name = "tokio-macros" 982 + version = "2.5.0" 983 + source = "registry+https://github.com/rust-lang/crates.io-index" 984 + checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 985 + dependencies = [ 986 + "proc-macro2", 987 + "quote", 988 + "syn", 989 + ] 990 + 991 + [[package]] 992 + name = "tokio-stream" 993 + version = "0.1.17" 994 + source = "registry+https://github.com/rust-lang/crates.io-index" 995 + checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" 996 + dependencies = [ 997 + "futures-core", 998 + "pin-project-lite", 999 + "tokio", 1000 + ] 1001 + 1002 + [[package]] 1003 + name = "tokio-tungstenite" 1004 + version = "0.26.2" 1005 + source = "registry+https://github.com/rust-lang/crates.io-index" 1006 + checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" 1007 + dependencies = [ 1008 + "futures-util", 1009 + "log", 1010 + "tokio", 1011 + "tungstenite", 1012 + ] 1013 + 1014 + [[package]] 1015 + name = "tower" 1016 + version = "0.5.2" 1017 + source = "registry+https://github.com/rust-lang/crates.io-index" 1018 + checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1019 + dependencies = [ 1020 + "futures-core", 1021 + "futures-util", 1022 + "pin-project-lite", 1023 + "sync_wrapper", 1024 + "tokio", 1025 + "tower-layer", 1026 + "tower-service", 1027 + "tracing", 1028 + ] 1029 + 1030 + [[package]] 1031 + name = "tower-http" 1032 + version = "0.6.6" 1033 + source = "registry+https://github.com/rust-lang/crates.io-index" 1034 + checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" 1035 + dependencies = [ 1036 + "bitflags", 1037 + "bytes", 1038 + "http", 1039 + "http-body", 1040 + "pin-project-lite", 1041 + "tower-layer", 1042 + "tower-service", 1043 + "tracing", 1044 + ] 1045 + 1046 + [[package]] 1047 + name = "tower-layer" 1048 + version = "0.3.3" 1049 + source = "registry+https://github.com/rust-lang/crates.io-index" 1050 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1051 + 1052 + [[package]] 1053 + name = "tower-service" 1054 + version = "0.3.3" 1055 + source = "registry+https://github.com/rust-lang/crates.io-index" 1056 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1057 + 1058 + [[package]] 1059 + name = "tracing" 1060 + version = "0.1.41" 1061 + source = "registry+https://github.com/rust-lang/crates.io-index" 1062 + checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1063 + dependencies = [ 1064 + "log", 1065 + "pin-project-lite", 1066 + "tracing-attributes", 1067 + "tracing-core", 1068 + ] 1069 + 1070 + [[package]] 1071 + name = "tracing-attributes" 1072 + version = "0.1.29" 1073 + source = "registry+https://github.com/rust-lang/crates.io-index" 1074 + checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" 1075 + dependencies = [ 1076 + "proc-macro2", 1077 + "quote", 1078 + "syn", 1079 + ] 1080 + 1081 + [[package]] 1082 + name = "tracing-core" 1083 + version = "0.1.34" 1084 + source = "registry+https://github.com/rust-lang/crates.io-index" 1085 + checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 1086 + dependencies = [ 1087 + "once_cell", 1088 + ] 1089 + 1090 + [[package]] 1091 + name = "tungstenite" 1092 + version = "0.26.2" 1093 + source = "registry+https://github.com/rust-lang/crates.io-index" 1094 + checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" 1095 + dependencies = [ 1096 + "bytes", 1097 + "data-encoding", 1098 + "http", 1099 + "httparse", 1100 + "log", 1101 + "rand", 1102 + "sha1", 1103 + "thiserror", 1104 + "utf-8", 1105 + ] 1106 + 1107 + [[package]] 1108 + name = "typenum" 1109 + version = "1.18.0" 1110 + source = "registry+https://github.com/rust-lang/crates.io-index" 1111 + checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 1112 + 1113 + [[package]] 1114 + name = "unicode-ident" 1115 + version = "1.0.18" 1116 + source = "registry+https://github.com/rust-lang/crates.io-index" 1117 + checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1118 + 1119 + [[package]] 1120 + name = "unicode-xid" 1121 + version = "0.2.6" 1122 + source = "registry+https://github.com/rust-lang/crates.io-index" 1123 + checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 1124 + 1125 + [[package]] 1126 + name = "utf-8" 1127 + version = "0.7.6" 1128 + source = "registry+https://github.com/rust-lang/crates.io-index" 1129 + checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 1130 + 1131 + [[package]] 1132 + name = "utf8parse" 1133 + version = "0.2.2" 1134 + source = "registry+https://github.com/rust-lang/crates.io-index" 1135 + checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1136 + 1137 + [[package]] 1138 + name = "uuid" 1139 + version = "1.17.0" 1140 + source = "registry+https://github.com/rust-lang/crates.io-index" 1141 + checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" 1142 + dependencies = [ 1143 + "getrandom", 1144 + "js-sys", 1145 + "serde", 1146 + "wasm-bindgen", 1147 + ] 1148 + 1149 + [[package]] 1150 + name = "version_check" 1151 + version = "0.9.5" 1152 + source = "registry+https://github.com/rust-lang/crates.io-index" 1153 + checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1154 + 1155 + [[package]] 1156 + name = "wasi" 1157 + version = "0.11.1+wasi-snapshot-preview1" 1158 + source = "registry+https://github.com/rust-lang/crates.io-index" 1159 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 1160 + 1161 + [[package]] 1162 + name = "wasi" 1163 + version = "0.14.2+wasi-0.2.4" 1164 + source = "registry+https://github.com/rust-lang/crates.io-index" 1165 + checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 1166 + dependencies = [ 1167 + "wit-bindgen-rt", 1168 + ] 1169 + 1170 + [[package]] 1171 + name = "wasm-bindgen" 1172 + version = "0.2.100" 1173 + source = "registry+https://github.com/rust-lang/crates.io-index" 1174 + checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1175 + dependencies = [ 1176 + "cfg-if", 1177 + "once_cell", 1178 + "rustversion", 1179 + "wasm-bindgen-macro", 1180 + ] 1181 + 1182 + [[package]] 1183 + name = "wasm-bindgen-backend" 1184 + version = "0.2.100" 1185 + source = "registry+https://github.com/rust-lang/crates.io-index" 1186 + checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1187 + dependencies = [ 1188 + "bumpalo", 1189 + "log", 1190 + "proc-macro2", 1191 + "quote", 1192 + "syn", 1193 + "wasm-bindgen-shared", 1194 + ] 1195 + 1196 + [[package]] 1197 + name = "wasm-bindgen-macro" 1198 + version = "0.2.100" 1199 + source = "registry+https://github.com/rust-lang/crates.io-index" 1200 + checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1201 + dependencies = [ 1202 + "quote", 1203 + "wasm-bindgen-macro-support", 1204 + ] 1205 + 1206 + [[package]] 1207 + name = "wasm-bindgen-macro-support" 1208 + version = "0.2.100" 1209 + source = "registry+https://github.com/rust-lang/crates.io-index" 1210 + checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1211 + dependencies = [ 1212 + "proc-macro2", 1213 + "quote", 1214 + "syn", 1215 + "wasm-bindgen-backend", 1216 + "wasm-bindgen-shared", 1217 + ] 1218 + 1219 + [[package]] 1220 + name = "wasm-bindgen-shared" 1221 + version = "0.2.100" 1222 + source = "registry+https://github.com/rust-lang/crates.io-index" 1223 + checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1224 + dependencies = [ 1225 + "unicode-ident", 1226 + ] 1227 + 1228 + [[package]] 1229 + name = "windows-sys" 1230 + version = "0.52.0" 1231 + source = "registry+https://github.com/rust-lang/crates.io-index" 1232 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1233 + dependencies = [ 1234 + "windows-targets", 1235 + ] 1236 + 1237 + [[package]] 1238 + name = "windows-sys" 1239 + version = "0.59.0" 1240 + source = "registry+https://github.com/rust-lang/crates.io-index" 1241 + checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1242 + dependencies = [ 1243 + "windows-targets", 1244 + ] 1245 + 1246 + [[package]] 1247 + name = "windows-targets" 1248 + version = "0.52.6" 1249 + source = "registry+https://github.com/rust-lang/crates.io-index" 1250 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1251 + dependencies = [ 1252 + "windows_aarch64_gnullvm", 1253 + "windows_aarch64_msvc", 1254 + "windows_i686_gnu", 1255 + "windows_i686_gnullvm", 1256 + "windows_i686_msvc", 1257 + "windows_x86_64_gnu", 1258 + "windows_x86_64_gnullvm", 1259 + "windows_x86_64_msvc", 1260 + ] 1261 + 1262 + [[package]] 1263 + name = "windows_aarch64_gnullvm" 1264 + version = "0.52.6" 1265 + source = "registry+https://github.com/rust-lang/crates.io-index" 1266 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1267 + 1268 + [[package]] 1269 + name = "windows_aarch64_msvc" 1270 + version = "0.52.6" 1271 + source = "registry+https://github.com/rust-lang/crates.io-index" 1272 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1273 + 1274 + [[package]] 1275 + name = "windows_i686_gnu" 1276 + version = "0.52.6" 1277 + source = "registry+https://github.com/rust-lang/crates.io-index" 1278 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1279 + 1280 + [[package]] 1281 + name = "windows_i686_gnullvm" 1282 + version = "0.52.6" 1283 + source = "registry+https://github.com/rust-lang/crates.io-index" 1284 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1285 + 1286 + [[package]] 1287 + name = "windows_i686_msvc" 1288 + version = "0.52.6" 1289 + source = "registry+https://github.com/rust-lang/crates.io-index" 1290 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1291 + 1292 + [[package]] 1293 + name = "windows_x86_64_gnu" 1294 + version = "0.52.6" 1295 + source = "registry+https://github.com/rust-lang/crates.io-index" 1296 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1297 + 1298 + [[package]] 1299 + name = "windows_x86_64_gnullvm" 1300 + version = "0.52.6" 1301 + source = "registry+https://github.com/rust-lang/crates.io-index" 1302 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1303 + 1304 + [[package]] 1305 + name = "windows_x86_64_msvc" 1306 + version = "0.52.6" 1307 + source = "registry+https://github.com/rust-lang/crates.io-index" 1308 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1309 + 1310 + [[package]] 1311 + name = "wit-bindgen-rt" 1312 + version = "0.39.0" 1313 + source = "registry+https://github.com/rust-lang/crates.io-index" 1314 + checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 1315 + dependencies = [ 1316 + "bitflags", 1317 + ] 1318 + 1319 + [[package]] 1320 + name = "zerocopy" 1321 + version = "0.8.25" 1322 + source = "registry+https://github.com/rust-lang/crates.io-index" 1323 + checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" 1324 + dependencies = [ 1325 + "zerocopy-derive", 1326 + ] 1327 + 1328 + [[package]] 1329 + name = "zerocopy-derive" 1330 + version = "0.8.25" 1331 + source = "registry+https://github.com/rust-lang/crates.io-index" 1332 + checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" 1333 + dependencies = [ 1334 + "proc-macro2", 1335 + "quote", 1336 + "syn", 1337 + ]
+20
manhunt-signaling/Cargo.toml
··· 1 + [package] 2 + name = "manhunt-signaling" 3 + version = "0.1.0" 4 + edition = "2024" 5 + default-run = "manhunt-signaling" 6 + 7 + [[bin]] 8 + name = "manhunt-signaling" 9 + path = "main.rs" 10 + 11 + [dependencies] 12 + anyhow = "1.0.98" 13 + async-trait = "0.1.88" 14 + axum = { version = "0.8.4", features = ["ws"] } 15 + colog = "1.3.0" 16 + futures = "0.3.31" 17 + log = "0.4.27" 18 + matchbox_protocol = "0.12.0" 19 + matchbox_signaling = "0.12.0" 20 + tokio = { version = "1.45.1", features = ["macros"] }
+336
manhunt-signaling/main.rs
··· 1 + use async_trait::async_trait; 2 + use axum::{ 3 + Error as AxumError, 4 + extract::{Path, ws::Message}, 5 + http::StatusCode, 6 + response::IntoResponse, 7 + routing::get, 8 + }; 9 + use futures::StreamExt; 10 + use log::{debug, error, info, warn}; 11 + use matchbox_protocol::{JsonPeerEvent, PeerId, PeerRequest}; 12 + use matchbox_signaling::{ 13 + ClientRequestError, NoCallbacks, SignalingError, SignalingServerBuilder, SignalingState, 14 + SignalingTopology, WsStateMeta, 15 + common_logic::{self, StateObj, parse_request}, 16 + }; 17 + 18 + use anyhow::Context; 19 + use std::{ 20 + collections::{HashMap, HashSet}, 21 + net::{IpAddr, Ipv4Addr, SocketAddr}, 22 + result::Result as StdResult, 23 + }; 24 + use tokio::sync::mpsc::UnboundedSender; 25 + 26 + type Result<T = (), E = anyhow::Error> = StdResult<T, E>; 27 + 28 + type RoomId = String; 29 + type Sender = UnboundedSender<Result<Message, AxumError>>; 30 + 31 + #[derive(Debug, Clone)] 32 + struct Match { 33 + pub open_lobby: bool, 34 + pub players: HashSet<PeerId>, 35 + } 36 + 37 + #[derive(Debug, Clone)] 38 + struct Peer { 39 + pub room: RoomId, 40 + sender: Sender, 41 + } 42 + 43 + impl Match { 44 + pub fn new() -> Self { 45 + Self { 46 + open_lobby: true, 47 + players: HashSet::with_capacity(10), 48 + } 49 + } 50 + } 51 + 52 + #[derive(Default, Debug, Clone)] 53 + struct ServerState { 54 + waiting_clients: StateObj<HashMap<SocketAddr, RoomId>>, 55 + queued_clients: StateObj<HashMap<PeerId, RoomId>>, 56 + matches: StateObj<HashMap<RoomId, Match>>, 57 + clients: StateObj<HashMap<PeerId, Peer>>, 58 + } 59 + 60 + impl SignalingState for ServerState {} 61 + 62 + impl ServerState { 63 + fn add_client(&mut self, origin: SocketAddr, code: RoomId) { 64 + self.waiting_clients 65 + .lock() 66 + .unwrap() 67 + .insert(origin, code.clone()); 68 + } 69 + 70 + pub fn room_is_open(&self, room_id: RoomId) -> bool { 71 + self.matches 72 + .lock() 73 + .unwrap() 74 + .get(&room_id) 75 + .is_some_and(|m| m.open_lobby) 76 + } 77 + 78 + /// Mark a match as started, disallowing others from joining 79 + pub fn mark_started(&mut self, room: &RoomId) { 80 + if let Some(mat) = self.matches.lock().unwrap().get_mut(room) { 81 + mat.open_lobby = false; 82 + } 83 + } 84 + 85 + /// Create a new room with the given code, should be called when someone wants to host a game. 86 + /// Returns false if a room with that code already exists. 87 + pub fn create_room(&mut self, origin: SocketAddr, code: RoomId) -> bool { 88 + let mut matches = self.matches.lock().unwrap(); 89 + if matches.contains_key(&code) { 90 + false 91 + } else { 92 + matches.insert(code.clone(), Match::new()); 93 + drop(matches); 94 + self.add_client(origin, code); 95 + true 96 + } 97 + } 98 + 99 + /// Try to join a room by a code, returns `true` if successful 100 + pub fn try_join_room(&mut self, origin: SocketAddr, code: RoomId) -> bool { 101 + if self 102 + .matches 103 + .lock() 104 + .unwrap() 105 + .get(&code) 106 + .is_some_and(|m| m.open_lobby) 107 + { 108 + self.waiting_clients.lock().unwrap().insert(origin, code); 109 + true 110 + } else { 111 + false 112 + } 113 + } 114 + 115 + /// Assign a peer an id 116 + pub fn assign_peer_id(&mut self, origin: SocketAddr, peer_id: PeerId) { 117 + let target_room = self 118 + .waiting_clients 119 + .lock() 120 + .unwrap() 121 + .remove(&origin) 122 + .expect("origin not waiting?"); 123 + 124 + self.queued_clients 125 + .lock() 126 + .unwrap() 127 + .insert(peer_id, target_room); 128 + } 129 + 130 + /// Add a peer to a room, returns other peers in the match currently 131 + pub fn add_peer(&mut self, peer_id: PeerId, sender: Sender) -> Vec<PeerId> { 132 + let target_room = self 133 + .queued_clients 134 + .lock() 135 + .unwrap() 136 + .remove(&peer_id) 137 + .expect("peer not waiting?"); 138 + let mut matches = self.matches.lock().unwrap(); 139 + let mat = matches.get_mut(&target_room).expect("Room not found?"); 140 + let peers = mat.players.iter().copied().collect::<Vec<_>>(); 141 + mat.players.insert(peer_id); 142 + drop(matches); 143 + let peer = Peer { 144 + room: target_room, 145 + sender, 146 + }; 147 + self.clients.lock().unwrap().insert(peer_id, peer); 148 + peers 149 + } 150 + 151 + /// Disconnect a peer from a room. Automatically deletes the room if no peers remain. Returns 152 + /// the removed peer and the set of other peers in the room that need to be notified 153 + pub fn remove_peer(&mut self, peer_id: PeerId) -> Option<Vec<PeerId>> { 154 + let removed_peer = self.clients.lock().unwrap().remove(&peer_id)?; 155 + let other_peers = self 156 + .matches 157 + .lock() 158 + .unwrap() 159 + .get_mut(&removed_peer.room) 160 + .map(|m| { 161 + m.players.remove(&peer_id); 162 + m.players.iter().copied().collect::<Vec<_>>() 163 + }) 164 + .unwrap_or_default(); 165 + 166 + if other_peers.is_empty() { 167 + self.matches.lock().unwrap().remove(&removed_peer.room); 168 + } 169 + 170 + Some(other_peers) 171 + } 172 + 173 + pub fn try_send(&self, peer: PeerId, msg: Message) -> Result<(), SignalingError> { 174 + self.clients 175 + .lock() 176 + .unwrap() 177 + .get(&peer) 178 + .ok_or(SignalingError::UnknownPeer) 179 + .and_then(|peer| common_logic::try_send(&peer.sender, msg)) 180 + } 181 + } 182 + 183 + #[derive(Default, Debug)] 184 + struct ServerTopology; 185 + 186 + #[async_trait] 187 + impl SignalingTopology<NoCallbacks, ServerState> for ServerTopology { 188 + async fn state_machine(upgrade: WsStateMeta<NoCallbacks, ServerState>) { 189 + let WsStateMeta { 190 + peer_id, 191 + sender, 192 + mut receiver, 193 + mut state, 194 + .. 195 + } = upgrade; 196 + 197 + let other_peers = state.add_peer(peer_id, sender.clone()); 198 + 199 + let msg = Message::Text(JsonPeerEvent::NewPeer(peer_id).to_string().into()); 200 + 201 + for other_id in other_peers { 202 + if let Err(why) = state.try_send(other_id, msg.clone()) { 203 + error!("Failed to publish new peer event to {other_id}: {why:?}"); 204 + } 205 + } 206 + 207 + while let Some(req) = receiver.next().await { 208 + let req = match parse_request(req) { 209 + Ok(req) => req, 210 + Err(e) => match e { 211 + ClientRequestError::Axum(e) => { 212 + warn!("Peer {peer_id} encountered Axum error: {e:?}. Disconnecting..."); 213 + break; 214 + } 215 + ClientRequestError::Close => { 216 + info!("Peer {peer_id} closed connection"); 217 + break; 218 + } 219 + ClientRequestError::Json(_) | ClientRequestError::UnsupportedType(_) => { 220 + error!("Error parsing request from {peer_id}: {e:?}"); 221 + continue; // Recoverable, although may mean bad state? 222 + } 223 + }, 224 + }; 225 + 226 + if let PeerRequest::Signal { receiver, data } = req { 227 + let msg = Message::Text( 228 + JsonPeerEvent::Signal { 229 + sender: peer_id, 230 + data, 231 + } 232 + .to_string() 233 + .into(), 234 + ); 235 + if let Err(why) = state.try_send(receiver, msg) { 236 + error!("Error sending signaling message from {peer_id} to {receiver}: {why:?}"); 237 + } 238 + } // Other variant, PeerRequest::KeepAlive is just for a heartbeat, do nothing 239 + } 240 + 241 + info!("Peer {peer_id} disconnected"); 242 + 243 + let msg = Message::Text(JsonPeerEvent::PeerLeft(peer_id).to_string().into()); 244 + if let Some(other_peers) = state.remove_peer(peer_id) { 245 + for other_id in other_peers { 246 + if let Err(why) = state.try_send(other_id, msg.clone()) { 247 + warn!("Failed to alert {other_id} that {peer_id} has disconnected: {why:?}"); 248 + } 249 + } 250 + } else { 251 + warn!("Trying to remove peer {peer_id}, which doesn't exist?"); 252 + } 253 + } 254 + } 255 + 256 + #[tokio::main] 257 + async fn main() -> Result { 258 + colog::init(); 259 + 260 + let args = std::env::args().collect::<Vec<_>>(); 261 + let socket_addr = args 262 + .get(1) 263 + .map(|raw_binding| raw_binding.parse::<SocketAddr>()) 264 + .transpose() 265 + .context("Invalid socket addr passed")? 266 + .unwrap_or(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 3536)); 267 + 268 + let mut state = ServerState::default(); 269 + 270 + let server = SignalingServerBuilder::new(socket_addr, ServerTopology, state.clone()) 271 + .on_connection_request({ 272 + let mut state = state.clone(); 273 + move |connection| { 274 + info!("{} is requesting to connect", connection.origin); 275 + debug!("Connection meta: {connection:?}"); 276 + 277 + let err = if let Some(room_code) = connection.path.clone() { 278 + let is_host = connection.query_params.contains_key("create"); 279 + if is_host { 280 + if state.create_room(connection.origin, room_code) { 281 + None 282 + } else { 283 + Some(StatusCode::CONFLICT) 284 + } 285 + } else if state.try_join_room(connection.origin, room_code) { 286 + None 287 + } else { 288 + Some(StatusCode::NOT_FOUND) 289 + } 290 + } else { 291 + Some(StatusCode::BAD_REQUEST) 292 + }; 293 + 294 + if let Some(status) = err { 295 + Err(status.into_response()) 296 + } else { 297 + Ok(true) 298 + } 299 + } 300 + }) 301 + .mutate_router({ 302 + let state = state.clone(); 303 + move |router| { 304 + let mut state2 = state.clone(); 305 + router 306 + .route( 307 + "/room_exists/{id}", 308 + get(move |Path(room_id): Path<String>| async move { 309 + if state.room_is_open(room_id) { 310 + StatusCode::OK 311 + } else { 312 + StatusCode::NOT_FOUND 313 + } 314 + }), 315 + ) 316 + .route( 317 + "/mark_started/{id}", 318 + get(move |Path(room_id): Path<String>| async move { 319 + state2.mark_started(&room_id); 320 + StatusCode::OK 321 + }), 322 + ) 323 + } 324 + }) 325 + .on_id_assignment({ 326 + move |(socket, id)| { 327 + info!("Assigning id {id} to {socket}"); 328 + state.assign_peer_id(socket, id); 329 + } 330 + }) 331 + .build(); 332 + 333 + info!("Starting manhunt signaling server {}", env!("CARGO_PKG_VERSION")); 334 + 335 + server.serve().await.context("Error while running server") 336 + }