libsignal authenticated websocket

This commit is contained in:
Sergey Skrobotov 2024-08-06 14:21:15 -07:00 committed by GitHub
parent 31bcb1e4cc
commit de33410be1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 470 additions and 286 deletions

View file

@ -4733,7 +4733,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
``` ```
## attest 0.1.0, libsignal-ffi 0.52.3, libsignal-jni 0.52.3, libsignal-jni-testing 0.52.3, libsignal-node 0.52.3, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-bridge-testing 0.1.0, libsignal-bridge-types 0.1.0, libsignal-core 0.1.0, signal-crypto 0.1.0, device-transfer 0.1.0, signal-media 0.1.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, signal-pin 0.1.0, poksho 0.7.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0 ## attest 0.1.0, libsignal-ffi 0.54.0, libsignal-jni 0.54.0, libsignal-jni-testing 0.54.0, libsignal-node 0.54.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-bridge-testing 0.1.0, libsignal-bridge-types 0.1.0, libsignal-core 0.1.0, signal-crypto 0.1.0, device-transfer 0.1.0, signal-media 0.1.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, signal-pin 0.1.0, poksho 0.7.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
``` ```
GNU AFFERO GENERAL PUBLIC LICENSE GNU AFFERO GENERAL PUBLIC LICENSE
@ -5182,7 +5182,7 @@ You should also get your employer (if you work as a programmer) or school, if an
``` ```
## clang-sys 1.7.0 ## clang-sys 1.8.1
``` ```
@ -5779,7 +5779,7 @@ END OF TERMS AND CONDITIONS
``` ```
## debugid 0.8.0, prost-build 0.12.6, prost-derive 0.12.6, prost-types 0.12.6, prost 0.12.6 ## debugid 0.8.0, prost-build 0.13.1, prost-derive 0.13.1, prost-types 0.13.1, prost 0.13.1
``` ```
Apache License Apache License
@ -6008,7 +6008,7 @@ limitations under the License.
``` ```
## arrayref 0.3.7 ## arrayref 0.3.8
``` ```
Copyright (c) 2015 David Roundy <roundyd@physics.oregonstate.edu> Copyright (c) 2015 David Roundy <roundyd@physics.oregonstate.edu>
@ -6107,10 +6107,11 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
``` ```
## subtle 2.5.0 ## subtle 2.6.1
``` ```
Copyright (c) 2016-2017 Isis Agora Lovecruft, Henry de Valence. All rights reserved. Copyright (c) 2016-2017 Isis Agora Lovecruft, Henry de Valence. All rights reserved.
Copyright (c) 2016-2024 Isis Agora Lovecruft. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
@ -6210,7 +6211,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
``` ```
## asn1 0.16.1, asn1_derive 0.16.1 ## asn1 0.16.2, asn1_derive 0.16.2
``` ```
Copyright (c) Alex Gaynor and individual contributors. Copyright (c) Alex Gaynor and individual contributors.
@ -6476,7 +6477,7 @@ express Statement of Purpose.
``` ```
## libloading 0.8.3 ## libloading 0.8.5
``` ```
Copyright © 2015, Simonas Kazlauskas Copyright © 2015, Simonas Kazlauskas
@ -6494,7 +6495,7 @@ THIS SOFTWARE.
``` ```
## rustls-webpki 0.102.4 ## rustls-webpki 0.102.6
``` ```
Except as otherwise noted, this project is licensed under the following Except as otherwise noted, this project is licensed under the following
@ -6519,7 +6520,7 @@ third-party/chromium/LICENSE.
``` ```
## windows-core 0.52.0, windows-sys 0.45.0, windows-sys 0.48.0, windows-sys 0.52.0, windows-targets 0.42.2, windows-targets 0.48.5, windows-targets 0.52.5, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.48.5, windows_aarch64_msvc 0.52.5, windows_x86_64_gnu 0.48.5, windows_x86_64_gnu 0.52.5, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.48.5, windows_x86_64_msvc 0.52.5 ## windows-core 0.52.0, windows-sys 0.45.0, windows-sys 0.52.0, windows-targets 0.42.2, windows-targets 0.52.6, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_x86_64_gnu 0.52.6, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6
``` ```
MIT License MIT License
@ -6610,7 +6611,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## lazy_static 1.4.0, rayon-core 1.12.1, rayon 1.10.0 ## lazy_static 1.5.0, rayon-core 1.12.1, rayon 1.10.0
``` ```
Copyright (c) 2010 The Rust Project Developers Copyright (c) 2010 The Rust Project Developers
@ -6729,7 +6730,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## idna 0.5.0, percent-encoding 2.3.1, url 2.5.0 ## idna 0.5.0, percent-encoding 2.3.1, url 2.5.2
``` ```
Copyright (c) 2013-2022 The rust-url developers Copyright (c) 2013-2022 The rust-url developers
@ -6760,7 +6761,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## backtrace 0.3.71, cc 1.0.98, cfg-if 1.0.0, cmake 0.1.48, flate2 1.0.30, openssl-probe 0.1.5, rustc-demangle 0.1.24, socket2 0.5.7 ## backtrace 0.3.73, cc 1.1.6, cfg-if 1.0.0, cmake 0.1.48, flate2 1.0.30, jobserver 0.1.32, openssl-probe 0.1.5, rustc-demangle 0.1.24, socket2 0.5.7
``` ```
Copyright (c) 2014 Alex Crichton Copyright (c) 2014 Alex Crichton
@ -6823,38 +6824,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## jobserver 0.1.31 ## mio 1.0.1
```
Copyright (c) 2014 Alex Crichton
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
## mio 0.8.11
``` ```
Copyright (c) 2014 Carl Lerche and other MIO contributors Copyright (c) 2014 Carl Lerche and other MIO contributors
@ -6942,7 +6912,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## bitflags 2.5.0, glob 0.3.1, log 0.4.21, num-bigint 0.4.5, num-derive 0.4.2, num-integer 0.1.46, num-traits 0.2.19, range-map 0.2.0, regex-automata 0.4.6, regex-syntax 0.8.3, regex 1.10.4 ## bitflags 2.6.0, glob 0.3.1, log 0.4.22, num-bigint 0.4.6, num-derive 0.4.2, num-integer 0.1.46, num-traits 0.2.19, range-map 0.2.0, regex-automata 0.4.7, regex-syntax 0.8.4, regex 1.10.5
``` ```
Copyright (c) 2014 The Rust Project Developers Copyright (c) 2014 The Rust Project Developers
@ -6973,7 +6943,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## uuid 1.8.0 ## uuid 1.10.0
``` ```
Copyright (c) 2014 The Rust Project Developers Copyright (c) 2014 The Rust Project Developers
@ -7062,7 +7032,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## hyper 1.3.1 ## hyper 1.4.1
``` ```
Copyright (c) 2014-2021 Sean McArthur Copyright (c) 2014-2021 Sean McArthur
@ -7087,7 +7057,7 @@ THE SOFTWARE.
``` ```
## either 1.12.0, itertools 0.12.1, petgraph 0.6.5 ## either 1.13.0, itertools 0.13.0, petgraph 0.6.5
``` ```
Copyright (c) 2015 Copyright (c) 2015
@ -7116,32 +7086,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
```
## num_cpus 1.16.0
```
Copyright (c) 2015
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
``` ```
## neon-macros 1.0.0, neon 1.0.0 ## neon-macros 1.0.0, neon 1.0.0
@ -7169,7 +7113,7 @@ THE SOFTWARE.
``` ```
## anstyle-wincon 3.0.3 ## anstyle-wincon 3.0.4
``` ```
Copyright (c) 2015 Josh Triplett, 2022 The rust-cli Developers Copyright (c) 2015 Josh Triplett, 2022 The rust-cli Developers
@ -7225,7 +7169,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## object 0.32.2 ## object 0.36.2
``` ```
Copyright (c) 2015 The Gimli Developers Copyright (c) 2015 The Gimli Developers
@ -7256,7 +7200,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## gimli 0.28.1, heck 0.3.3, heck 0.4.1, heck 0.5.0, peeking_take_while 0.1.2, unicode-bidi 0.3.15, unicode-normalization 0.1.23, unicode-segmentation 1.11.0 ## gimli 0.29.0, heck 0.5.0, peeking_take_while 0.1.2, unicode-bidi 0.3.15, unicode-normalization 0.1.23
``` ```
Copyright (c) 2015 The Rust Project Developers Copyright (c) 2015 The Rust Project Developers
@ -7577,10 +7521,10 @@ DEALINGS IN THE SOFTWARE.
``` ```
## httparse 1.8.0 ## httparse 1.9.4
``` ```
Copyright (c) 2015-2021 Sean McArthur Copyright (c) 2015-2024 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -7635,7 +7579,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## hashbrown 0.12.3, hashbrown 0.14.5 ## hashbrown 0.14.5
``` ```
Copyright (c) 2016 Amanieu d'Antras Copyright (c) 2016 Amanieu d'Antras
@ -7666,7 +7610,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## utf8parse 0.2.1 ## utf8parse 0.2.2
``` ```
Copyright (c) 2016 Joe Wilm Copyright (c) 2016 Joe Wilm
@ -7697,7 +7641,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## anstyle-parse 0.2.4 ## anstyle-parse 0.2.5
``` ```
Copyright (c) 2016 Joe Wilm and individual contributors Copyright (c) 2016 Joe Wilm and individual contributors
@ -7728,7 +7672,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## rustls-native-certs 0.7.0, rustls-pemfile 2.1.2, rustls 0.23.8 ## rustls-native-certs 0.7.1, rustls-pemfile 2.1.2, rustls 0.23.12
``` ```
Copyright (c) 2016 Joseph Birr-Pixton <jpixton@gmail.com> Copyright (c) 2016 Joseph Birr-Pixton <jpixton@gmail.com>
@ -7941,7 +7885,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## indexmap 1.9.3, indexmap 2.2.6 ## indexmap 2.2.6
``` ```
Copyright (c) 2016--2017 Copyright (c) 2016--2017
@ -8003,7 +7947,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## addr2line 0.21.0 ## addr2line 0.22.0
``` ```
Copyright (c) 2016-2018 The gimli Developers Copyright (c) 2016-2018 The gimli Developers
@ -8096,7 +8040,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## tungstenite 0.21.0 ## tungstenite 0.23.0
``` ```
Copyright (c) 2017 Alexey Galakhov Copyright (c) 2017 Alexey Galakhov
@ -8215,7 +8159,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## tokio-tungstenite 0.21.0 ## tokio-tungstenite 0.23.1
``` ```
Copyright (c) 2017 Daniel Abramov Copyright (c) 2017 Daniel Abramov
@ -8417,7 +8361,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## bytes 1.6.0 ## bytes 1.6.1
``` ```
Copyright (c) 2018 Carl Lerche Copyright (c) 2018 Carl Lerche
@ -8751,7 +8695,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## http-body-util 0.1.1, http-body 1.0.0 ## http-body-util 0.1.2
``` ```
Copyright (c) 2019 Hyper Contributors Copyright (c) 2019 Hyper Contributors
@ -8813,7 +8757,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## protobuf-codegen 3.4.0, protobuf-json-mapping 3.4.0, protobuf-parse 3.4.0, protobuf-support 3.4.0, protobuf 3.4.0 ## protobuf-codegen 3.5.0, protobuf-json-mapping 3.5.0, protobuf-support 3.5.0, protobuf 3.5.0
``` ```
Copyright (c) 2019 Stepan Koltsov Copyright (c) 2019 Stepan Koltsov
@ -8835,6 +8779,7 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE. OR OTHER DEALINGS IN THE SOFTWARE.
``` ```
## ppv-lite86 0.2.17 ## ppv-lite86 0.2.17
@ -9055,6 +9000,37 @@ DEALINGS IN THE SOFTWARE.
``` ```
## http-body 1.0.1
```
Copyright (c) 2019-2024 Sean McArthur & Hyper Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
## iana-time-zone 0.1.60 ## iana-time-zone 0.1.60
``` ```
@ -9330,7 +9306,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## anstyle 1.0.7 ## anstyle 1.0.8
``` ```
Copyright (c) 2022 The rust-cli Developers Copyright (c) 2022 The rust-cli Developers
@ -9461,7 +9437,7 @@ SOFTWARE.
``` ```
## hyper-util 0.1.4 ## hyper-util 0.1.6
``` ```
Copyright (c) 2023 Sean McArthur Copyright (c) 2023 Sean McArthur
@ -9486,7 +9462,7 @@ THE SOFTWARE.
``` ```
## tokio-macros 2.2.0, tokio-stream 0.1.15, tokio-util 0.7.11, tokio 1.37.0 ## tokio-stream 0.1.15, tokio-util 0.7.11
``` ```
Copyright (c) 2023 Tokio Contributors Copyright (c) 2023 Tokio Contributors
@ -9542,7 +9518,7 @@ SOFTWARE.
``` ```
## anstream 0.6.14, anstyle-query 1.0.3, clap 4.4.18, colorchoice 1.0.1, env_logger 0.10.2, is_terminal_polyfill 1.70.0, toml_datetime 0.6.6, toml_edit 0.19.15 ## anstream 0.6.15, anstyle-query 1.1.1, clap 4.5.11, colorchoice 1.0.2, env_filter 0.1.2, env_logger 0.11.5, is_terminal_polyfill 1.70.1, toml_datetime 0.6.7, toml_edit 0.21.1
``` ```
Copyright (c) Individual contributors Copyright (c) Individual contributors
@ -9642,7 +9618,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## zerocopy-derive 0.7.34, zerocopy 0.7.34 ## zerocopy-derive 0.7.35, zerocopy 0.7.35
``` ```
Copyright 2023 The Fuchsia Authors Copyright 2023 The Fuchsia Authors
@ -9786,7 +9762,7 @@ SOFTWARE.
``` ```
## miniz_oxide 0.7.3 ## miniz_oxide 0.7.4
``` ```
MIT License MIT License
@ -9921,7 +9897,7 @@ SOFTWARE.
``` ```
## zeroize 1.7.0 ## zeroize 1.8.1
``` ```
MIT License MIT License
@ -9975,7 +9951,7 @@ SOFTWARE.
``` ```
## strum 0.26.2, strum_macros 0.26.4 ## strum 0.26.3, strum_macros 0.26.4
``` ```
MIT License MIT License
@ -10002,6 +9978,34 @@ SOFTWARE.
``` ```
## tokio-macros 2.4.0
```
MIT License
Copyright (c) 2019 Yoshua Wuyts
Copyright (c) Tokio Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## fslock 0.2.1 ## fslock 0.2.1
``` ```
@ -10217,7 +10221,34 @@ SOFTWARE.
``` ```
## cesu8 1.1.0, half 2.4.1, pqcrypto-internals 0.2.5, pqcrypto-kyber 0.7.9, pqcrypto-kyber 0.8.1, pqcrypto-traits 0.3.5, rustls-platform-verifier-android 0.1.0, rustls-platform-verifier 0.3.1 ## rustls-platform-verifier-android 0.1.0, rustls-platform-verifier 0.3.2
```
MIT License
Copyright (c) 2022 1Password
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## cesu8 1.1.0, half 2.4.1, pqcrypto-internals 0.2.5, pqcrypto-kyber 0.7.9, pqcrypto-kyber 0.8.1, pqcrypto-traits 0.3.5, protobuf-parse 3.5.0
``` ```
MIT License MIT License
@ -10232,6 +10263,33 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
``` ```
## tokio 1.39.1
```
MIT License
Copyright (c) Tokio Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## android-tzdata 0.1.1 ## android-tzdata 0.1.1
``` ```
@ -10316,7 +10374,7 @@ DEALINGS IN THE SOFTWARE.
``` ```
## curve25519-dalek-derive 0.1.1, adler 1.0.2, anyhow 1.0.86, async-trait 0.1.80, atomic-waker 1.1.2, displaydoc 0.2.5, dyn-clone 1.0.17, fastrand 2.1.0, home 0.5.9, is-terminal 0.4.12, itoa 1.0.11, linkme-impl 0.3.26, linkme 0.3.26, linux-raw-sys 0.4.14, minimal-lexical 0.2.1, num_enum 0.6.1, num_enum_derive 0.6.1, once_cell 1.19.0, paste 1.0.15, pin-project-lite 0.2.14, prettyplease 0.2.20, proc-macro-crate 1.3.1, proc-macro2 1.0.83, quote 1.0.36, rustc-hash 1.1.0, rustix 0.38.34, rustversion 1.0.17, semver 1.0.23, send_wrapper 0.6.0, serde 1.0.202, serde_derive 1.0.202, serde_json 1.0.117, syn-mid 0.6.0, syn 1.0.109, syn 2.0.66, thiserror-impl 1.0.61, thiserror 1.0.61, unicode-ident 1.0.12, utf-8 0.7.6 ## curve25519-dalek-derive 0.1.1, adler 1.0.2, anyhow 1.0.86, async-trait 0.1.81, atomic-waker 1.1.2, displaydoc 0.2.5, dyn-clone 1.0.17, fastrand 2.1.0, home 0.5.9, itoa 1.0.11, linkme-impl 0.3.27, linkme 0.3.27, linux-raw-sys 0.4.14, minimal-lexical 0.2.1, num_enum 0.7.2, num_enum_derive 0.7.2, once_cell 1.19.0, paste 1.0.15, pin-project-lite 0.2.14, prettyplease 0.2.20, proc-macro-crate 3.1.0, proc-macro2 1.0.86, quote 1.0.36, rustc-hash 1.1.0, rustix 0.38.34, rustversion 1.0.17, semver 1.0.23, send_wrapper 0.6.0, serde 1.0.204, serde_derive 1.0.204, serde_json 1.0.120, syn-mid 0.6.0, syn 1.0.109, syn 2.0.72, thiserror-impl 1.0.63, thiserror 1.0.63, unicode-ident 1.0.12, utf-8 0.7.6
``` ```
Permission is hereby granted, free of charge, to any Permission is hereby granted, free of charge, to any
@ -10369,7 +10427,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
``` ```
## tinyvec 1.6.0 ## tinyvec 1.8.0
``` ```
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@ -10512,7 +10570,7 @@ THE SOFTWARE.
``` ```
## aho-corasick 1.1.3, byteorder 1.5.0, memchr 2.7.2, termcolor 1.4.1, walkdir 2.5.0 ## aho-corasick 1.1.3, byteorder 1.5.0, memchr 2.7.4, walkdir 2.5.0
``` ```
The MIT License (MIT) The MIT License (MIT)
@ -10539,7 +10597,7 @@ THE SOFTWARE.
``` ```
## strsim 0.10.0 ## strsim 0.10.0, strsim 0.11.1
``` ```
The MIT License (MIT) The MIT License (MIT)
@ -10623,7 +10681,7 @@ THE SOFTWARE.
``` ```
## security-framework-sys 2.11.0, security-framework 2.11.0 ## security-framework-sys 2.11.1, security-framework 2.11.1
``` ```
The MIT License (MIT) The MIT License (MIT)
@ -10677,7 +10735,7 @@ SOFTWARE.
``` ```
## clap_builder 4.4.18, clap_derive 4.4.7, clap_lex 0.6.0 ## clap_builder 4.5.11, clap_derive 4.5.11, clap_lex 0.7.2
``` ```
The MIT License (MIT) The MIT License (MIT)
@ -10704,7 +10762,7 @@ SOFTWARE.
``` ```
## derive_more 0.99.17 ## derive_more 0.99.18
``` ```
The MIT License (MIT) The MIT License (MIT)
@ -10812,7 +10870,7 @@ THE SOFTWARE.
``` ```
## async-compression 0.4.10 ## async-compression 0.4.12
``` ```
The MIT License (MIT) The MIT License (MIT)
@ -10960,7 +11018,7 @@ SOFTWARE.
``` ```
## version_check 0.9.4 ## version_check 0.9.5
``` ```
The MIT License (MIT) The MIT License (MIT)

8
package-lock.json generated
View file

@ -22,7 +22,7 @@
"@react-aria/utils": "3.16.0", "@react-aria/utils": "3.16.0",
"@react-spring/web": "9.5.5", "@react-spring/web": "9.5.5",
"@signalapp/better-sqlite3": "8.7.1", "@signalapp/better-sqlite3": "8.7.1",
"@signalapp/libsignal-client": "0.52.3", "@signalapp/libsignal-client": "0.54.0",
"@signalapp/ringrtc": "2.46.0", "@signalapp/ringrtc": "2.46.0",
"@signalapp/windows-dummy-keystroke": "1.0.0", "@signalapp/windows-dummy-keystroke": "1.0.0",
"@types/fabric": "4.5.3", "@types/fabric": "4.5.3",
@ -7224,9 +7224,9 @@
} }
}, },
"node_modules/@signalapp/libsignal-client": { "node_modules/@signalapp/libsignal-client": {
"version": "0.52.3", "version": "0.54.0",
"resolved": "https://registry.npmjs.org/@signalapp/libsignal-client/-/libsignal-client-0.52.3.tgz", "resolved": "https://registry.npmjs.org/@signalapp/libsignal-client/-/libsignal-client-0.54.0.tgz",
"integrity": "sha512-mGO6DUfaWq4tX6NdX3jCXe+1TB/PhX0Lw5HBsJVxJpIUITRF0+OQqDHddj31+DL7F6tbTBX3pyp/L+BKLpg4Gw==", "integrity": "sha512-bkdw3r39UU0W0UaFAJJVhLC5AEiMkgCgtdtabI64c1KuT7oeIx4XvegfqtBwF7vKj29ZHz4lODCh3tFyqbrNLw==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"node-gyp-build": "^4.2.3", "node-gyp-build": "^4.2.3",

View file

@ -104,7 +104,7 @@
"@react-aria/utils": "3.16.0", "@react-aria/utils": "3.16.0",
"@react-spring/web": "9.5.5", "@react-spring/web": "9.5.5",
"@signalapp/better-sqlite3": "8.7.1", "@signalapp/better-sqlite3": "8.7.1",
"@signalapp/libsignal-client": "0.52.3", "@signalapp/libsignal-client": "0.54.0",
"@signalapp/ringrtc": "2.46.0", "@signalapp/ringrtc": "2.46.0",
"@signalapp/windows-dummy-keystroke": "1.0.0", "@signalapp/windows-dummy-keystroke": "1.0.0",
"@types/fabric": "4.5.3", "@types/fabric": "4.5.3",

View file

@ -26,6 +26,7 @@ export type ConfigKeyType =
| 'desktop.retryRespondMaxAge' | 'desktop.retryRespondMaxAge'
| 'desktop.senderKey.retry' | 'desktop.senderKey.retry'
| 'desktop.senderKeyMaxAge' | 'desktop.senderKeyMaxAge'
| 'desktop.experimentalTransport.enableAuth'
| 'desktop.experimentalTransportEnabled.alpha' | 'desktop.experimentalTransportEnabled.alpha'
| 'desktop.experimentalTransportEnabled.beta' | 'desktop.experimentalTransportEnabled.beta'
| 'desktop.experimentalTransportEnabled.prod' | 'desktop.experimentalTransportEnabled.prod'

View file

@ -7,7 +7,7 @@ import { assert } from 'chai';
import Long from 'long'; import Long from 'long';
import MessageReceiver from '../textsecure/MessageReceiver'; import MessageReceiver from '../textsecure/MessageReceiver';
import { IncomingWebSocketRequest } from '../textsecure/WebsocketResources'; import { IncomingWebSocketRequestLegacy } from '../textsecure/WebsocketResources';
import type { WebAPIType } from '../textsecure/WebAPI'; import type { WebAPIType } from '../textsecure/WebAPI';
import type { DecryptionErrorEvent } from '../textsecure/messageReceiverEvents'; import type { DecryptionErrorEvent } from '../textsecure/messageReceiverEvents';
import { generateAci } from '../types/ServiceId'; import { generateAci } from '../types/ServiceId';
@ -53,7 +53,7 @@ describe('MessageReceiver', () => {
}).finish(); }).finish();
messageReceiver.handleRequest( messageReceiver.handleRequest(
new IncomingWebSocketRequest( new IncomingWebSocketRequestLegacy(
{ {
id: Long.fromNumber(1), id: Long.fromNumber(1),
verb: 'PUT', verb: 'PUT',

View file

@ -16,7 +16,9 @@ import Long from 'long';
import { dropNull } from '../util/dropNull'; import { dropNull } from '../util/dropNull';
import { SignalService as Proto } from '../protobuf'; import { SignalService as Proto } from '../protobuf';
import WebSocketResource from '../textsecure/WebsocketResources'; import WebSocketResource, {
ServerRequestType,
} from '../textsecure/WebsocketResources';
describe('WebSocket-Resource', () => { describe('WebSocket-Resource', () => {
class FakeSocket extends EventEmitter { class FakeSocket extends EventEmitter {
@ -72,8 +74,7 @@ describe('WebSocket-Resource', () => {
new WebSocketResource(socket as WebSocket, { new WebSocketResource(socket as WebSocket, {
name: 'test', name: 'test',
handleRequest(request: any) { handleRequest(request: any) {
assert.strictEqual(request.verb, 'PUT'); assert.strictEqual(request.requestType, ServerRequestType.ApiMessage);
assert.strictEqual(request.path, '/some/path');
assert.deepEqual(request.body, new Uint8Array([1, 2, 3])); assert.deepEqual(request.body, new Uint8Array([1, 2, 3]));
request.respond(200, 'OK'); request.respond(200, 'OK');
}, },
@ -87,7 +88,7 @@ describe('WebSocket-Resource', () => {
request: { request: {
id: requestId, id: requestId,
verb: 'PUT', verb: 'PUT',
path: '/some/path', path: ServerRequestType.ApiMessage.toString(),
body: new Uint8Array([1, 2, 3]), body: new Uint8Array([1, 2, 3]),
}, },
}).finish(), }).finish(),

View file

@ -15,39 +15,40 @@ import type {
WebAPIType, WebAPIType,
} from './WebAPI'; } from './WebAPI';
import type { import type {
CompatSignedPreKeyType,
CompatPreKeyType, CompatPreKeyType,
CompatSignedPreKeyType,
KeyPairType, KeyPairType,
KyberPreKeyType, KyberPreKeyType,
PniKeyMaterialType, PniKeyMaterialType,
} from './Types.d'; } from './Types.d';
import ProvisioningCipher from './ProvisioningCipher'; import ProvisioningCipher from './ProvisioningCipher';
import type { IncomingWebSocketRequest } from './WebsocketResources'; import type { IncomingWebSocketRequest } from './WebsocketResources';
import { ServerRequestType } from './WebsocketResources';
import createTaskWithTimeout from './TaskWithTimeout'; import createTaskWithTimeout from './TaskWithTimeout';
import * as Bytes from '../Bytes'; import * as Bytes from '../Bytes';
import * as Errors from '../types/errors'; import * as Errors from '../types/errors';
import { senderCertificateService } from '../services/senderCertificate'; import { senderCertificateService } from '../services/senderCertificate';
import { backupsService } from '../services/backups'; import { backupsService } from '../services/backups';
import { import {
decryptDeviceName,
deriveAccessKey, deriveAccessKey,
deriveStorageServiceKey,
encryptDeviceName,
generateRegistrationId, generateRegistrationId,
getRandomBytes, getRandomBytes,
decryptDeviceName,
encryptDeviceName,
deriveStorageServiceKey,
} from '../Crypto'; } from '../Crypto';
import { import {
generateKeyPair, generateKeyPair,
generateSignedPreKey,
generatePreKey,
generateKyberPreKey, generateKyberPreKey,
generatePreKey,
generateSignedPreKey,
} from '../Curve'; } from '../Curve';
import type { ServiceIdString, AciString, PniString } from '../types/ServiceId'; import type { AciString, PniString, ServiceIdString } from '../types/ServiceId';
import { import {
ServiceIdKind,
normalizePni,
toTaggedPni,
isUntaggedPniString, isUntaggedPniString,
normalizePni,
ServiceIdKind,
toTaggedPni,
} from '../types/ServiceId'; } from '../types/ServiceId';
import { normalizeAci } from '../util/normalizeAci'; import { normalizeAci } from '../util/normalizeAci';
import { drop } from '../util/drop'; import { drop } from '../util/drop';
@ -367,8 +368,7 @@ export default class AccountManager extends EventTarget {
const wsr = await this.server.getProvisioningResource({ const wsr = await this.server.getProvisioningResource({
handleRequest(request: IncomingWebSocketRequest) { handleRequest(request: IncomingWebSocketRequest) {
if ( if (
request.path === '/v1/address' && request.requestType === ServerRequestType.ProvisioningAddress &&
request.verb === 'PUT' &&
request.body request.body
) { ) {
const proto = Proto.ProvisioningUuid.decode(request.body); const proto = Proto.ProvisioningUuid.decode(request.body);
@ -388,8 +388,7 @@ export default class AccountManager extends EventTarget {
setProvisioningUrl(url); setProvisioningUrl(url);
request.respond(200, 'OK'); request.respond(200, 'OK');
} else if ( } else if (
request.path === '/v1/message' && request.requestType === ServerRequestType.ProvisioningMessage &&
request.verb === 'PUT' &&
request.body request.body
) { ) {
const envelope = Proto.ProvisionEnvelope.decode(request.body); const envelope = Proto.ProvisionEnvelope.decode(request.body);
@ -397,7 +396,7 @@ export default class AccountManager extends EventTarget {
wsr.close(); wsr.close();
envelopeCallbacks?.resolve(envelope); envelopeCallbacks?.resolve(envelope);
} else { } else {
log.error('Unknown websocket message', request.path); log.error('Unknown websocket message', request.requestType);
} }
}, },
}); });

View file

@ -13,13 +13,13 @@ import type {
UnidentifiedSenderMessageContent, UnidentifiedSenderMessageContent,
} from '@signalapp/libsignal-client'; } from '@signalapp/libsignal-client';
import { import {
ContentHint,
CiphertextMessageType, CiphertextMessageType,
ContentHint,
DecryptionErrorMessage, DecryptionErrorMessage,
groupDecrypt, groupDecrypt,
PlaintextContent, PlaintextContent,
PreKeySignalMessage,
Pni, Pni,
PreKeySignalMessage,
processSenderKeyDistributionMessage, processSenderKeyDistributionMessage,
ProtocolAddress, ProtocolAddress,
PublicKey, PublicKey,
@ -40,7 +40,7 @@ import {
SignedPreKeys, SignedPreKeys,
} from '../LibSignalStores'; } from '../LibSignalStores';
import { verifySignature } from '../Curve'; import { verifySignature } from '../Curve';
import { strictAssert, assertDev } from '../util/assert'; import { assertDev, strictAssert } from '../util/assert';
import type { BatcherType } from '../util/batcher'; import type { BatcherType } from '../util/batcher';
import { createBatcher } from '../util/batcher'; import { createBatcher } from '../util/batcher';
import { drop } from '../util/drop'; import { drop } from '../util/drop';
@ -48,6 +48,7 @@ import { dropNull } from '../util/dropNull';
import { parseIntOrThrow } from '../util/parseIntOrThrow'; import { parseIntOrThrow } from '../util/parseIntOrThrow';
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary'; import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
import { Zone } from '../util/Zone'; import { Zone } from '../util/Zone';
import * as durations from '../util/durations';
import { DurationInSeconds, SECOND } from '../util/durations'; import { DurationInSeconds, SECOND } from '../util/durations';
import type { AttachmentType } from '../types/Attachment'; import type { AttachmentType } from '../types/Attachment';
import { Address } from '../types/Address'; import { Address } from '../types/Address';
@ -55,13 +56,13 @@ import { QualifiedAddress } from '../types/QualifiedAddress';
import { normalizeStoryDistributionId } from '../types/StoryDistributionId'; import { normalizeStoryDistributionId } from '../types/StoryDistributionId';
import type { ServiceIdString } from '../types/ServiceId'; import type { ServiceIdString } from '../types/ServiceId';
import { import {
ServiceIdKind,
normalizeServiceId,
normalizePni,
isPniString,
isUntaggedPniString,
isServiceIdString,
fromPniObject, fromPniObject,
isPniString,
isServiceIdString,
isUntaggedPniString,
normalizePni,
normalizeServiceId,
ServiceIdKind,
toTaggedPni, toTaggedPni,
} from '../types/ServiceId'; } from '../types/ServiceId';
import { normalizeAci } from '../util/normalizeAci'; import { normalizeAci } from '../util/normalizeAci';
@ -75,70 +76,70 @@ import createTaskWithTimeout from './TaskWithTimeout';
import { import {
processAttachment, processAttachment,
processDataMessage, processDataMessage,
processPreview,
processGroupV2Context, processGroupV2Context,
processPreview,
} from './processDataMessage'; } from './processDataMessage';
import { processSyncMessage } from './processSyncMessage'; import { processSyncMessage } from './processSyncMessage';
import type { EventHandler } from './EventTarget'; import type { EventHandler } from './EventTarget';
import EventTarget from './EventTarget'; import EventTarget from './EventTarget';
import { downloadAttachment } from './downloadAttachment'; import { downloadAttachment } from './downloadAttachment';
import type { IncomingWebSocketRequest } from './WebsocketResources'; import type { IncomingWebSocketRequest } from './WebsocketResources';
import { ServerRequestType } from './WebsocketResources';
import { parseContactsV2 } from './ContactsParser'; import { parseContactsV2 } from './ContactsParser';
import type { WebAPIType } from './WebAPI'; import type { WebAPIType } from './WebAPI';
import type { Storage } from './Storage'; import type { Storage } from './Storage';
import { WarnOnlyError } from './Errors'; import { WarnOnlyError } from './Errors';
import * as Bytes from '../Bytes'; import * as Bytes from '../Bytes';
import type { import type {
IRequestHandler,
ProcessedAttachment, ProcessedAttachment,
ProcessedDataMessage, ProcessedDataMessage,
ProcessedPreview,
ProcessedSyncMessage,
ProcessedSent,
ProcessedEnvelope, ProcessedEnvelope,
IRequestHandler, ProcessedPreview,
ProcessedSent,
ProcessedSyncMessage,
UnprocessedType, UnprocessedType,
} from './Types.d'; } from './Types.d';
import type {
ConversationToDelete,
DeleteForMeSyncEventData,
DeleteForMeSyncTarget,
MessageToDelete,
ReadSyncEventData,
ViewSyncEventData,
} from './messageReceiverEvents';
import { import {
CallEventSyncEvent, CallEventSyncEvent,
CallLinkUpdateSyncEvent,
CallLogEventSyncEvent,
ConfigurationEvent,
ContactSyncEvent,
DecryptionErrorEvent,
DeleteForMeSyncEvent,
DeliveryEvent,
EmptyEvent, EmptyEvent,
EnvelopeQueuedEvent, EnvelopeQueuedEvent,
EnvelopeUnsealedEvent, EnvelopeUnsealedEvent,
ProgressEvent,
TypingEvent,
ErrorEvent, ErrorEvent,
DeliveryEvent,
DecryptionErrorEvent,
SentEvent,
ProfileKeyUpdateEvent,
InvalidPlaintextEvent,
MessageEvent,
RetryRequestEvent,
ReadEvent,
ViewEvent,
ConfigurationEvent,
ViewOnceOpenSyncEvent,
MessageRequestResponseEvent,
FetchLatestEvent, FetchLatestEvent,
InvalidPlaintextEvent,
KeysEvent, KeysEvent,
StickerPackEvent, MessageEvent,
MessageRequestResponseEvent,
ProfileKeyUpdateEvent,
ProgressEvent,
ReadEvent,
ReadSyncEvent, ReadSyncEvent,
ViewSyncEvent, RetryRequestEvent,
ContactSyncEvent, SentEvent,
StickerPackEvent,
StoryRecipientUpdateEvent, StoryRecipientUpdateEvent,
CallLogEventSyncEvent, TypingEvent,
CallLinkUpdateSyncEvent, ViewEvent,
DeleteForMeSyncEvent, ViewOnceOpenSyncEvent,
} from './messageReceiverEvents'; ViewSyncEvent,
import type {
MessageToDelete,
DeleteForMeSyncEventData,
DeleteForMeSyncTarget,
ConversationToDelete,
ViewSyncEventData,
ReadSyncEventData,
} from './messageReceiverEvents'; } from './messageReceiverEvents';
import * as log from '../logging/log'; import * as log from '../logging/log';
import * as durations from '../util/durations';
import { areArraysMatchingSets } from '../util/areArraysMatchingSets'; import { areArraysMatchingSets } from '../util/areArraysMatchingSets';
import { generateBlurHash } from '../util/generateBlurHash'; import { generateBlurHash } from '../util/generateBlurHash';
import { TEXT_ATTACHMENT } from '../types/MIME'; import { TEXT_ATTACHMENT } from '../types/MIME';
@ -385,11 +386,11 @@ export default class MessageReceiver
public handleRequest(request: IncomingWebSocketRequest): void { public handleRequest(request: IncomingWebSocketRequest): void {
// We do the message decryption here, instead of in the ordered pending queue, // We do the message decryption here, instead of in the ordered pending queue,
// to avoid exposing the time it took us to process messages through the time-to-ack. // to avoid exposing the time it took us to process messages through the time-to-ack.
log.info('MessageReceiver: got request', request.verb, request.path); log.info('MessageReceiver: got request', request.requestType);
if (request.path !== '/api/v1/message') { if (request.requestType !== ServerRequestType.ApiMessage) {
request.respond(200, 'OK'); request.respond(200, 'OK');
if (request.verb === 'PUT' && request.path === '/api/v1/queue/empty') { if (request.requestType === ServerRequestType.ApiEmptyQueue) {
drop( drop(
this.incomingQueue.add( this.incomingQueue.add(
createTaskWithTimeout( createTaskWithTimeout(
@ -406,8 +407,6 @@ export default class MessageReceiver
} }
const job = async () => { const job = async () => {
const headers = request.headers || [];
if (!request.body) { if (!request.body) {
throw new Error( throw new Error(
'MessageReceiver.handleRequest: request.body was falsey!' 'MessageReceiver.handleRequest: request.body was falsey!'
@ -429,7 +428,10 @@ export default class MessageReceiver
receivedAtCounter: incrementMessageCounter(), receivedAtCounter: incrementMessageCounter(),
receivedAtDate: Date.now(), receivedAtDate: Date.now(),
// Calculate the message age (time on server). // Calculate the message age (time on server).
messageAgeSec: this.calculateMessageAge(headers, serverTimestamp), messageAgeSec: this.calculateMessageAge(
request.timestamp,
serverTimestamp
),
// Proto.Envelope fields // Proto.Envelope fields
type: decoded.type ?? Proto.Envelope.Type.UNKNOWN, type: decoded.type ?? Proto.Envelope.Type.UNKNOWN,
@ -728,32 +730,15 @@ export default class MessageReceiver
} }
private calculateMessageAge( private calculateMessageAge(
headers: ReadonlyArray<string>, timestamp: number | undefined,
serverTimestamp?: number serverTimestamp: number | undefined
): number { ): number {
let messageAgeSec = 0; // Default to 0 in case of unreliable parameters. // Default to 0 in case of unreliable parameters.
// One final sanity check, the timestamp when a message is pulled from
if (serverTimestamp) { // the server should be later than when it was pushed.
// The 'X-Signal-Timestamp' is usually the last item, so start there. return serverTimestamp && timestamp && timestamp > serverTimestamp
let it = headers.length; ? Math.floor((timestamp - serverTimestamp) / 1000)
// eslint-disable-next-line no-plusplus : 0;
while (--it >= 0) {
const match = headers[it].match(/^X-Signal-Timestamp:\s*(\d+)\s*$/i);
if (match && match.length === 2) {
const timestamp = Number(match[1]);
// One final sanity check, the timestamp when a message is pulled from
// the server should be later than when it was pushed.
if (timestamp > serverTimestamp) {
messageAgeSec = Math.floor((timestamp - serverTimestamp) / 1000);
}
break;
}
}
}
return messageAgeSec;
} }
private async addToQueue<T>( private async addToQueue<T>(

View file

@ -13,14 +13,14 @@ import { AbortableProcess } from '../util/AbortableProcess';
import { strictAssert } from '../util/assert'; import { strictAssert } from '../util/assert';
import { import {
BackOff, BackOff,
FIBONACCI_TIMEOUTS,
EXTENDED_FIBONACCI_TIMEOUTS, EXTENDED_FIBONACCI_TIMEOUTS,
FIBONACCI_TIMEOUTS,
} from '../util/BackOff'; } from '../util/BackOff';
import * as durations from '../util/durations'; import * as durations from '../util/durations';
import { sleep } from '../util/sleep'; import { sleep } from '../util/sleep';
import { drop } from '../util/drop'; import { drop } from '../util/drop';
import { createProxyAgent } from '../util/createProxyAgent';
import type { ProxyAgent } from '../util/createProxyAgent'; import type { ProxyAgent } from '../util/createProxyAgent';
import { createProxyAgent } from '../util/createProxyAgent';
import { SocketStatus } from '../types/SocketStatus'; import { SocketStatus } from '../types/SocketStatus';
import * as Errors from '../types/errors'; import * as Errors from '../types/errors';
import * as Bytes from '../Bytes'; import * as Bytes from '../Bytes';
@ -32,7 +32,8 @@ import type {
WebSocketResourceOptions, WebSocketResourceOptions,
} from './WebsocketResources'; } from './WebsocketResources';
import WebSocketResource, { import WebSocketResource, {
LibsignalWebSocketResource, connectAuthenticatedLibsignal,
connectUnauthenticatedLibsignal,
TransportOption, TransportOption,
WebSocketResourceWithShadowing, WebSocketResourceWithShadowing,
} from './WebsocketResources'; } from './WebsocketResources';
@ -166,22 +167,38 @@ export class SocketManager extends EventListener {
this.setStatus(SocketStatus.CONNECTING); this.setStatus(SocketStatus.CONNECTING);
const process = this.connectResource({ const proxyAgent = await this.getProxyAgent();
name: AUTHENTICATED_CHANNEL_NAME, const useLibsignalTransport =
path: '/v1/websocket/', window.Signal.RemoteConfig.isEnabled(
query: { login: username, password }, 'desktop.experimentalTransport.enableAuth'
proxyAgent: await this.getProxyAgent(), ) && this.transportOption(proxyAgent) === TransportOption.Libsignal;
resourceOptions: {
name: AUTHENTICATED_CHANNEL_NAME, const process = useLibsignalTransport
keepalive: { path: '/v1/keepalive' }, ? connectAuthenticatedLibsignal({
handleRequest: (req: IncomingWebSocketRequest): void => { libsignalNet: this.libsignalNet,
this.queueOrHandleRequest(req); name: AUTHENTICATED_CHANNEL_NAME,
}, credentials: this.credentials,
}, handler: (req: IncomingWebSocketRequest): void => {
extraHeaders: { this.queueOrHandleRequest(req);
'X-Signal-Receive-Stories': String(!this.hasStoriesDisabled), },
}, receiveStories: !this.hasStoriesDisabled,
}); })
: this.connectResource({
name: AUTHENTICATED_CHANNEL_NAME,
path: '/v1/websocket/',
query: { login: username, password },
resourceOptions: {
name: AUTHENTICATED_CHANNEL_NAME,
keepalive: { path: '/v1/keepalive' },
handleRequest: (req: IncomingWebSocketRequest): void => {
this.queueOrHandleRequest(req);
},
},
extraHeaders: {
'X-Signal-Receive-Stories': String(!this.hasStoriesDisabled),
},
proxyAgent,
});
// Cancel previous connect attempt or close socket // Cancel previous connect attempt or close socket
this.authenticated?.abort(); this.authenticated?.abort();
@ -575,10 +592,10 @@ export class SocketManager extends EventListener {
} }
private connectLibsignalUnauthenticated(): AbortableProcess<IWebSocketResource> { private connectLibsignalUnauthenticated(): AbortableProcess<IWebSocketResource> {
return LibsignalWebSocketResource.connect( return connectUnauthenticatedLibsignal({
this.libsignalNet, libsignalNet: this.libsignalNet,
UNAUTHENTICATED_CHANNEL_NAME name: UNAUTHENTICATED_CHANNEL_NAME,
); });
} }
private async getUnauthenticatedResource(): Promise<IWebSocketResource> { private async getUnauthenticatedResource(): Promise<IWebSocketResource> {
@ -724,10 +741,10 @@ export class SocketManager extends EventListener {
options: WebSocketResourceOptions options: WebSocketResourceOptions
): AbortableProcess<IWebSocketResource> { ): AbortableProcess<IWebSocketResource> {
// creating an `AbortableProcess` of libsignal websocket connection // creating an `AbortableProcess` of libsignal websocket connection
const shadowingConnection = LibsignalWebSocketResource.connect( const shadowingConnection = connectUnauthenticatedLibsignal({
this.libsignalNet, libsignalNet: this.libsignalNet,
options.name name: options.name,
); });
const shadowWrapper = async () => { const shadowWrapper = async () => {
// if main connection results in an error, // if main connection results in an error,
// it's propagated as the error of the resulting process // it's propagated as the error of the resulting process

View file

@ -37,6 +37,8 @@ import { random } from 'lodash';
import type { ChatServiceDebugInfo } from '@signalapp/libsignal-client/Native'; import type { ChatServiceDebugInfo } from '@signalapp/libsignal-client/Native';
import type { Net } from '@signalapp/libsignal-client'; import type { Net } from '@signalapp/libsignal-client';
import { Buffer } from 'node:buffer';
import type { ChatServerMessageAck } from '@signalapp/libsignal-client/dist/net';
import type { EventHandler } from './EventTarget'; import type { EventHandler } from './EventTarget';
import EventTarget from './EventTarget'; import EventTarget from './EventTarget';
@ -54,6 +56,7 @@ import { isProduction } from '../util/version';
import { ToastType } from '../types/Toast'; import { ToastType } from '../types/Toast';
import { AbortableProcess } from '../util/AbortableProcess'; import { AbortableProcess } from '../util/AbortableProcess';
import type { WebAPICredentials } from './Types';
const THIRTY_SECONDS = 30 * durations.SECOND; const THIRTY_SECONDS = 30 * durations.SECOND;
@ -166,16 +169,49 @@ export namespace AggregatedStats {
} }
} }
export class IncomingWebSocketRequest { export enum ServerRequestType {
ApiMessage = '/api/v1/message',
ApiEmptyQueue = '/api/v1/queue/empty',
ProvisioningMessage = '/v1/message',
ProvisioningAddress = '/v1/address',
Unknown = 'unknown',
}
export type IncomingWebSocketRequest = {
readonly requestType: ServerRequestType;
readonly body: Uint8Array | undefined;
readonly timestamp: number | undefined;
respond(status: number, message: string): void;
};
export class IncomingWebSocketRequestLibsignal
implements IncomingWebSocketRequest
{
constructor(
readonly requestType: ServerRequestType,
readonly body: Uint8Array | undefined,
readonly timestamp: number | undefined,
private readonly ack: ChatServerMessageAck | undefined
) {}
respond(status: number, _message: string): void {
if (this.ack) {
drop(this.ack.send(status));
}
}
}
export class IncomingWebSocketRequestLegacy
implements IncomingWebSocketRequest
{
private readonly id: Long; private readonly id: Long;
public readonly verb: string; public readonly requestType: ServerRequestType;
public readonly path: string;
public readonly body: Uint8Array | undefined; public readonly body: Uint8Array | undefined;
public readonly headers: ReadonlyArray<string>; public readonly timestamp: number | undefined;
constructor( constructor(
request: Proto.IWebSocketRequestMessage, request: Proto.IWebSocketRequestMessage,
@ -186,10 +222,9 @@ export class IncomingWebSocketRequest {
strictAssert(request.path, 'request without path'); strictAssert(request.path, 'request without path');
this.id = request.id; this.id = request.id;
this.verb = request.verb; this.requestType = resolveType(request.path, request.verb);
this.path = request.path;
this.body = dropNull(request.body); this.body = dropNull(request.body);
this.headers = request.headers || []; this.timestamp = resolveTimestamp(request.headers || []);
} }
public respond(status: number, message: string): void { public respond(status: number, message: string): void {
@ -202,6 +237,35 @@ export class IncomingWebSocketRequest {
} }
} }
function resolveType(path: string, verb: string): ServerRequestType {
if (path === ServerRequestType.ApiMessage) {
return ServerRequestType.ApiMessage;
}
if (path === ServerRequestType.ApiEmptyQueue && verb === 'PUT') {
return ServerRequestType.ApiEmptyQueue;
}
if (path === ServerRequestType.ProvisioningAddress && verb === 'PUT') {
return ServerRequestType.ProvisioningAddress;
}
if (path === ServerRequestType.ProvisioningMessage && verb === 'PUT') {
return ServerRequestType.ProvisioningMessage;
}
return ServerRequestType.Unknown;
}
function resolveTimestamp(headers: ReadonlyArray<string>): number | undefined {
// The 'X-Signal-Timestamp' is usually the last item, so start there.
let it = headers.length;
// eslint-disable-next-line no-plusplus
while (--it >= 0) {
const match = headers[it].match(/^X-Signal-Timestamp:\s*(\d+)\s*$/i);
if (match && match.length === 2) {
return Number(match[1]);
}
}
return undefined;
}
export type SendRequestOptions = Readonly<{ export type SendRequestOptions = Readonly<{
verb: string; verb: string;
path: string; path: string;
@ -266,6 +330,100 @@ export interface IWebSocketResource extends IResource {
localPort(): number | undefined; localPort(): number | undefined;
} }
export function connectUnauthenticatedLibsignal({
libsignalNet,
name,
}: {
libsignalNet: Net.Net;
name: string;
}): AbortableProcess<LibsignalWebSocketResource> {
return connectLibsignal(libsignalNet.newUnauthenticatedChatService(), name);
}
export function connectAuthenticatedLibsignal({
libsignalNet,
name,
credentials,
handler,
receiveStories,
}: {
libsignalNet: Net.Net;
name: string;
credentials: WebAPICredentials;
handler: (request: IncomingWebSocketRequest) => void;
receiveStories: boolean;
}): AbortableProcess<LibsignalWebSocketResource> {
const listener = {
onIncomingMessage(
envelope: Buffer,
timestamp: number,
ack: ChatServerMessageAck
): void {
const request = new IncomingWebSocketRequestLibsignal(
ServerRequestType.ApiMessage,
envelope,
timestamp,
ack
);
handler(request);
},
onQueueEmpty(): void {
const request = new IncomingWebSocketRequestLibsignal(
ServerRequestType.ApiEmptyQueue,
undefined,
undefined,
undefined
);
handler(request);
},
onConnectionInterrupted(): void {
log.warn(`LibsignalWebSocketResource(${name}): connection interrupted`);
},
};
return connectLibsignal(
libsignalNet.newAuthenticatedChatService(
credentials.username,
credentials.password,
receiveStories,
listener
),
name
);
}
function connectLibsignal(
chatService: Net.ChatService,
name: string
): AbortableProcess<LibsignalWebSocketResource> {
const connectAsync = async () => {
try {
const debugInfo = await chatService.connect();
log.info(`LibsignalWebSocketResource(${name}) connected`, debugInfo);
return new LibsignalWebSocketResource(
chatService,
IpVersion.fromDebugInfoCode(debugInfo.ipType)
);
} catch (error) {
// Handle any errors that occur during connection
log.error(
`LibsignalWebSocketResource(${name}) connection failed`,
Errors.toLogFormat(error)
);
throw error;
}
};
return new AbortableProcess<LibsignalWebSocketResource>(
`LibsignalWebSocketResource.connect(${name})`,
{
abort() {
// if interrupted, trying to disconnect
drop(chatService.disconnect());
},
},
connectAsync()
);
}
export class LibsignalWebSocketResource export class LibsignalWebSocketResource
extends EventTarget extends EventTarget
implements IWebSocketResource implements IWebSocketResource
@ -277,40 +435,6 @@ export class LibsignalWebSocketResource
super(); super();
} }
public static connect(
libsignalNet: Net.Net,
name: string
): AbortableProcess<LibsignalWebSocketResource> {
const chatService = libsignalNet.newChatService();
const connectAsync = async () => {
try {
const debugInfo = await chatService.connectUnauthenticated();
log.info(`LibsignalWebSocketResource(${name}) connected`, debugInfo);
return new LibsignalWebSocketResource(
chatService,
IpVersion.fromDebugInfoCode(debugInfo.ipType)
);
} catch (error) {
// Handle any errors that occur during connection
log.error(
`LibsignalWebSocketResource(${name}) connection failed`,
Errors.toLogFormat(error)
);
throw error;
}
};
return new AbortableProcess<LibsignalWebSocketResource>(
`LibsignalWebSocketResource.connect(${name})`,
{
abort() {
// if interrupted, trying to disconnect
drop(chatService.disconnect());
},
},
connectAsync()
);
}
public localPort(): number | undefined { public localPort(): number | undefined {
return undefined; return undefined;
} }
@ -348,14 +472,13 @@ export class LibsignalWebSocketResource
public async sendRequestGetDebugInfo( public async sendRequestGetDebugInfo(
options: SendRequestOptions options: SendRequestOptions
): Promise<[Response, ChatServiceDebugInfo]> { ): Promise<[Response, ChatServiceDebugInfo]> {
const { response, debugInfo } = const { response, debugInfo } = await this.chatService.fetchAndDebug({
await this.chatService.unauthenticatedFetchAndDebug({ verb: options.verb,
verb: options.verb, path: options.path,
path: options.path, headers: options.headers ? options.headers : [],
headers: options.headers ? options.headers : [], body: options.body,
body: options.body, timeoutMillis: options.timeout,
timeoutMillis: options.timeout, });
});
return [ return [
new Response(response.body, { new Response(response.body, {
status: response.status, status: response.status,
@ -765,7 +888,7 @@ export default class WebSocketResource
this.options.handleRequest || this.options.handleRequest ||
(request => request.respond(404, 'Not found')); (request => request.respond(404, 'Not found'));
const incomingRequest = new IncomingWebSocketRequest( const incomingRequest = new IncomingWebSocketRequestLegacy(
message.request, message.request,
(bytes: Buffer): void => { (bytes: Buffer): void => {
this.removeActive(incomingRequest); this.removeActive(incomingRequest);