├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── assets ├── banner.png └── logo.png ├── crates ├── broadcast │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── lib.rs │ │ ├── rtc │ │ ├── codecs.rs │ │ ├── mod.rs │ │ ├── producers.rs │ │ ├── routers.rs │ │ └── workers.rs │ │ └── signaling │ │ ├── messages.rs │ │ ├── mod.rs │ │ └── websocket.rs └── ftl │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── lib.rs │ ├── protocol │ ├── command.rs │ ├── error.rs │ ├── handshake.rs │ ├── mod.rs │ └── response.rs │ ├── server.rs │ └── util.rs ├── packages ├── docs │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── docs │ │ ├── components │ │ │ ├── _category_.json │ │ │ ├── broadcast.md │ │ │ ├── ftl.md │ │ │ └── javascript-lib.md │ │ ├── ftl │ │ │ ├── _category_.json │ │ │ ├── establishing.md │ │ │ ├── overview.md │ │ │ ├── proposals.md │ │ │ ├── protocol.md │ │ │ └── security.md │ │ └── intro.md │ ├── docusaurus.config.js │ ├── package.json │ ├── sidebars.js │ ├── src │ │ ├── css │ │ │ └── custom.css │ │ └── theme │ │ │ └── prism-include-languages.js │ ├── static │ │ ├── .nojekyll │ │ ├── github-dark.min.css │ │ ├── highlight.min.js │ │ ├── img │ │ │ ├── favicon.ico │ │ │ ├── ftl_test.png │ │ │ └── logo.png │ │ └── inject.js │ └── yarn.lock ├── hyperspeed.js │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src │ │ ├── client.ts │ │ ├── index.ts │ │ └── messages.ts │ ├── tsconfig.json │ └── yarn.lock └── web-player │ ├── .eslintrc │ ├── .gitignore │ ├── README.md │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ ├── _app.tsx │ └── index.tsx │ ├── styles │ ├── Home.module.scss │ └── globals.scss │ ├── tsconfig.json │ └── yarn.lock └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "async-attributes" 16 | version = "1.1.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" 19 | dependencies = [ 20 | "quote", 21 | "syn", 22 | ] 23 | 24 | [[package]] 25 | name = "async-channel" 26 | version = "1.6.1" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" 29 | dependencies = [ 30 | "concurrent-queue", 31 | "event-listener", 32 | "futures-core", 33 | ] 34 | 35 | [[package]] 36 | name = "async-executor" 37 | version = "1.4.1" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" 40 | dependencies = [ 41 | "async-task", 42 | "concurrent-queue", 43 | "fastrand", 44 | "futures-lite", 45 | "once_cell", 46 | "slab", 47 | ] 48 | 49 | [[package]] 50 | name = "async-global-executor" 51 | version = "2.0.2" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" 54 | dependencies = [ 55 | "async-channel", 56 | "async-executor", 57 | "async-io", 58 | "async-mutex", 59 | "blocking", 60 | "futures-lite", 61 | "num_cpus", 62 | "once_cell", 63 | ] 64 | 65 | [[package]] 66 | name = "async-io" 67 | version = "1.6.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" 70 | dependencies = [ 71 | "concurrent-queue", 72 | "futures-lite", 73 | "libc", 74 | "log", 75 | "once_cell", 76 | "parking", 77 | "polling", 78 | "slab", 79 | "socket2", 80 | "waker-fn", 81 | "winapi", 82 | ] 83 | 84 | [[package]] 85 | name = "async-lock" 86 | version = "2.4.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" 89 | dependencies = [ 90 | "event-listener", 91 | ] 92 | 93 | [[package]] 94 | name = "async-mutex" 95 | version = "1.4.0" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" 98 | dependencies = [ 99 | "event-listener", 100 | ] 101 | 102 | [[package]] 103 | name = "async-oneshot" 104 | version = "0.5.0" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "1ec7c75bcbcb0139e9177f30692fd617405ca4e0c27802e128d53171f7042e2c" 107 | dependencies = [ 108 | "futures-micro", 109 | ] 110 | 111 | [[package]] 112 | name = "async-process" 113 | version = "1.3.0" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" 116 | dependencies = [ 117 | "async-io", 118 | "blocking", 119 | "cfg-if", 120 | "event-listener", 121 | "futures-lite", 122 | "libc", 123 | "once_cell", 124 | "signal-hook", 125 | "winapi", 126 | ] 127 | 128 | [[package]] 129 | name = "async-std" 130 | version = "1.10.0" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" 133 | dependencies = [ 134 | "async-attributes", 135 | "async-channel", 136 | "async-global-executor", 137 | "async-io", 138 | "async-lock", 139 | "async-process", 140 | "crossbeam-utils", 141 | "futures-channel", 142 | "futures-core", 143 | "futures-io", 144 | "futures-lite", 145 | "gloo-timers", 146 | "kv-log-macro", 147 | "log", 148 | "memchr", 149 | "num_cpus", 150 | "once_cell", 151 | "pin-project-lite", 152 | "pin-utils", 153 | "slab", 154 | "wasm-bindgen-futures", 155 | ] 156 | 157 | [[package]] 158 | name = "async-task" 159 | version = "4.1.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" 162 | 163 | [[package]] 164 | name = "async-trait" 165 | version = "0.1.52" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" 168 | dependencies = [ 169 | "proc-macro2", 170 | "quote", 171 | "syn", 172 | ] 173 | 174 | [[package]] 175 | name = "async-tungstenite" 176 | version = "0.16.1" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "5682ea0913e5c20780fe5785abacb85a411e7437bf52a1bedb93ddb3972cb8dd" 179 | dependencies = [ 180 | "async-std", 181 | "futures-io", 182 | "futures-util", 183 | "log", 184 | "pin-project-lite", 185 | "tungstenite", 186 | ] 187 | 188 | [[package]] 189 | name = "atomic-take" 190 | version = "1.0.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "f9f65e4fb35ff6a80b3298d1f028649f3a23da141fa3951e9b24dde1d515b67e" 193 | 194 | [[package]] 195 | name = "atomic-waker" 196 | version = "1.0.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" 199 | 200 | [[package]] 201 | name = "atty" 202 | version = "0.2.14" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 205 | dependencies = [ 206 | "hermit-abi", 207 | "libc", 208 | "winapi", 209 | ] 210 | 211 | [[package]] 212 | name = "autocfg" 213 | version = "1.0.1" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 216 | 217 | [[package]] 218 | name = "base64" 219 | version = "0.13.0" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 222 | 223 | [[package]] 224 | name = "bitflags" 225 | version = "1.3.2" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 228 | 229 | [[package]] 230 | name = "bitpattern" 231 | version = "0.1.0" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "3fc436c543b5fd522e5428d65c88e7bfb538ba267dad95cfb9d8fb8a465b0935" 234 | dependencies = [ 235 | "paste", 236 | "proc-macro2", 237 | "quote", 238 | ] 239 | 240 | [[package]] 241 | name = "block-buffer" 242 | version = "0.9.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 245 | dependencies = [ 246 | "generic-array", 247 | ] 248 | 249 | [[package]] 250 | name = "blocking" 251 | version = "1.1.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" 254 | dependencies = [ 255 | "async-channel", 256 | "async-task", 257 | "atomic-waker", 258 | "fastrand", 259 | "futures-lite", 260 | "once_cell", 261 | ] 262 | 263 | [[package]] 264 | name = "bumpalo" 265 | version = "3.9.1" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" 268 | 269 | [[package]] 270 | name = "byteorder" 271 | version = "1.4.3" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 274 | 275 | [[package]] 276 | name = "bytes" 277 | version = "1.1.0" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 280 | 281 | [[package]] 282 | name = "cache-padded" 283 | version = "1.2.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" 286 | 287 | [[package]] 288 | name = "cc" 289 | version = "1.0.72" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" 292 | 293 | [[package]] 294 | name = "cfg-if" 295 | version = "1.0.0" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 298 | 299 | [[package]] 300 | name = "concurrent-queue" 301 | version = "1.2.2" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" 304 | dependencies = [ 305 | "cache-padded", 306 | ] 307 | 308 | [[package]] 309 | name = "cpufeatures" 310 | version = "0.2.1" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" 313 | dependencies = [ 314 | "libc", 315 | ] 316 | 317 | [[package]] 318 | name = "crossbeam-utils" 319 | version = "0.8.6" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" 322 | dependencies = [ 323 | "cfg-if", 324 | "lazy_static", 325 | ] 326 | 327 | [[package]] 328 | name = "ctor" 329 | version = "0.1.21" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" 332 | dependencies = [ 333 | "quote", 334 | "syn", 335 | ] 336 | 337 | [[package]] 338 | name = "digest" 339 | version = "0.9.0" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 342 | dependencies = [ 343 | "generic-array", 344 | ] 345 | 346 | [[package]] 347 | name = "env_logger" 348 | version = "0.7.1" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 351 | dependencies = [ 352 | "atty", 353 | "humantime", 354 | "log", 355 | "regex", 356 | "termcolor", 357 | ] 358 | 359 | [[package]] 360 | name = "event-listener" 361 | version = "2.5.2" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" 364 | 365 | [[package]] 366 | name = "event-listener-primitives" 367 | version = "2.0.1" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "5384093b4255393cc8c42f0fc3dd4f19977ad3b1025f968257854895a993028c" 370 | dependencies = [ 371 | "nohash-hasher", 372 | "parking_lot", 373 | "smallvec", 374 | ] 375 | 376 | [[package]] 377 | name = "fastrand" 378 | version = "1.7.0" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" 381 | dependencies = [ 382 | "instant", 383 | ] 384 | 385 | [[package]] 386 | name = "fnv" 387 | version = "1.0.7" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 390 | 391 | [[package]] 392 | name = "form_urlencoded" 393 | version = "1.0.1" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 396 | dependencies = [ 397 | "matches", 398 | "percent-encoding", 399 | ] 400 | 401 | [[package]] 402 | name = "ftl-protocol" 403 | version = "0.0.6" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "a89a4d7b50237d0f1218514e6cdd136cb26f1af515c13470159e3c3aa5caf5ba" 406 | dependencies = [ 407 | "async-std", 408 | "async-trait", 409 | "hex", 410 | "log", 411 | "rand", 412 | "ring", 413 | ] 414 | 415 | [[package]] 416 | name = "futures" 417 | version = "0.3.19" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" 420 | dependencies = [ 421 | "futures-channel", 422 | "futures-core", 423 | "futures-executor", 424 | "futures-io", 425 | "futures-sink", 426 | "futures-task", 427 | "futures-util", 428 | ] 429 | 430 | [[package]] 431 | name = "futures-channel" 432 | version = "0.3.19" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" 435 | dependencies = [ 436 | "futures-core", 437 | "futures-sink", 438 | ] 439 | 440 | [[package]] 441 | name = "futures-core" 442 | version = "0.3.19" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" 445 | 446 | [[package]] 447 | name = "futures-executor" 448 | version = "0.3.19" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" 451 | dependencies = [ 452 | "futures-core", 453 | "futures-task", 454 | "futures-util", 455 | ] 456 | 457 | [[package]] 458 | name = "futures-io" 459 | version = "0.3.19" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" 462 | 463 | [[package]] 464 | name = "futures-lite" 465 | version = "1.12.0" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 468 | dependencies = [ 469 | "fastrand", 470 | "futures-core", 471 | "futures-io", 472 | "memchr", 473 | "parking", 474 | "pin-project-lite", 475 | "waker-fn", 476 | ] 477 | 478 | [[package]] 479 | name = "futures-macro" 480 | version = "0.3.19" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" 483 | dependencies = [ 484 | "proc-macro2", 485 | "quote", 486 | "syn", 487 | ] 488 | 489 | [[package]] 490 | name = "futures-micro" 491 | version = "0.5.0" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "b460264b3593d68b16a7bc35f7bc226ddfebdf9a1c8db1ed95d5cc6b7168c826" 494 | dependencies = [ 495 | "pin-project-lite", 496 | ] 497 | 498 | [[package]] 499 | name = "futures-sink" 500 | version = "0.3.19" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" 503 | 504 | [[package]] 505 | name = "futures-task" 506 | version = "0.3.19" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" 509 | 510 | [[package]] 511 | name = "futures-util" 512 | version = "0.3.19" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" 515 | dependencies = [ 516 | "futures-channel", 517 | "futures-core", 518 | "futures-io", 519 | "futures-macro", 520 | "futures-sink", 521 | "futures-task", 522 | "memchr", 523 | "pin-project-lite", 524 | "pin-utils", 525 | "slab", 526 | ] 527 | 528 | [[package]] 529 | name = "generic-array" 530 | version = "0.14.5" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" 533 | dependencies = [ 534 | "typenum", 535 | "version_check", 536 | ] 537 | 538 | [[package]] 539 | name = "getrandom" 540 | version = "0.2.4" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" 543 | dependencies = [ 544 | "cfg-if", 545 | "libc", 546 | "wasi", 547 | ] 548 | 549 | [[package]] 550 | name = "gloo-timers" 551 | version = "0.2.2" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e" 554 | dependencies = [ 555 | "futures-channel", 556 | "futures-core", 557 | "js-sys", 558 | "wasm-bindgen", 559 | "web-sys", 560 | ] 561 | 562 | [[package]] 563 | name = "h264-profile-level-id" 564 | version = "0.1.1" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "e12ebc03fc4f14b7ddc94da90cfb28ba3edee2d926798a9eef89f8a27bbdbca5" 567 | dependencies = [ 568 | "bitpattern", 569 | "log", 570 | "once_cell", 571 | "thiserror", 572 | ] 573 | 574 | [[package]] 575 | name = "hash_hasher" 576 | version = "2.0.3" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "74721d007512d0cb3338cd20f0654ac913920061a4c4d0d8708edb3f2a698c0c" 579 | 580 | [[package]] 581 | name = "hermit-abi" 582 | version = "0.1.19" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 585 | dependencies = [ 586 | "libc", 587 | ] 588 | 589 | [[package]] 590 | name = "hex" 591 | version = "0.4.3" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 594 | 595 | [[package]] 596 | name = "http" 597 | version = "0.2.6" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" 600 | dependencies = [ 601 | "bytes", 602 | "fnv", 603 | "itoa", 604 | ] 605 | 606 | [[package]] 607 | name = "httparse" 608 | version = "1.5.1" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" 611 | 612 | [[package]] 613 | name = "humantime" 614 | version = "1.3.0" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" 617 | dependencies = [ 618 | "quick-error", 619 | ] 620 | 621 | [[package]] 622 | name = "hyperspeed" 623 | version = "0.1.0" 624 | dependencies = [ 625 | "async-std", 626 | "async-trait", 627 | "ftl-protocol", 628 | "hyperspeed-broadcast", 629 | "once_cell", 630 | "pretty_env_logger", 631 | ] 632 | 633 | [[package]] 634 | name = "hyperspeed-broadcast" 635 | version = "0.0.11" 636 | dependencies = [ 637 | "async-std", 638 | "async-trait", 639 | "async-tungstenite", 640 | "bytes", 641 | "ftl-protocol", 642 | "futures", 643 | "lazy_static", 644 | "log", 645 | "mediasoup", 646 | "nanoid", 647 | "once_cell", 648 | "rtp", 649 | "serde", 650 | "serde_json", 651 | "webrtc-util", 652 | ] 653 | 654 | [[package]] 655 | name = "idna" 656 | version = "0.2.3" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 659 | dependencies = [ 660 | "matches", 661 | "unicode-bidi", 662 | "unicode-normalization", 663 | ] 664 | 665 | [[package]] 666 | name = "instant" 667 | version = "0.1.12" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 670 | dependencies = [ 671 | "cfg-if", 672 | ] 673 | 674 | [[package]] 675 | name = "ipnet" 676 | version = "2.3.1" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" 679 | 680 | [[package]] 681 | name = "itoa" 682 | version = "1.0.1" 683 | source = "registry+https://github.com/rust-lang/crates.io-index" 684 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" 685 | 686 | [[package]] 687 | name = "js-sys" 688 | version = "0.3.56" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" 691 | dependencies = [ 692 | "wasm-bindgen", 693 | ] 694 | 695 | [[package]] 696 | name = "kv-log-macro" 697 | version = "1.0.7" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" 700 | dependencies = [ 701 | "log", 702 | ] 703 | 704 | [[package]] 705 | name = "lazy_static" 706 | version = "1.4.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 709 | 710 | [[package]] 711 | name = "libc" 712 | version = "0.2.115" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "0a8d982fa7a96a000f6ec4cfe966de9703eccde29750df2bb8949da91b0e818d" 715 | 716 | [[package]] 717 | name = "lock_api" 718 | version = "0.4.5" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" 721 | dependencies = [ 722 | "scopeguard", 723 | "serde", 724 | ] 725 | 726 | [[package]] 727 | name = "log" 728 | version = "0.4.14" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 731 | dependencies = [ 732 | "cfg-if", 733 | "value-bag", 734 | ] 735 | 736 | [[package]] 737 | name = "lru" 738 | version = "0.7.2" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "274353858935c992b13c0ca408752e2121da852d07dec7ce5f108c77dfa14d1f" 741 | 742 | [[package]] 743 | name = "matches" 744 | version = "0.1.9" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 747 | 748 | [[package]] 749 | name = "mediasoup" 750 | version = "0.9.2" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "517582a7a65fefeb305b9a9b9dc711a5f91a28bc0d2f4a52d8bca935a4a7b4aa" 753 | dependencies = [ 754 | "async-channel", 755 | "async-executor", 756 | "async-lock", 757 | "async-oneshot", 758 | "async-trait", 759 | "atomic-take", 760 | "event-listener-primitives", 761 | "fastrand", 762 | "futures-lite", 763 | "h264-profile-level-id", 764 | "hash_hasher", 765 | "log", 766 | "lru", 767 | "mediasoup-sys", 768 | "nohash-hasher", 769 | "once_cell", 770 | "parking_lot", 771 | "regex", 772 | "serde", 773 | "serde_json", 774 | "serde_repr", 775 | "thiserror", 776 | "uuid", 777 | ] 778 | 779 | [[package]] 780 | name = "mediasoup-sys" 781 | version = "0.3.2" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "c83eda72bddffb50bd363b3d598a9c4634f7458be4b5ec67c459b38237b6d301" 784 | 785 | [[package]] 786 | name = "memchr" 787 | version = "2.4.1" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 790 | 791 | [[package]] 792 | name = "memoffset" 793 | version = "0.6.5" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 796 | dependencies = [ 797 | "autocfg", 798 | ] 799 | 800 | [[package]] 801 | name = "mio" 802 | version = "0.7.14" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" 805 | dependencies = [ 806 | "libc", 807 | "log", 808 | "miow", 809 | "ntapi", 810 | "winapi", 811 | ] 812 | 813 | [[package]] 814 | name = "miow" 815 | version = "0.3.7" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 818 | dependencies = [ 819 | "winapi", 820 | ] 821 | 822 | [[package]] 823 | name = "nanoid" 824 | version = "0.4.0" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" 827 | dependencies = [ 828 | "rand", 829 | ] 830 | 831 | [[package]] 832 | name = "nix" 833 | version = "0.23.1" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" 836 | dependencies = [ 837 | "bitflags", 838 | "cc", 839 | "cfg-if", 840 | "libc", 841 | "memoffset", 842 | ] 843 | 844 | [[package]] 845 | name = "nohash-hasher" 846 | version = "0.2.0" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" 849 | 850 | [[package]] 851 | name = "ntapi" 852 | version = "0.3.6" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 855 | dependencies = [ 856 | "winapi", 857 | ] 858 | 859 | [[package]] 860 | name = "num_cpus" 861 | version = "1.13.1" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 864 | dependencies = [ 865 | "hermit-abi", 866 | "libc", 867 | ] 868 | 869 | [[package]] 870 | name = "once_cell" 871 | version = "1.9.0" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" 874 | 875 | [[package]] 876 | name = "opaque-debug" 877 | version = "0.3.0" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 880 | 881 | [[package]] 882 | name = "parking" 883 | version = "2.0.0" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 886 | 887 | [[package]] 888 | name = "parking_lot" 889 | version = "0.11.2" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 892 | dependencies = [ 893 | "instant", 894 | "lock_api", 895 | "parking_lot_core", 896 | ] 897 | 898 | [[package]] 899 | name = "parking_lot_core" 900 | version = "0.8.5" 901 | source = "registry+https://github.com/rust-lang/crates.io-index" 902 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 903 | dependencies = [ 904 | "cfg-if", 905 | "instant", 906 | "libc", 907 | "redox_syscall", 908 | "smallvec", 909 | "winapi", 910 | ] 911 | 912 | [[package]] 913 | name = "paste" 914 | version = "0.1.18" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" 917 | dependencies = [ 918 | "paste-impl", 919 | "proc-macro-hack", 920 | ] 921 | 922 | [[package]] 923 | name = "paste-impl" 924 | version = "0.1.18" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" 927 | dependencies = [ 928 | "proc-macro-hack", 929 | ] 930 | 931 | [[package]] 932 | name = "percent-encoding" 933 | version = "2.1.0" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 936 | 937 | [[package]] 938 | name = "pin-project-lite" 939 | version = "0.2.8" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" 942 | 943 | [[package]] 944 | name = "pin-utils" 945 | version = "0.1.0" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 948 | 949 | [[package]] 950 | name = "polling" 951 | version = "2.2.0" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" 954 | dependencies = [ 955 | "cfg-if", 956 | "libc", 957 | "log", 958 | "wepoll-ffi", 959 | "winapi", 960 | ] 961 | 962 | [[package]] 963 | name = "ppv-lite86" 964 | version = "0.2.16" 965 | source = "registry+https://github.com/rust-lang/crates.io-index" 966 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 967 | 968 | [[package]] 969 | name = "pretty_env_logger" 970 | version = "0.4.0" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" 973 | dependencies = [ 974 | "env_logger", 975 | "log", 976 | ] 977 | 978 | [[package]] 979 | name = "proc-macro-hack" 980 | version = "0.5.19" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 983 | 984 | [[package]] 985 | name = "proc-macro2" 986 | version = "1.0.36" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 989 | dependencies = [ 990 | "unicode-xid", 991 | ] 992 | 993 | [[package]] 994 | name = "quick-error" 995 | version = "1.2.3" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 998 | 999 | [[package]] 1000 | name = "quote" 1001 | version = "1.0.15" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" 1004 | dependencies = [ 1005 | "proc-macro2", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "rand" 1010 | version = "0.8.4" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 1013 | dependencies = [ 1014 | "libc", 1015 | "rand_chacha", 1016 | "rand_core", 1017 | "rand_hc", 1018 | ] 1019 | 1020 | [[package]] 1021 | name = "rand_chacha" 1022 | version = "0.3.1" 1023 | source = "registry+https://github.com/rust-lang/crates.io-index" 1024 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1025 | dependencies = [ 1026 | "ppv-lite86", 1027 | "rand_core", 1028 | ] 1029 | 1030 | [[package]] 1031 | name = "rand_core" 1032 | version = "0.6.3" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 1035 | dependencies = [ 1036 | "getrandom", 1037 | ] 1038 | 1039 | [[package]] 1040 | name = "rand_hc" 1041 | version = "0.3.1" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 1044 | dependencies = [ 1045 | "rand_core", 1046 | ] 1047 | 1048 | [[package]] 1049 | name = "redox_syscall" 1050 | version = "0.2.10" 1051 | source = "registry+https://github.com/rust-lang/crates.io-index" 1052 | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" 1053 | dependencies = [ 1054 | "bitflags", 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "regex" 1059 | version = "1.5.4" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 1062 | dependencies = [ 1063 | "aho-corasick", 1064 | "memchr", 1065 | "regex-syntax", 1066 | ] 1067 | 1068 | [[package]] 1069 | name = "regex-syntax" 1070 | version = "0.6.25" 1071 | source = "registry+https://github.com/rust-lang/crates.io-index" 1072 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 1073 | 1074 | [[package]] 1075 | name = "ring" 1076 | version = "0.16.20" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 1079 | dependencies = [ 1080 | "cc", 1081 | "libc", 1082 | "once_cell", 1083 | "spin", 1084 | "untrusted", 1085 | "web-sys", 1086 | "winapi", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "rtp" 1091 | version = "0.6.5" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "5110c12c9f7d1e76eba80076cce4ccb82ee085bd10a62472468de0663240f8b5" 1094 | dependencies = [ 1095 | "async-trait", 1096 | "bytes", 1097 | "rand", 1098 | "thiserror", 1099 | "webrtc-util", 1100 | ] 1101 | 1102 | [[package]] 1103 | name = "ryu" 1104 | version = "1.0.9" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" 1107 | 1108 | [[package]] 1109 | name = "scopeguard" 1110 | version = "1.1.0" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1113 | 1114 | [[package]] 1115 | name = "serde" 1116 | version = "1.0.136" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" 1119 | dependencies = [ 1120 | "serde_derive", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "serde_derive" 1125 | version = "1.0.136" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" 1128 | dependencies = [ 1129 | "proc-macro2", 1130 | "quote", 1131 | "syn", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "serde_json" 1136 | version = "1.0.78" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" 1139 | dependencies = [ 1140 | "itoa", 1141 | "ryu", 1142 | "serde", 1143 | ] 1144 | 1145 | [[package]] 1146 | name = "serde_repr" 1147 | version = "0.1.7" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" 1150 | dependencies = [ 1151 | "proc-macro2", 1152 | "quote", 1153 | "syn", 1154 | ] 1155 | 1156 | [[package]] 1157 | name = "sha-1" 1158 | version = "0.9.8" 1159 | source = "registry+https://github.com/rust-lang/crates.io-index" 1160 | checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" 1161 | dependencies = [ 1162 | "block-buffer", 1163 | "cfg-if", 1164 | "cpufeatures", 1165 | "digest", 1166 | "opaque-debug", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "signal-hook" 1171 | version = "0.3.13" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" 1174 | dependencies = [ 1175 | "libc", 1176 | "signal-hook-registry", 1177 | ] 1178 | 1179 | [[package]] 1180 | name = "signal-hook-registry" 1181 | version = "1.4.0" 1182 | source = "registry+https://github.com/rust-lang/crates.io-index" 1183 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1184 | dependencies = [ 1185 | "libc", 1186 | ] 1187 | 1188 | [[package]] 1189 | name = "slab" 1190 | version = "0.4.5" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 1193 | 1194 | [[package]] 1195 | name = "smallvec" 1196 | version = "1.8.0" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" 1199 | 1200 | [[package]] 1201 | name = "socket2" 1202 | version = "0.4.4" 1203 | source = "registry+https://github.com/rust-lang/crates.io-index" 1204 | checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" 1205 | dependencies = [ 1206 | "libc", 1207 | "winapi", 1208 | ] 1209 | 1210 | [[package]] 1211 | name = "spin" 1212 | version = "0.5.2" 1213 | source = "registry+https://github.com/rust-lang/crates.io-index" 1214 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1215 | 1216 | [[package]] 1217 | name = "syn" 1218 | version = "1.0.86" 1219 | source = "registry+https://github.com/rust-lang/crates.io-index" 1220 | checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" 1221 | dependencies = [ 1222 | "proc-macro2", 1223 | "quote", 1224 | "unicode-xid", 1225 | ] 1226 | 1227 | [[package]] 1228 | name = "termcolor" 1229 | version = "1.1.2" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 1232 | dependencies = [ 1233 | "winapi-util", 1234 | ] 1235 | 1236 | [[package]] 1237 | name = "thiserror" 1238 | version = "1.0.30" 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" 1240 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 1241 | dependencies = [ 1242 | "thiserror-impl", 1243 | ] 1244 | 1245 | [[package]] 1246 | name = "thiserror-impl" 1247 | version = "1.0.30" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 1250 | dependencies = [ 1251 | "proc-macro2", 1252 | "quote", 1253 | "syn", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "tinyvec" 1258 | version = "1.5.1" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" 1261 | dependencies = [ 1262 | "tinyvec_macros", 1263 | ] 1264 | 1265 | [[package]] 1266 | name = "tinyvec_macros" 1267 | version = "0.1.0" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1270 | 1271 | [[package]] 1272 | name = "tokio" 1273 | version = "1.15.0" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" 1276 | dependencies = [ 1277 | "bytes", 1278 | "libc", 1279 | "memchr", 1280 | "mio", 1281 | "num_cpus", 1282 | "once_cell", 1283 | "parking_lot", 1284 | "pin-project-lite", 1285 | "signal-hook-registry", 1286 | "tokio-macros", 1287 | "winapi", 1288 | ] 1289 | 1290 | [[package]] 1291 | name = "tokio-macros" 1292 | version = "1.7.0" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" 1295 | dependencies = [ 1296 | "proc-macro2", 1297 | "quote", 1298 | "syn", 1299 | ] 1300 | 1301 | [[package]] 1302 | name = "tungstenite" 1303 | version = "0.16.0" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" 1306 | dependencies = [ 1307 | "base64", 1308 | "byteorder", 1309 | "bytes", 1310 | "http", 1311 | "httparse", 1312 | "log", 1313 | "rand", 1314 | "sha-1", 1315 | "thiserror", 1316 | "url", 1317 | "utf-8", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "typenum" 1322 | version = "1.15.0" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 1325 | 1326 | [[package]] 1327 | name = "unicode-bidi" 1328 | version = "0.3.7" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" 1331 | 1332 | [[package]] 1333 | name = "unicode-normalization" 1334 | version = "0.1.19" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 1337 | dependencies = [ 1338 | "tinyvec", 1339 | ] 1340 | 1341 | [[package]] 1342 | name = "unicode-xid" 1343 | version = "0.2.2" 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" 1345 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 1346 | 1347 | [[package]] 1348 | name = "untrusted" 1349 | version = "0.7.1" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 1352 | 1353 | [[package]] 1354 | name = "url" 1355 | version = "2.2.2" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 1358 | dependencies = [ 1359 | "form_urlencoded", 1360 | "idna", 1361 | "matches", 1362 | "percent-encoding", 1363 | ] 1364 | 1365 | [[package]] 1366 | name = "utf-8" 1367 | version = "0.7.6" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 1370 | 1371 | [[package]] 1372 | name = "uuid" 1373 | version = "0.8.2" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 1376 | dependencies = [ 1377 | "getrandom", 1378 | "serde", 1379 | ] 1380 | 1381 | [[package]] 1382 | name = "value-bag" 1383 | version = "1.0.0-alpha.8" 1384 | source = "registry+https://github.com/rust-lang/crates.io-index" 1385 | checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" 1386 | dependencies = [ 1387 | "ctor", 1388 | "version_check", 1389 | ] 1390 | 1391 | [[package]] 1392 | name = "version_check" 1393 | version = "0.9.4" 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" 1395 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1396 | 1397 | [[package]] 1398 | name = "waker-fn" 1399 | version = "1.1.0" 1400 | source = "registry+https://github.com/rust-lang/crates.io-index" 1401 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 1402 | 1403 | [[package]] 1404 | name = "wasi" 1405 | version = "0.10.2+wasi-snapshot-preview1" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 1408 | 1409 | [[package]] 1410 | name = "wasm-bindgen" 1411 | version = "0.2.79" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" 1414 | dependencies = [ 1415 | "cfg-if", 1416 | "wasm-bindgen-macro", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "wasm-bindgen-backend" 1421 | version = "0.2.79" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" 1424 | dependencies = [ 1425 | "bumpalo", 1426 | "lazy_static", 1427 | "log", 1428 | "proc-macro2", 1429 | "quote", 1430 | "syn", 1431 | "wasm-bindgen-shared", 1432 | ] 1433 | 1434 | [[package]] 1435 | name = "wasm-bindgen-futures" 1436 | version = "0.4.29" 1437 | source = "registry+https://github.com/rust-lang/crates.io-index" 1438 | checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" 1439 | dependencies = [ 1440 | "cfg-if", 1441 | "js-sys", 1442 | "wasm-bindgen", 1443 | "web-sys", 1444 | ] 1445 | 1446 | [[package]] 1447 | name = "wasm-bindgen-macro" 1448 | version = "0.2.79" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" 1451 | dependencies = [ 1452 | "quote", 1453 | "wasm-bindgen-macro-support", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "wasm-bindgen-macro-support" 1458 | version = "0.2.79" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" 1461 | dependencies = [ 1462 | "proc-macro2", 1463 | "quote", 1464 | "syn", 1465 | "wasm-bindgen-backend", 1466 | "wasm-bindgen-shared", 1467 | ] 1468 | 1469 | [[package]] 1470 | name = "wasm-bindgen-shared" 1471 | version = "0.2.79" 1472 | source = "registry+https://github.com/rust-lang/crates.io-index" 1473 | checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" 1474 | 1475 | [[package]] 1476 | name = "web-sys" 1477 | version = "0.3.56" 1478 | source = "registry+https://github.com/rust-lang/crates.io-index" 1479 | checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" 1480 | dependencies = [ 1481 | "js-sys", 1482 | "wasm-bindgen", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "webrtc-util" 1487 | version = "0.5.3" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "60b69bdea720881eddee50bd969be052ed95f04ccc5a6f684495131afb87e31c" 1490 | dependencies = [ 1491 | "async-trait", 1492 | "bitflags", 1493 | "bytes", 1494 | "cc", 1495 | "ipnet", 1496 | "lazy_static", 1497 | "libc", 1498 | "log", 1499 | "nix", 1500 | "parking_lot", 1501 | "rand", 1502 | "thiserror", 1503 | "tokio", 1504 | "winapi", 1505 | ] 1506 | 1507 | [[package]] 1508 | name = "wepoll-ffi" 1509 | version = "0.1.2" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" 1512 | dependencies = [ 1513 | "cc", 1514 | ] 1515 | 1516 | [[package]] 1517 | name = "winapi" 1518 | version = "0.3.9" 1519 | source = "registry+https://github.com/rust-lang/crates.io-index" 1520 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1521 | dependencies = [ 1522 | "winapi-i686-pc-windows-gnu", 1523 | "winapi-x86_64-pc-windows-gnu", 1524 | ] 1525 | 1526 | [[package]] 1527 | name = "winapi-i686-pc-windows-gnu" 1528 | version = "0.4.0" 1529 | source = "registry+https://github.com/rust-lang/crates.io-index" 1530 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1531 | 1532 | [[package]] 1533 | name = "winapi-util" 1534 | version = "0.1.5" 1535 | source = "registry+https://github.com/rust-lang/crates.io-index" 1536 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1537 | dependencies = [ 1538 | "winapi", 1539 | ] 1540 | 1541 | [[package]] 1542 | name = "winapi-x86_64-pc-windows-gnu" 1543 | version = "0.4.0" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1546 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hyperspeed" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | hyperspeed-broadcast = { path = "crates/broadcast" } 10 | ftl-protocol = { version = "0.0.6", features = ["server"] } 11 | # ftl-protocol = { path = "crates/ftl", features = ["server"] } 12 | 13 | once_cell = "1.8.0" 14 | async-trait = "0.1.50" 15 | pretty_env_logger = "0.4" 16 | async-std = { version = "1.8.0", features = ["attributes"] } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Logo 4 | 5 |

