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
@ -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
@ -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>
@ -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.
```
## subtle 2.5.0
## subtle 2.6.1
```
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
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.
@ -6476,7 +6477,7 @@ express Statement of Purpose.
```
## libloading 0.8.3
## libloading 0.8.5
```
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
@ -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
@ -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
@ -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
@ -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
@ -6823,38 +6824,7 @@ DEALINGS IN THE SOFTWARE.
```
## jobserver 0.1.31
```
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
## mio 1.0.1
```
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
@ -6973,7 +6943,7 @@ DEALINGS IN THE SOFTWARE.
```
## uuid 1.8.0
## uuid 1.10.0
```
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
@ -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
@ -7116,32 +7086,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
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
@ -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
@ -7225,7 +7169,7 @@ DEALINGS IN THE SOFTWARE.
```
## object 0.32.2
## object 0.36.2
```
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
@ -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
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
@ -7666,7 +7610,7 @@ DEALINGS IN THE SOFTWARE.
```
## utf8parse 0.2.1
## utf8parse 0.2.2
```
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
@ -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>
@ -7941,7 +7885,7 @@ DEALINGS IN THE SOFTWARE.
```
## indexmap 1.9.3, indexmap 2.2.6
## indexmap 2.2.6
```
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
@ -8096,7 +8040,7 @@ DEALINGS IN THE SOFTWARE.
```
## tungstenite 0.21.0
## tungstenite 0.23.0
```
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
@ -8417,7 +8361,7 @@ DEALINGS IN THE SOFTWARE.
```
## bytes 1.6.0
## bytes 1.6.1
```
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
@ -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
@ -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
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
```
## 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
```
@ -9330,7 +9306,7 @@ DEALINGS IN THE SOFTWARE.
```
## anstyle 1.0.7
## anstyle 1.0.8
```
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
@ -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
@ -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
@ -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
@ -9786,7 +9762,7 @@ SOFTWARE.
```
## miniz_oxide 0.7.3
## miniz_oxide 0.7.4
```
MIT License
@ -9921,7 +9897,7 @@ SOFTWARE.
```
## zeroize 1.7.0
## zeroize 1.8.1
```
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
@ -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
```
@ -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
@ -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
```
@ -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
@ -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:
@ -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)
@ -10539,7 +10597,7 @@ THE SOFTWARE.
```
## strsim 0.10.0
## strsim 0.10.0, strsim 0.11.1
```
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)
@ -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)
@ -10704,7 +10762,7 @@ SOFTWARE.
```
## derive_more 0.99.17
## derive_more 0.99.18
```
The MIT License (MIT)
@ -10812,7 +10870,7 @@ THE SOFTWARE.
```
## async-compression 0.4.10
## async-compression 0.4.12
```
The MIT License (MIT)
@ -10960,7 +11018,7 @@ SOFTWARE.
```
## version_check 0.9.4
## version_check 0.9.5
```
The MIT License (MIT)

8
package-lock.json generated
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -13,14 +13,14 @@ import { AbortableProcess } from '../util/AbortableProcess';
import { strictAssert } from '../util/assert';
import {
BackOff,
FIBONACCI_TIMEOUTS,
EXTENDED_FIBONACCI_TIMEOUTS,
FIBONACCI_TIMEOUTS,
} from '../util/BackOff';
import * as durations from '../util/durations';
import { sleep } from '../util/sleep';
import { drop } from '../util/drop';
import { createProxyAgent } from '../util/createProxyAgent';
import type { ProxyAgent } from '../util/createProxyAgent';
import { createProxyAgent } from '../util/createProxyAgent';
import { SocketStatus } from '../types/SocketStatus';
import * as Errors from '../types/errors';
import * as Bytes from '../Bytes';
@ -32,7 +32,8 @@ import type {
WebSocketResourceOptions,
} from './WebsocketResources';
import WebSocketResource, {
LibsignalWebSocketResource,
connectAuthenticatedLibsignal,
connectUnauthenticatedLibsignal,
TransportOption,
WebSocketResourceWithShadowing,
} from './WebsocketResources';
@ -166,22 +167,38 @@ export class SocketManager extends EventListener {
this.setStatus(SocketStatus.CONNECTING);
const process = this.connectResource({
name: AUTHENTICATED_CHANNEL_NAME,
path: '/v1/websocket/',
query: { login: username, password },
proxyAgent: await this.getProxyAgent(),
resourceOptions: {
name: AUTHENTICATED_CHANNEL_NAME,
keepalive: { path: '/v1/keepalive' },
handleRequest: (req: IncomingWebSocketRequest): void => {
this.queueOrHandleRequest(req);
},
},
extraHeaders: {
'X-Signal-Receive-Stories': String(!this.hasStoriesDisabled),
},
});
const proxyAgent = await this.getProxyAgent();
const useLibsignalTransport =
window.Signal.RemoteConfig.isEnabled(
'desktop.experimentalTransport.enableAuth'
) && this.transportOption(proxyAgent) === TransportOption.Libsignal;
const process = useLibsignalTransport
? connectAuthenticatedLibsignal({
libsignalNet: this.libsignalNet,
name: AUTHENTICATED_CHANNEL_NAME,
credentials: this.credentials,
handler: (req: IncomingWebSocketRequest): void => {
this.queueOrHandleRequest(req);
},
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
this.authenticated?.abort();
@ -575,10 +592,10 @@ export class SocketManager extends EventListener {
}
private connectLibsignalUnauthenticated(): AbortableProcess<IWebSocketResource> {
return LibsignalWebSocketResource.connect(
this.libsignalNet,
UNAUTHENTICATED_CHANNEL_NAME
);
return connectUnauthenticatedLibsignal({
libsignalNet: this.libsignalNet,
name: UNAUTHENTICATED_CHANNEL_NAME,
});
}
private async getUnauthenticatedResource(): Promise<IWebSocketResource> {
@ -724,10 +741,10 @@ export class SocketManager extends EventListener {
options: WebSocketResourceOptions
): AbortableProcess<IWebSocketResource> {
// creating an `AbortableProcess` of libsignal websocket connection
const shadowingConnection = LibsignalWebSocketResource.connect(
this.libsignalNet,
options.name
);
const shadowingConnection = connectUnauthenticatedLibsignal({
libsignalNet: this.libsignalNet,
name: options.name,
});
const shadowWrapper = async () => {
// if main connection results in an error,
// 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 { 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 EventTarget from './EventTarget';
@ -54,6 +56,7 @@ import { isProduction } from '../util/version';
import { ToastType } from '../types/Toast';
import { AbortableProcess } from '../util/AbortableProcess';
import type { WebAPICredentials } from './Types';
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;
public readonly verb: string;
public readonly path: string;
public readonly requestType: ServerRequestType;
public readonly body: Uint8Array | undefined;
public readonly headers: ReadonlyArray<string>;
public readonly timestamp: number | undefined;
constructor(
request: Proto.IWebSocketRequestMessage,
@ -186,10 +222,9 @@ export class IncomingWebSocketRequest {
strictAssert(request.path, 'request without path');
this.id = request.id;
this.verb = request.verb;
this.path = request.path;
this.requestType = resolveType(request.path, request.verb);
this.body = dropNull(request.body);
this.headers = request.headers || [];
this.timestamp = resolveTimestamp(request.headers || []);
}
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<{
verb: string;
path: string;
@ -266,6 +330,100 @@ export interface IWebSocketResource extends IResource {
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
extends EventTarget
implements IWebSocketResource
@ -277,40 +435,6 @@ export class LibsignalWebSocketResource
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 {
return undefined;
}
@ -348,14 +472,13 @@ export class LibsignalWebSocketResource
public async sendRequestGetDebugInfo(
options: SendRequestOptions
): Promise<[Response, ChatServiceDebugInfo]> {
const { response, debugInfo } =
await this.chatService.unauthenticatedFetchAndDebug({
verb: options.verb,
path: options.path,
headers: options.headers ? options.headers : [],
body: options.body,
timeoutMillis: options.timeout,
});
const { response, debugInfo } = await this.chatService.fetchAndDebug({
verb: options.verb,
path: options.path,
headers: options.headers ? options.headers : [],
body: options.body,
timeoutMillis: options.timeout,
});
return [
new Response(response.body, {
status: response.status,
@ -765,7 +888,7 @@ export default class WebSocketResource
this.options.handleRequest ||
(request => request.respond(404, 'Not found'));
const incomingRequest = new IncomingWebSocketRequest(
const incomingRequest = new IncomingWebSocketRequestLegacy(
message.request,
(bytes: Buffer): void => {
this.removeActive(incomingRequest);