6 | 7 | ## [Documentation](https://hyperspeed.cli.rs) 8 | 9 | ## [FTL Protocol](https://hyperspeed.cli.rs/ftl) 10 | -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/insertish/project-hyperspeed/df2b113701939f47046f533ceaf4a57fb68d7b7d/assets/banner.png -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/insertish/project-hyperspeed/df2b113701939f47046f533ceaf4a57fb68d7b7d/assets/logo.png -------------------------------------------------------------------------------- /crates/broadcast/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hyperspeed-broadcast" 3 | description = "FTL media ingest server and WebSocket signaling server." 4 | homepage = "https://hyperspeed.cli.rs" 5 | documentation = "https://hyperspeed.cli.rs/components/broadcast" 6 | repository = "https://github.com/insertish/project-hyperspeed" 7 | version = "0.0.11" 8 | license = "AGPL-3.0" 9 | edition = "2018" 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [features] 14 | rtc = [ "once_cell", "mediasoup" ] 15 | ingest = [ "rtc", "async-trait", "async-std", "rtp", "webrtc-util", "bytes", "lazy_static", "nanoid" ] 16 | signaling = [ "rtc", "futures", "async-std", "async-trait", "async-tungstenite", "serde", "serde_json" ] 17 | default = [ "rtc", "ingest", "signaling" ] 18 | 19 | [dependencies] 20 | # ftl-protocol = { path = "../ftl" } 21 | ftl-protocol = "0.0.6" 22 | 23 | # misc 24 | log = "0.4" 25 | bytes = { version = "1.1.0", optional = true } 26 | nanoid = { version = "0.4.0", optional = true } 27 | futures = { version = "0.3.15", optional = true } 28 | once_cell = { version = "1.8.0", optional = true } 29 | lazy_static = { version = "1.4.0", optional = true } 30 | 31 | # async std 32 | async-trait = { version = "0.1.50", optional = true } 33 | async-std = { version = "1.8.0", features = ["attributes", "unstable"], optional = true } 34 | async-tungstenite = { version = "0.16.1", features = ["async-std-runtime"], optional = true } 35 | 36 | # serde 37 | serde_json = { version = "1.0.64", optional = true } 38 | serde = { version = "1.0.126", features = ["derive"], optional = true } 39 | 40 | # WebRTC 41 | rtp = { version = "0.6.5", optional = true } 42 | mediasoup = { version = "0.9.2", optional = true } 43 | webrtc-util = { version = "0.5.3", optional = true } 44 | 45 | [package.metadata.docs.rs] 46 | all-features = true 47 | rustc-args = ["--cfg", "docsrs"] 48 | rustdoc-args = ["--cfg", "docsrs"] 49 | -------------------------------------------------------------------------------- /crates/broadcast/README.md: -------------------------------------------------------------------------------- 1 | # Broadcast 2 | 3 | [hyperspeed-broadcast](https://gitlab.insrt.uk/insert/project-hyperspeed/-/tree/master/crates/broadcast) is a media ingest server (currently only supports FTL media ingest, forwarding RTP packets to WebRTC clients), it also provides a signaling WebSocket server for establishing new client connections. 4 | 5 | ## [Documentation](https://hyperspeed.cli.rs/components/broadcast) 6 | -------------------------------------------------------------------------------- /crates/broadcast/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, feature(doc_cfg))] 2 | 3 | #[cfg(feature = "ingest")] 4 | #[cfg_attr(docsrs, doc(cfg(feature = "ingest")))] 5 | #[macro_use] 6 | extern crate lazy_static; 7 | 8 | #[cfg(feature = "rtc")] 9 | #[cfg_attr(docsrs, doc(cfg(feature = "rtc")))] 10 | pub mod rtc; 11 | 12 | #[cfg(feature = "signaling")] 13 | #[cfg_attr(docsrs, doc(cfg(feature = "signaling")))] 14 | pub mod signaling; 15 | -------------------------------------------------------------------------------- /crates/broadcast/src/rtc/codecs.rs: -------------------------------------------------------------------------------- 1 | use std::num::{NonZeroU32, NonZeroU8}; 2 | 3 | use mediasoup::router::RouterOptions; 4 | use mediasoup::rtp_parameters::{MimeTypeAudio, MimeTypeVideo, RtcpFeedback, RtpCodecCapability, RtpCodecParametersParameters}; 5 | 6 | use super::routers::DataSource; 7 | 8 | pub struct VideoCodec { 9 | pub mime_type: MimeTypeVideo, 10 | pub clock_rate: u32, 11 | pub parameters: RtpCodecParametersParameters, 12 | pub rtcp_feedback: Vec 13 | } 14 | 15 | impl VideoCodec { 16 | pub fn from(codec: &str) -> VideoCodec { 17 | let mime_type = match codec { 18 | "H264" => MimeTypeVideo::H264, 19 | _ => unimplemented!() 20 | }; 21 | 22 | let mut parameters = match mime_type { 23 | MimeTypeVideo::H264 => RtpCodecParametersParameters::from([ 24 | ("packetization-mode", 1_u32.into()), 25 | ("level-asymmetry-allowed", 1_u32.into()) 26 | ]), 27 | _ => unreachable!() 28 | }; 29 | 30 | parameters.insert("profile-level-id", "42e01f"); 31 | 32 | let clock_rate = match mime_type { 33 | MimeTypeVideo::H264 => 90_000, 34 | _ => unreachable!() 35 | }; 36 | 37 | let rtcp_feedback = match mime_type { 38 | MimeTypeVideo::H264 => vec! [ 39 | RtcpFeedback::Nack, 40 | RtcpFeedback::NackPli, 41 | RtcpFeedback::CcmFir, 42 | RtcpFeedback::GoogRemb, 43 | RtcpFeedback::TransportCc, 44 | ], 45 | _ => unreachable!() 46 | }; 47 | 48 | VideoCodec { 49 | mime_type, 50 | clock_rate, 51 | parameters, 52 | rtcp_feedback 53 | } 54 | } 55 | } 56 | 57 | pub struct AudioCodec { 58 | pub mime_type: MimeTypeAudio, 59 | pub clock_rate: u32, 60 | pub parameters: RtpCodecParametersParameters, 61 | pub rtcp_feedback: Vec 62 | } 63 | 64 | impl AudioCodec { 65 | pub fn from(codec: &str) -> AudioCodec { 66 | let mime_type = match codec { 67 | "OPUS" => MimeTypeAudio::Opus, 68 | _ => unimplemented!() 69 | }; 70 | 71 | let parameters = RtpCodecParametersParameters::default(); 72 | let rtcp_feedback = Vec::new(); 73 | 74 | let clock_rate = match mime_type { 75 | MimeTypeAudio::Opus => 48_000, 76 | _ => unreachable!() 77 | }; 78 | 79 | AudioCodec { 80 | mime_type, 81 | clock_rate, 82 | parameters, 83 | rtcp_feedback 84 | } 85 | } 86 | } 87 | 88 | pub fn init_codecs(options: &mut RouterOptions, source: &DataSource) { 89 | match source { 90 | DataSource::Ftl(handshake) => { 91 | if let Some(video) = &handshake.video { 92 | let VideoCodec { mime_type, clock_rate, parameters, rtcp_feedback } 93 | = VideoCodec::from(&video.codec); 94 | 95 | options.media_codecs.push( 96 | RtpCodecCapability::Video { 97 | mime_type, 98 | preferred_payload_type: None, 99 | clock_rate: NonZeroU32::new(clock_rate).unwrap(), 100 | parameters, 101 | rtcp_feedback 102 | } 103 | ); 104 | } 105 | 106 | if let Some(audio) = &handshake.audio { 107 | let AudioCodec { mime_type, clock_rate, parameters, rtcp_feedback } 108 | = AudioCodec::from(&audio.codec); 109 | 110 | options.media_codecs.push( 111 | RtpCodecCapability::Audio { 112 | mime_type, 113 | preferred_payload_type: None, 114 | clock_rate: NonZeroU32::new(clock_rate).unwrap(), 115 | channels: NonZeroU8::new(2).unwrap(), 116 | parameters, 117 | rtcp_feedback 118 | } 119 | ); 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /crates/broadcast/src/rtc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod producers; 2 | pub mod routers; 3 | pub mod workers; 4 | pub mod codecs; 5 | -------------------------------------------------------------------------------- /crates/broadcast/src/rtc/producers.rs: -------------------------------------------------------------------------------- 1 | use std::num::{NonZeroU32, NonZeroU8}; 2 | use std::net::SocketAddr; 3 | 4 | use mediasoup::plain_transport::PlainTransportOptions; 5 | use mediasoup::prelude::TransportListenIp; 6 | use mediasoup::producer::{Producer, ProducerOptions}; 7 | use mediasoup::router::Router; 8 | use mediasoup::transport::Transport; 9 | use mediasoup::rtp_parameters::{MediaKind, RtpCodecParameters, RtpEncodingParameters, RtpParameters}; 10 | 11 | use crate::rtc::codecs::{AudioCodec, VideoCodec}; 12 | 13 | use super::routers::DataSource; 14 | 15 | pub async fn init_producers(router: &Router, source: &DataSource, addr: SocketAddr) -> Vec { 16 | let mut producers = Vec::new(); 17 | 18 | match source { 19 | DataSource::Ftl(handshake) => { 20 | // Prepare transport options 21 | let listen_ip = TransportListenIp { 22 | ip: addr.ip(), 23 | announced_ip: None, 24 | }; 25 | let mut transport_options = PlainTransportOptions::new(listen_ip); 26 | transport_options.port = Some(addr.port()); 27 | transport_options.rtcp_mux = true; 28 | transport_options.comedia = true; 29 | 30 | // Create plain transport 31 | let plain_transport = router 32 | .create_plain_transport(transport_options) 33 | .await.unwrap(); 34 | 35 | // Initialise video producer 36 | if let Some(video) = &handshake.video { 37 | let VideoCodec { mime_type, clock_rate, parameters, rtcp_feedback } 38 | = VideoCodec::from(&video.codec); 39 | 40 | let mut video_rtp_params = RtpParameters::default(); 41 | video_rtp_params.codecs = vec![ 42 | RtpCodecParameters::Video { 43 | mime_type, 44 | payload_type: video.payload_type, 45 | clock_rate: NonZeroU32::new(clock_rate).unwrap(), 46 | parameters, 47 | rtcp_feedback 48 | } 49 | ]; 50 | 51 | video_rtp_params.encodings = vec![ 52 | RtpEncodingParameters { 53 | ssrc: Some(video.ssrc), 54 | ..RtpEncodingParameters::default() 55 | } 56 | ]; 57 | 58 | producers.push( 59 | plain_transport.produce( 60 | ProducerOptions::new(MediaKind::Video, video_rtp_params) 61 | ).await.unwrap() 62 | ); 63 | } 64 | 65 | // Initialise audio producer 66 | if let Some(audio) = &handshake.audio { 67 | let AudioCodec { mime_type, clock_rate, parameters, rtcp_feedback } 68 | = AudioCodec::from(&audio.codec); 69 | 70 | let mut audio_rtp_params = RtpParameters::default(); 71 | audio_rtp_params.codecs = vec![ 72 | RtpCodecParameters::Audio { 73 | mime_type, 74 | payload_type: audio.payload_type, 75 | clock_rate: NonZeroU32::new(clock_rate).unwrap(), 76 | channels: NonZeroU8::new(2).unwrap(), 77 | parameters, 78 | rtcp_feedback, 79 | } 80 | ]; 81 | 82 | audio_rtp_params.encodings = vec![ 83 | RtpEncodingParameters { 84 | ssrc: Some(audio.ssrc), 85 | ..RtpEncodingParameters::default() 86 | } 87 | ]; 88 | 89 | producers.push( 90 | plain_transport.produce( 91 | ProducerOptions::new(MediaKind::Audio, audio_rtp_params) 92 | ).await.unwrap() 93 | ); 94 | } 95 | } 96 | } 97 | 98 | return producers; 99 | } 100 | -------------------------------------------------------------------------------- /crates/broadcast/src/rtc/routers.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | 3 | use mediasoup::router::{Router, RouterOptions}; 4 | use mediasoup::producer::{Producer, ProducerId}; 5 | use ftl_protocol::protocol::FtlHandshakeFinalised; 6 | 7 | use super::{codecs::init_codecs, workers::WorkerPool, producers::init_producers}; 8 | 9 | #[derive(Clone)] 10 | pub enum DataSource { 11 | Ftl(FtlHandshakeFinalised) 12 | } 13 | 14 | #[derive(Clone)] 15 | pub struct HyperspeedRouter { 16 | pub router: Router, 17 | pub channel_id: String, 18 | pub producers: Vec, 19 | pub source: DataSource 20 | } 21 | 22 | impl HyperspeedRouter { 23 | pub async fn new(channel_id: String, source: DataSource, addr: SocketAddr) -> HyperspeedRouter { 24 | let mut options = RouterOptions::default(); 25 | init_codecs(&mut options, &source); 26 | 27 | let router = WorkerPool::get() 28 | .get_worker() 29 | .create_router(options) 30 | .await 31 | .unwrap(); 32 | 33 | let producers = init_producers(&router, &source, addr).await; 34 | 35 | HyperspeedRouter { 36 | router, 37 | channel_id, 38 | producers, 39 | source 40 | } 41 | } 42 | 43 | pub fn clone_router(&self) -> Router { 44 | self.router.clone() 45 | } 46 | 47 | pub fn get_producer_ids(&self) -> Vec { 48 | self.producers.iter() 49 | .map(|v| v.id().clone()) 50 | .collect() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crates/broadcast/src/rtc/workers.rs: -------------------------------------------------------------------------------- 1 | use mediasoup::{worker::Worker, worker::WorkerSettings, worker_manager::WorkerManager}; 2 | use once_cell::sync::OnceCell; 3 | use log::debug; 4 | 5 | static WORKER_POOL: OnceCell = OnceCell::new(); 6 | 7 | // ! Worker pool taken from Vortex source code. 8 | // ! This is single-threaded, which is enough for now. 9 | 10 | #[derive(Debug)] 11 | pub struct WorkerPool { 12 | _manager: WorkerManager, 13 | worker: Worker, 14 | } 15 | 16 | impl WorkerPool { 17 | pub async fn init() { 18 | let worker_pool = WorkerPool::new().await; 19 | WORKER_POOL.set(worker_pool).unwrap(); 20 | } 21 | 22 | pub fn get() -> &'static WorkerPool { 23 | WORKER_POOL 24 | .get() 25 | .expect("Mediasoup worker pool not initialized") 26 | } 27 | 28 | pub async fn new() -> Self { 29 | let manager = WorkerManager::new(); 30 | let mut settings = WorkerSettings::default(); 31 | // ! FIXME: hardcoded value 32 | settings.rtc_ports_range = 10100..=10200; 33 | 34 | let worker = manager.create_worker(settings).await.unwrap(); 35 | debug!("Initialized worker pool"); 36 | WorkerPool { 37 | _manager: manager, 38 | worker, 39 | } 40 | } 41 | 42 | pub fn get_worker(&self) -> &Worker { 43 | &self.worker 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /crates/broadcast/src/signaling/messages.rs: -------------------------------------------------------------------------------- 1 | use mediasoup::rtp_parameters::{MediaKind, RtpCapabilities, RtpCapabilitiesFinalized, RtpParameters}; 2 | use mediasoup::data_structures::{DtlsParameters, IceCandidate, IceParameters}; 3 | use mediasoup::transport::TransportId; 4 | use mediasoup::consumer::ConsumerId; 5 | use mediasoup::producer::ProducerId; 6 | 7 | use serde::{Serialize, Deserialize}; 8 | 9 | #[derive(Serialize, Deserialize)] 10 | #[serde(rename_all = "camelCase")] 11 | pub struct TransportOptions { 12 | pub id: TransportId, 13 | pub dtls_parameters: DtlsParameters, 14 | pub ice_candidates: Vec, 15 | pub ice_parameters: IceParameters, 16 | } 17 | 18 | #[derive(Serialize, Deserialize)] 19 | #[serde(tag = "type")] 20 | pub enum ServerboundMessage { 21 | Begin { 22 | channel_id: String 23 | }, 24 | Init { 25 | rtp_capabilities: RtpCapabilities 26 | }, 27 | Connect { 28 | dtls_parameters: DtlsParameters 29 | }, 30 | Consume, 31 | Resume { 32 | id: ConsumerId 33 | }, 34 | PollConnectedViewers, 35 | } 36 | 37 | #[derive(Serialize, Deserialize)] 38 | #[serde(rename_all = "camelCase")] 39 | pub struct Consume { 40 | pub id: ConsumerId, 41 | pub producer_id: ProducerId, 42 | pub kind: MediaKind, 43 | pub rtp_parameters: RtpParameters 44 | } 45 | 46 | #[derive(Serialize, Deserialize)] 47 | #[serde(tag = "type")] 48 | pub enum ClientboundMessage { 49 | Init { 50 | producers: Vec, 51 | transport: TransportOptions, 52 | router_rtp_capabilities: RtpCapabilitiesFinalized 53 | }, 54 | Connected, 55 | #[serde(rename_all = "camelCase")] 56 | Consuming { 57 | consume: Vec 58 | }, 59 | ViewerCount { 60 | count: usize 61 | }, 62 | } 63 | -------------------------------------------------------------------------------- /crates/broadcast/src/signaling/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod websocket; 2 | pub mod messages; 3 | -------------------------------------------------------------------------------- /crates/broadcast/src/signaling/websocket.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | 3 | use async_tungstenite::tungstenite::Message; 4 | use futures::{StreamExt, TryStreamExt, SinkExt}; 5 | use async_std::{net::TcpListener, sync::RwLock}; 6 | use mediasoup::{consumer::ConsumerOptions, data_structures::TransportListenIp, producer::ProducerId, router::Router, webrtc_transport::{TransportListenIps, WebRtcTransportOptions, WebRtcTransportRemoteParameters}}; 7 | use mediasoup::transport::Transport; 8 | use async_trait::async_trait; 9 | use async_std::task; 10 | use log::info; 11 | 12 | use crate::signaling::messages::{ClientboundMessage, Consume, ServerboundMessage, TransportOptions}; 13 | 14 | pub struct StreamInformation { 15 | pub router: Router, 16 | pub producers: Vec 17 | } 18 | 19 | lazy_static! { 20 | static ref VIEWERS: RwLock>> = RwLock::new(HashMap::new()); 21 | } 22 | 23 | async fn viewers_start(channel: String, ip: String) { 24 | let mut viewers = VIEWERS.write().await; 25 | if !viewers.contains_key(&channel) { 26 | viewers.insert(channel.clone(), HashSet::new()); 27 | } 28 | 29 | if let Some(set) = viewers.get_mut(&channel) { 30 | set.insert(ip); 31 | } 32 | } 33 | 34 | async fn viewers_stop(channel: String, ip: String) { 35 | let mut viewers = VIEWERS.write().await; 36 | if let Some(set) = viewers.get_mut(&channel) { 37 | set.remove(&ip); 38 | } 39 | } 40 | 41 | async fn viewers_count(channel: String) -> usize { 42 | VIEWERS.read().await.get(&channel).map(|x| x.len()).unwrap_or_else(|| 0) 43 | } 44 | 45 | #[async_trait] 46 | pub trait SignalingServer { 47 | async fn launch(&'static self, addr: &'static str, announced_ip: &'static str) { 48 | let try_socket = TcpListener::bind(addr).await; 49 | let listener = try_socket.expect("Failed to bind"); 50 | 51 | while let Ok((stream, _)) = listener.accept().await { 52 | task::spawn_local(async move { 53 | let addr = stream.peer_addr().unwrap(); 54 | let id = nanoid::nanoid!(32); 55 | info!("User connected: {addr} (assigned id {id})"); 56 | 57 | let ws = async_tungstenite::accept_async(stream) 58 | .await.unwrap(); 59 | 60 | let (mut write, mut read) = ws.split(); 61 | let mut channel_id = None; 62 | 'outer: while let Ok(message) = read.try_next().await { 63 | if let Message::Text(text) = message.unwrap() { 64 | let msg: ServerboundMessage = serde_json::from_str(&text).unwrap(); 65 | match msg { 66 | ServerboundMessage::Begin { channel_id: cid } => { 67 | channel_id = Some(cid); 68 | break 'outer; 69 | }, 70 | _ => {} 71 | } 72 | } 73 | } 74 | 75 | let channel_id = channel_id.unwrap(); 76 | let stream_info = self.get_stream(channel_id.clone()).await; 77 | 78 | if stream_info.is_none() { 79 | // ! FIXME: throw error; not live here 80 | dbg!("not live"); 81 | return; 82 | } 83 | 84 | let StreamInformation { router, producers } = stream_info.unwrap(); 85 | let transport_options = 86 | WebRtcTransportOptions::new(TransportListenIps::new(TransportListenIp { 87 | ip: "0.0.0.0".parse().unwrap(), 88 | announced_ip: Some(announced_ip.parse().unwrap()), 89 | })); 90 | 91 | let consumer_transport = router 92 | .create_webrtc_transport(transport_options) 93 | .await.unwrap(); 94 | 95 | write.send(Message::Text( 96 | serde_json::to_string(&ClientboundMessage::Init { 97 | transport: TransportOptions { 98 | id: consumer_transport.id(), 99 | dtls_parameters: consumer_transport.dtls_parameters(), 100 | ice_candidates: consumer_transport.ice_candidates().clone(), 101 | ice_parameters: consumer_transport.ice_parameters().clone() 102 | }, 103 | router_rtp_capabilities: router.rtp_capabilities().clone(), 104 | producers: producers.clone() 105 | }) 106 | .unwrap() 107 | )) 108 | .await.unwrap(); 109 | 110 | // Client data 111 | let mut consumers = HashMap::new(); 112 | let mut client_rtp_capabilities = None; 113 | 114 | 'disconnect: while let Ok(Some(message)) = read.try_next().await { 115 | if let Message::Text(text) = message { 116 | if let Ok(msg) = serde_json::from_str(&text) { 117 | match msg { 118 | ServerboundMessage::Begin { .. } => {}, 119 | ServerboundMessage::Init { rtp_capabilities } => { 120 | client_rtp_capabilities = Some(rtp_capabilities); 121 | }, 122 | ServerboundMessage::Connect { dtls_parameters } => { 123 | if consumer_transport 124 | .connect(WebRtcTransportRemoteParameters { dtls_parameters }) 125 | .await 126 | .is_err() { 127 | break 'disconnect; 128 | } 129 | 130 | if write.send(Message::Text( 131 | serde_json::to_string(&ClientboundMessage::Connected) 132 | .unwrap() 133 | )) 134 | .await 135 | .is_err() { 136 | break 'disconnect; 137 | } 138 | 139 | viewers_start(channel_id.clone(), id.clone()).await; 140 | }, 141 | ServerboundMessage::Consume => { 142 | let mut consume = vec![]; 143 | for producer_id in &producers { 144 | let rtp_capabilities = client_rtp_capabilities.as_ref().unwrap(); 145 | let mut options = ConsumerOptions::new(*producer_id, rtp_capabilities.clone()); 146 | options.paused = true; 147 | 148 | let consumer = consumer_transport.consume(options).await.unwrap(); 149 | 150 | let id = consumer.id(); 151 | let kind = consumer.kind(); 152 | let rtp_parameters = consumer.rtp_parameters().clone(); 153 | 154 | consumers.insert(id, consumer); 155 | consume.push(Consume { 156 | id, 157 | producer_id: *producer_id, 158 | kind, 159 | rtp_parameters 160 | }); 161 | } 162 | 163 | write.send(Message::Text( 164 | serde_json::to_string(&ClientboundMessage::Consuming { 165 | consume 166 | }) 167 | .unwrap() 168 | )) 169 | .await.unwrap(); 170 | }, 171 | ServerboundMessage::Resume { id } => { 172 | if let Some(consumer) = consumers.get(&id).cloned() { 173 | consumer.resume().await.unwrap(); 174 | } 175 | }, 176 | ServerboundMessage::PollConnectedViewers => { 177 | write.send(Message::Text( 178 | serde_json::to_string(&ClientboundMessage::ViewerCount { 179 | count: viewers_count(channel_id.clone()).await 180 | }) 181 | .unwrap() 182 | )) 183 | .await.unwrap(); 184 | } 185 | } 186 | } else { 187 | break 'disconnect 188 | } 189 | } 190 | } 191 | 192 | viewers_stop(channel_id.clone(), id.clone()).await; 193 | }); 194 | } 195 | } 196 | 197 | async fn get_stream(&self, channel_id: String) -> Option; 198 | } 199 | -------------------------------------------------------------------------------- /crates/ftl/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "async-attributes" 7 | version = "1.1.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" 10 | dependencies = [ 11 | "quote", 12 | "syn", 13 | ] 14 | 15 | [[package]] 16 | name = "async-channel" 17 | version = "1.6.1" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" 20 | dependencies = [ 21 | "concurrent-queue", 22 | "event-listener", 23 | "futures-core", 24 | ] 25 | 26 | [[package]] 27 | name = "async-executor" 28 | version = "1.4.1" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" 31 | dependencies = [ 32 | "async-task", 33 | "concurrent-queue", 34 | "fastrand", 35 | "futures-lite", 36 | "once_cell", 37 | "slab", 38 | ] 39 | 40 | [[package]] 41 | name = "async-global-executor" 42 | version = "2.0.2" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" 45 | dependencies = [ 46 | "async-channel", 47 | "async-executor", 48 | "async-io", 49 | "async-mutex", 50 | "blocking", 51 | "futures-lite", 52 | "num_cpus", 53 | "once_cell", 54 | ] 55 | 56 | [[package]] 57 | name = "async-io" 58 | version = "1.6.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" 61 | dependencies = [ 62 | "concurrent-queue", 63 | "futures-lite", 64 | "libc", 65 | "log", 66 | "once_cell", 67 | "parking", 68 | "polling", 69 | "slab", 70 | "socket2", 71 | "waker-fn", 72 | "winapi", 73 | ] 74 | 75 | [[package]] 76 | name = "async-lock" 77 | version = "2.4.0" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" 80 | dependencies = [ 81 | "event-listener", 82 | ] 83 | 84 | [[package]] 85 | name = "async-mutex" 86 | version = "1.4.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" 89 | dependencies = [ 90 | "event-listener", 91 | ] 92 | 93 | [[package]] 94 | name = "async-std" 95 | version = "1.9.0" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" 98 | dependencies = [ 99 | "async-attributes", 100 | "async-channel", 101 | "async-global-executor", 102 | "async-io", 103 | "async-lock", 104 | "crossbeam-utils", 105 | "futures-channel", 106 | "futures-core", 107 | "futures-io", 108 | "futures-lite", 109 | "gloo-timers", 110 | "kv-log-macro", 111 | "log", 112 | "memchr", 113 | "num_cpus", 114 | "once_cell", 115 | "pin-project-lite", 116 | "pin-utils", 117 | "slab", 118 | "wasm-bindgen-futures", 119 | ] 120 | 121 | [[package]] 122 | name = "async-task" 123 | version = "4.0.3" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" 126 | 127 | [[package]] 128 | name = "async-trait" 129 | version = "0.1.50" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" 132 | dependencies = [ 133 | "proc-macro2", 134 | "quote", 135 | "syn", 136 | ] 137 | 138 | [[package]] 139 | name = "atomic-waker" 140 | version = "1.0.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" 143 | 144 | [[package]] 145 | name = "blocking" 146 | version = "1.0.2" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" 149 | dependencies = [ 150 | "async-channel", 151 | "async-task", 152 | "atomic-waker", 153 | "fastrand", 154 | "futures-lite", 155 | "once_cell", 156 | ] 157 | 158 | [[package]] 159 | name = "bumpalo" 160 | version = "3.7.0" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" 163 | 164 | [[package]] 165 | name = "cache-padded" 166 | version = "1.1.1" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" 169 | 170 | [[package]] 171 | name = "cc" 172 | version = "1.0.69" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" 175 | 176 | [[package]] 177 | name = "cfg-if" 178 | version = "1.0.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 181 | 182 | [[package]] 183 | name = "concurrent-queue" 184 | version = "1.2.2" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" 187 | dependencies = [ 188 | "cache-padded", 189 | ] 190 | 191 | [[package]] 192 | name = "crossbeam-utils" 193 | version = "0.8.5" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" 196 | dependencies = [ 197 | "cfg-if", 198 | "lazy_static", 199 | ] 200 | 201 | [[package]] 202 | name = "ctor" 203 | version = "0.1.20" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" 206 | dependencies = [ 207 | "quote", 208 | "syn", 209 | ] 210 | 211 | [[package]] 212 | name = "event-listener" 213 | version = "2.5.1" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" 216 | 217 | [[package]] 218 | name = "fastrand" 219 | version = "1.4.1" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" 222 | dependencies = [ 223 | "instant", 224 | ] 225 | 226 | [[package]] 227 | name = "ftl-protocol" 228 | version = "0.0.6" 229 | dependencies = [ 230 | "async-std", 231 | "async-trait", 232 | "hex", 233 | "log", 234 | "rand", 235 | "ring", 236 | ] 237 | 238 | [[package]] 239 | name = "futures-channel" 240 | version = "0.3.15" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" 243 | dependencies = [ 244 | "futures-core", 245 | ] 246 | 247 | [[package]] 248 | name = "futures-core" 249 | version = "0.3.15" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" 252 | 253 | [[package]] 254 | name = "futures-io" 255 | version = "0.3.15" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" 258 | 259 | [[package]] 260 | name = "futures-lite" 261 | version = "1.12.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 264 | dependencies = [ 265 | "fastrand", 266 | "futures-core", 267 | "futures-io", 268 | "memchr", 269 | "parking", 270 | "pin-project-lite", 271 | "waker-fn", 272 | ] 273 | 274 | [[package]] 275 | name = "getrandom" 276 | version = "0.2.3" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 279 | dependencies = [ 280 | "cfg-if", 281 | "libc", 282 | "wasi", 283 | ] 284 | 285 | [[package]] 286 | name = "gloo-timers" 287 | version = "0.2.1" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" 290 | dependencies = [ 291 | "futures-channel", 292 | "futures-core", 293 | "js-sys", 294 | "wasm-bindgen", 295 | "web-sys", 296 | ] 297 | 298 | [[package]] 299 | name = "hermit-abi" 300 | version = "0.1.19" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 303 | dependencies = [ 304 | "libc", 305 | ] 306 | 307 | [[package]] 308 | name = "hex" 309 | version = "0.4.3" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 312 | 313 | [[package]] 314 | name = "instant" 315 | version = "0.1.10" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" 318 | dependencies = [ 319 | "cfg-if", 320 | ] 321 | 322 | [[package]] 323 | name = "js-sys" 324 | version = "0.3.51" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" 327 | dependencies = [ 328 | "wasm-bindgen", 329 | ] 330 | 331 | [[package]] 332 | name = "kv-log-macro" 333 | version = "1.0.7" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" 336 | dependencies = [ 337 | "log", 338 | ] 339 | 340 | [[package]] 341 | name = "lazy_static" 342 | version = "1.4.0" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 345 | 346 | [[package]] 347 | name = "libc" 348 | version = "0.2.98" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" 351 | 352 | [[package]] 353 | name = "log" 354 | version = "0.4.14" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 357 | dependencies = [ 358 | "cfg-if", 359 | "value-bag", 360 | ] 361 | 362 | [[package]] 363 | name = "memchr" 364 | version = "2.4.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" 367 | 368 | [[package]] 369 | name = "num_cpus" 370 | version = "1.13.0" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 373 | dependencies = [ 374 | "hermit-abi", 375 | "libc", 376 | ] 377 | 378 | [[package]] 379 | name = "once_cell" 380 | version = "1.8.0" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 383 | 384 | [[package]] 385 | name = "parking" 386 | version = "2.0.0" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 389 | 390 | [[package]] 391 | name = "pin-project-lite" 392 | version = "0.2.7" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" 395 | 396 | [[package]] 397 | name = "pin-utils" 398 | version = "0.1.0" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 401 | 402 | [[package]] 403 | name = "polling" 404 | version = "2.1.0" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" 407 | dependencies = [ 408 | "cfg-if", 409 | "libc", 410 | "log", 411 | "wepoll-ffi", 412 | "winapi", 413 | ] 414 | 415 | [[package]] 416 | name = "ppv-lite86" 417 | version = "0.2.10" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 420 | 421 | [[package]] 422 | name = "proc-macro2" 423 | version = "1.0.27" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" 426 | dependencies = [ 427 | "unicode-xid", 428 | ] 429 | 430 | [[package]] 431 | name = "quote" 432 | version = "1.0.9" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 435 | dependencies = [ 436 | "proc-macro2", 437 | ] 438 | 439 | [[package]] 440 | name = "rand" 441 | version = "0.8.4" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 444 | dependencies = [ 445 | "libc", 446 | "rand_chacha", 447 | "rand_core", 448 | "rand_hc", 449 | ] 450 | 451 | [[package]] 452 | name = "rand_chacha" 453 | version = "0.3.1" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 456 | dependencies = [ 457 | "ppv-lite86", 458 | "rand_core", 459 | ] 460 | 461 | [[package]] 462 | name = "rand_core" 463 | version = "0.6.3" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 466 | dependencies = [ 467 | "getrandom", 468 | ] 469 | 470 | [[package]] 471 | name = "rand_hc" 472 | version = "0.3.1" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 475 | dependencies = [ 476 | "rand_core", 477 | ] 478 | 479 | [[package]] 480 | name = "ring" 481 | version = "0.16.20" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 484 | dependencies = [ 485 | "cc", 486 | "libc", 487 | "once_cell", 488 | "spin", 489 | "untrusted", 490 | "web-sys", 491 | "winapi", 492 | ] 493 | 494 | [[package]] 495 | name = "slab" 496 | version = "0.4.3" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" 499 | 500 | [[package]] 501 | name = "socket2" 502 | version = "0.4.0" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" 505 | dependencies = [ 506 | "libc", 507 | "winapi", 508 | ] 509 | 510 | [[package]] 511 | name = "spin" 512 | version = "0.5.2" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 515 | 516 | [[package]] 517 | name = "syn" 518 | version = "1.0.73" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" 521 | dependencies = [ 522 | "proc-macro2", 523 | "quote", 524 | "unicode-xid", 525 | ] 526 | 527 | [[package]] 528 | name = "unicode-xid" 529 | version = "0.2.2" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 532 | 533 | [[package]] 534 | name = "untrusted" 535 | version = "0.7.1" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 538 | 539 | [[package]] 540 | name = "value-bag" 541 | version = "1.0.0-alpha.7" 542 | source = "registry+https://github.com/rust-lang/crates.io-index" 543 | checksum = "dd320e1520f94261153e96f7534476ad869c14022aee1e59af7c778075d840ae" 544 | dependencies = [ 545 | "ctor", 546 | "version_check", 547 | ] 548 | 549 | [[package]] 550 | name = "version_check" 551 | version = "0.9.3" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 554 | 555 | [[package]] 556 | name = "waker-fn" 557 | version = "1.1.0" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 560 | 561 | [[package]] 562 | name = "wasi" 563 | version = "0.10.2+wasi-snapshot-preview1" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 566 | 567 | [[package]] 568 | name = "wasm-bindgen" 569 | version = "0.2.74" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" 572 | dependencies = [ 573 | "cfg-if", 574 | "wasm-bindgen-macro", 575 | ] 576 | 577 | [[package]] 578 | name = "wasm-bindgen-backend" 579 | version = "0.2.74" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" 582 | dependencies = [ 583 | "bumpalo", 584 | "lazy_static", 585 | "log", 586 | "proc-macro2", 587 | "quote", 588 | "syn", 589 | "wasm-bindgen-shared", 590 | ] 591 | 592 | [[package]] 593 | name = "wasm-bindgen-futures" 594 | version = "0.4.24" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" 597 | dependencies = [ 598 | "cfg-if", 599 | "js-sys", 600 | "wasm-bindgen", 601 | "web-sys", 602 | ] 603 | 604 | [[package]] 605 | name = "wasm-bindgen-macro" 606 | version = "0.2.74" 607 | source = "registry+https://github.com/rust-lang/crates.io-index" 608 | checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" 609 | dependencies = [ 610 | "quote", 611 | "wasm-bindgen-macro-support", 612 | ] 613 | 614 | [[package]] 615 | name = "wasm-bindgen-macro-support" 616 | version = "0.2.74" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" 619 | dependencies = [ 620 | "proc-macro2", 621 | "quote", 622 | "syn", 623 | "wasm-bindgen-backend", 624 | "wasm-bindgen-shared", 625 | ] 626 | 627 | [[package]] 628 | name = "wasm-bindgen-shared" 629 | version = "0.2.74" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" 632 | 633 | [[package]] 634 | name = "web-sys" 635 | version = "0.3.51" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" 638 | dependencies = [ 639 | "js-sys", 640 | "wasm-bindgen", 641 | ] 642 | 643 | [[package]] 644 | name = "wepoll-ffi" 645 | version = "0.1.2" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" 648 | dependencies = [ 649 | "cc", 650 | ] 651 | 652 | [[package]] 653 | name = "winapi" 654 | version = "0.3.9" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 657 | dependencies = [ 658 | "winapi-i686-pc-windows-gnu", 659 | "winapi-x86_64-pc-windows-gnu", 660 | ] 661 | 662 | [[package]] 663 | name = "winapi-i686-pc-windows-gnu" 664 | version = "0.4.0" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 667 | 668 | [[package]] 669 | name = "winapi-x86_64-pc-windows-gnu" 670 | version = "0.4.0" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 673 | -------------------------------------------------------------------------------- /crates/ftl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ftl-protocol" 3 | description = "Common data structures for working with the Faster Than Light protocol as well as an optional FTL ingest control server." 4 | homepage = "https://hyperspeed.cli.rs" 5 | documentation = "https://hyperspeed.cli.rs/components/ftl" 6 | repository = "https://github.com/insertish/project-hyperspeed" 7 | version = "0.0.6" 8 | license = "MIT" 9 | edition = "2018" 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [features] 14 | server = [ "log", "async-trait", "async-std", "util" ] 15 | util = [ "ring", "rand", "hex" ] 16 | default = [ "server" ] 17 | 18 | [dependencies] 19 | # server only 20 | log = { version = "0.4", optional = true } 21 | async-trait = { version = "0.1.50", optional = true } 22 | async-std = { version = "1.8.0", features = ["attributes"], optional = true } 23 | 24 | # util only 25 | ring = { version = "0.16.20", optional = true } 26 | rand = { version = "0.8.4", optional = true } 27 | hex = { version = "0.4.3", optional = true } 28 | 29 | [package.metadata.docs.rs] 30 | all-features = true 31 | rustc-args = ["--cfg", "docsrs"] 32 | rustdoc-args = ["--cfg", "docsrs"] 33 | -------------------------------------------------------------------------------- /crates/ftl/README.md: -------------------------------------------------------------------------------- 1 | # FTL Protocol 2 | 3 | [ftl-protocol](https://gitlab.insrt.uk/insert/project-hyperspeed/-/tree/master/crates/ftl) provides common data structures for working with FTL as well as an optional FTL ingest control server. 4 | 5 | ## [Documentation](https://hyperspeed.cli.rs/components/ftl) 6 | -------------------------------------------------------------------------------- /crates/ftl/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, feature(doc_cfg))] 2 | 3 | pub mod protocol; 4 | 5 | #[cfg(feature = "server")] 6 | #[cfg_attr(docsrs, doc(cfg(feature = "server")))] 7 | pub mod server; 8 | 9 | #[cfg(feature = "util")] 10 | #[cfg_attr(docsrs, doc(cfg(feature = "util")))] 11 | pub mod util; 12 | -------------------------------------------------------------------------------- /crates/ftl/src/protocol/command.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use super::FtlError; 4 | 5 | #[derive(Debug, PartialEq)] 6 | pub enum FtlCommand { 7 | HMAC, 8 | Connect { 9 | channel_id: String, 10 | hashed_hmac_payload: String, 11 | }, 12 | Dot, 13 | Attribute { 14 | key: String, 15 | value: String, 16 | }, 17 | Ping { 18 | channel_id: String, 19 | }, 20 | Disconnect, 21 | } 22 | 23 | impl FromStr for FtlCommand { 24 | type Err = FtlError; 25 | 26 | fn from_str(s: &str) -> Result { 27 | match s { 28 | "HMAC" => Ok(FtlCommand::HMAC), 29 | "." => Ok(FtlCommand::Dot), 30 | "DISCONNECT" => Ok(FtlCommand::Disconnect), 31 | s => { 32 | if &s[..4] == "PING" { 33 | Ok(FtlCommand::Ping { 34 | channel_id: s[5..].to_string(), 35 | }) 36 | } else if &s[..7] == "CONNECT" { 37 | let parts = &mut s[8..].split(" "); 38 | 39 | Ok(FtlCommand::Connect { 40 | channel_id: parts 41 | .next() 42 | .ok_or_else(|| FtlError::MissingPart)? 43 | .to_string(), 44 | hashed_hmac_payload: parts 45 | .next() 46 | .ok_or_else(|| FtlError::MissingPart)? 47 | .to_string(), 48 | }) 49 | } else { 50 | if s.contains(':') { 51 | let mut parts = s.split(':').map(|v| v.trim()); 52 | 53 | return Ok(FtlCommand::Attribute { 54 | key: parts 55 | .next() 56 | .ok_or_else(|| FtlError::MissingPart)? 57 | .to_string(), 58 | value: parts 59 | .next() 60 | .ok_or_else(|| FtlError::MissingPart)? 61 | .to_string(), 62 | }); 63 | } 64 | 65 | Err(FtlError::UnimplementedCommand) 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | #[cfg(test)] 73 | mod tests { 74 | use std::str::FromStr; 75 | 76 | use crate::protocol::FtlCommand; 77 | 78 | #[test] 79 | fn should_parse_hmac() { 80 | let command = FtlCommand::from_str("HMAC").unwrap(); 81 | assert_eq!(command, FtlCommand::HMAC); 82 | } 83 | 84 | #[test] 85 | fn should_parse_dot() { 86 | let command = FtlCommand::from_str(".").unwrap(); 87 | assert_eq!(command, FtlCommand::Dot); 88 | } 89 | 90 | #[test] 91 | fn should_parse_disconnect() { 92 | let command = FtlCommand::from_str("DISCONNECT").unwrap(); 93 | assert_eq!(command, FtlCommand::Disconnect); 94 | } 95 | 96 | #[test] 97 | fn should_parse_ping() { 98 | let command = FtlCommand::from_str("PING channel_id").unwrap(); 99 | assert_eq!(command, FtlCommand::Ping { channel_id: "channel_id".to_string() }); 100 | } 101 | 102 | #[test] 103 | fn should_parse_connect() { 104 | let command = FtlCommand::from_str("CONNECT channel_id hmac").unwrap(); 105 | assert_eq!(command, FtlCommand::Connect { channel_id: "channel_id".to_string(), hashed_hmac_payload: "hmac".to_string() }); 106 | } 107 | 108 | #[test] 109 | fn should_parse_attribute() { 110 | let command = FtlCommand::from_str("ProtocolVersion: 0.9").unwrap(); 111 | assert_eq!(command, FtlCommand::Attribute { key: "ProtocolVersion".to_string(), value: "0.9".to_string() }); 112 | } 113 | 114 | #[test] 115 | fn should_fail_other() { 116 | let command = FtlCommand::from_str("i am invalid data"); 117 | assert!(command.is_err()) 118 | } 119 | 120 | #[test] 121 | fn doc_test() { 122 | use crate::protocol::FtlCommand; 123 | 124 | let command = FtlCommand::from_str(".").unwrap(); 125 | assert_eq!(command, FtlCommand::Dot); 126 | 127 | let command = FtlCommand::from_str("PING 123").unwrap(); 128 | assert_eq!(command, FtlCommand::Ping { 129 | channel_id: "123".to_string() 130 | }); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /crates/ftl/src/protocol/error.rs: -------------------------------------------------------------------------------- 1 | use std::string::ToString; 2 | 3 | #[derive(Debug)] 4 | pub enum FtlError { 5 | IoError, 6 | AllocateError, 7 | RingError, 8 | DecodeError, 9 | MissingPart, 10 | 11 | InvalidStreamKey, // applies to channel id as well 12 | ChannelNotAuthorized, 13 | ChannelInUse, 14 | UnsupportedRegion, 15 | GameBlocked, 16 | 17 | InvalidProtocolVersion, 18 | UnsupportedProtocolVersion, 19 | MissingCodecInformation, 20 | UnimplementedCommand, 21 | 22 | Disconnect, 23 | } 24 | 25 | impl FtlError { 26 | pub fn is_err(&self) -> bool { 27 | match self { 28 | FtlError::Disconnect => false, 29 | _ => true 30 | } 31 | } 32 | } 33 | 34 | impl ToString for FtlError { 35 | fn to_string(&self) -> String { 36 | match self { 37 | FtlError::IoError => "500 Internal Server Error\n".to_string(), 38 | FtlError::AllocateError => "500 Internal Server Error\n".to_string(), 39 | FtlError::RingError => "400 HMAC Decode Error\n".to_string(), 40 | FtlError::DecodeError => "400 HMAC Decode Error\n".to_string(), 41 | FtlError::MissingPart => "400 Bad Request\n".to_string(), 42 | 43 | FtlError::InvalidStreamKey => "405 Invalid stream key\n".to_string(), 44 | FtlError::ChannelNotAuthorized => "401 Channel not authorized to stream\n".to_string(), 45 | FtlError::ChannelInUse => "406 Channel actively streaming\n".to_string(), 46 | FtlError::UnsupportedRegion => "407 Streaming from your region is not authorized\n".to_string(), 47 | FtlError::GameBlocked => "409 Channel is not allowed to stream set game\n".to_string(), 48 | 49 | FtlError::InvalidProtocolVersion => "400 Invalid Protocol Version\n".to_string(), 50 | FtlError::UnsupportedProtocolVersion => "402 Outdated FTL SDK version\n".to_string(), 51 | FtlError::MissingCodecInformation => "400 Missing Codec Information\n".to_string(), 52 | FtlError::UnimplementedCommand => "901 Invalid Command\n".to_string(), 53 | _ => "".to_string(), 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /crates/ftl/src/protocol/handshake.rs: -------------------------------------------------------------------------------- 1 | use super::FtlError; 2 | 3 | #[derive(Default, Debug, Clone)] 4 | pub struct Vendor { 5 | pub name: Option, 6 | pub version: Option, 7 | } 8 | 9 | #[derive(Default, Debug, Clone)] 10 | pub struct Video { 11 | pub codec: Option, 12 | pub height: Option, 13 | pub width: Option, 14 | pub payload_type: Option, 15 | pub ssrc: Option, 16 | } 17 | 18 | #[derive(Default, Debug, Clone)] 19 | pub struct Audio { 20 | pub codec: Option, 21 | pub payload_type: Option, 22 | pub ssrc: Option, 23 | } 24 | 25 | #[derive(Default, Debug, Clone)] 26 | pub struct FtlHandshake { 27 | pub protocol_version: Option<(isize, isize)>, 28 | pub vendor: Vendor, 29 | pub video: Option