Skip to content

Commit a673ad9

Browse files
authored
Migrate PushService methods to the emulated HTTP request/response inside of the websocket (#366)
1 parent abad163 commit a673ad9

26 files changed

+537
-520
lines changed

src/account_manager.rs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,37 @@ use crate::proto::sync_message::PniChangeNumber;
3030
use crate::proto::{DeviceName, SyncMessage};
3131
use crate::provisioning::generate_registration_id;
3232
use crate::push_service::{
33-
AvatarWrite, CaptchaAttributes, DeviceActivationRequest, DeviceInfo,
34-
HttpAuthOverride, RegistrationMethod, ReqwestExt, VerifyAccountResponse,
35-
DEFAULT_DEVICE_ID,
33+
AvatarWrite, HttpAuthOverride, ReqwestExt, DEFAULT_DEVICE_ID,
3634
};
3735
use crate::sender::OutgoingPushMessage;
3836
use crate::service_address::ServiceIdExt;
3937
use crate::session_store::SessionStoreExt;
4038
use crate::timestamp::TimestampExt as _;
4139
use crate::utils::{random_length_padding, BASE64_RELAXED};
40+
use crate::websocket::account::DeviceInfo;
41+
use crate::websocket::keys::PreKeyStatus;
42+
use crate::websocket::registration::{
43+
CaptchaAttributes, DeviceActivationRequest, RegistrationMethod,
44+
VerifyAccountResponse,
45+
};
46+
use crate::websocket::{self, SignalWebSocket};
4247
use crate::{
4348
configuration::{Endpoint, ServiceCredentials},
4449
pre_keys::PreKeyState,
4550
profile_cipher::{ProfileCipher, ProfileCipherError},
4651
profile_name::ProfileName,
4752
proto::{ProvisionEnvelope, ProvisionMessage, ProvisioningVersion},
4853
provisioning::{ProvisioningCipher, ProvisioningError},
49-
push_service::{AccountAttributes, PushService, ServiceError},
54+
push_service::{PushService, ServiceError},
5055
utils::serde_base64,
56+
websocket::account::AccountAttributes,
5157
};
5258

5359
type Aes256Ctr128BE = ctr::Ctr128BE<aes::Aes256>;
5460

5561
pub struct AccountManager {
5662
service: PushService,
63+
websocket: SignalWebSocket<websocket::Identified>,
5764
profile_key: Option<ProfileKey>,
5865
}
5966

@@ -75,9 +82,14 @@ pub struct Profile {
7582
}
7683

7784
impl AccountManager {
78-
pub fn new(service: PushService, profile_key: Option<ProfileKey>) -> Self {
85+
pub fn new(
86+
service: PushService,
87+
websocket: SignalWebSocket<websocket::Identified>,
88+
profile_key: Option<ProfileKey>,
89+
) -> Self {
7990
Self {
8091
service,
92+
websocket,
8193
profile_key,
8294
}
8395
}
@@ -122,7 +134,7 @@ impl AccountManager {
122134
hash.update((u32::from(kyber_prekey_id) as u64).to_be_bytes());
123135
hash.update(kyber_prekey.public_key()?.serialize());
124136

125-
self.service
137+
self.websocket
126138
.check_pre_keys(service_id_kind, hash.finalize().as_ref())
127139
.await
128140
}
@@ -134,16 +146,15 @@ impl AccountManager {
134146
///
135147
/// Equivalent to Java's RefreshPreKeysJob
136148
#[allow(clippy::too_many_arguments)]
137-
#[tracing::instrument(skip(self, csprng, protocol_store))]
138-
pub async fn update_pre_key_bundle<R: Rng + CryptoRng, P: PreKeysStore>(
149+
#[tracing::instrument(skip(self, protocol_store))]
150+
pub async fn update_pre_key_bundle<P: PreKeysStore>(
139151
&mut self,
140152
protocol_store: &mut P,
141153
service_id_kind: ServiceIdKind,
142154
use_last_resort_key: bool,
143-
csprng: &mut R,
144155
) -> Result<(), ServiceError> {
145156
let prekey_status = match self
146-
.service
157+
.websocket
147158
.get_pre_key_status(service_id_kind)
148159
.instrument(tracing::span!(
149160
tracing::Level::DEBUG,
@@ -156,7 +167,7 @@ impl AccountManager {
156167
tracing::info!("Got Unauthorized when fetching pre-key status. Assuming first installment.");
157168
// Additionally, the second PUT request will fail if this really comes down to an
158169
// authorization failure.
159-
crate::push_service::PreKeyStatus {
170+
PreKeyStatus {
160171
count: 0,
161172
pq_count: 0,
162173
}
@@ -218,7 +229,7 @@ impl AccountManager {
218229
let (pre_keys, signed_pre_key, pq_pre_keys, pq_last_resort_key) =
219230
crate::pre_keys::replenish_pre_keys(
220231
protocol_store,
221-
csprng,
232+
&mut rand::rng(),
222233
&identity_key_pair,
223234
use_last_resort_key && !has_last_resort_key,
224235
PRE_KEY_BATCH_SIZE,
@@ -266,7 +277,7 @@ impl AccountManager {
266277
pq_last_resort_key,
267278
};
268279

269-
self.service
280+
self.websocket
270281
.register_pre_keys(service_id_kind, pre_key_state)
271282
.instrument(tracing::span!(
272283
tracing::Level::DEBUG,
@@ -425,7 +436,7 @@ impl AccountManager {
425436
&mut self,
426437
aci_identity_store: &dyn IdentityKeyStore,
427438
) -> Result<Vec<DeviceInfo>, ServiceError> {
428-
let device_infos = self.service.devices().await?;
439+
let device_infos = self.websocket.devices().await?;
429440
let aci_identity_keypair =
430441
aci_identity_store.get_identity_key_pair().await?;
431442

@@ -520,7 +531,7 @@ impl AccountManager {
520531
};
521532

522533
let result = self
523-
.service
534+
.websocket
524535
.submit_registration_request(
525536
registration_method,
526537
account_attributes,
@@ -580,7 +591,7 @@ impl AccountManager {
580591
self.profile_key.expect("set profile key in AccountManager");
581592

582593
let encrypted_profile = self
583-
.service
594+
.websocket
584595
.retrieve_profile_by_id(address, Some(profile_key))
585596
.await?;
586597

@@ -630,7 +641,7 @@ impl AccountManager {
630641
let profile_key_version = profile_key.get_profile_key_version(aci);
631642

632643
Ok(self
633-
.service
644+
.websocket
634645
.write_profile::<C, S>(
635646
&profile_key_version,
636647
&name,
@@ -649,7 +660,7 @@ impl AccountManager {
649660
&mut self,
650661
attributes: AccountAttributes,
651662
) -> Result<(), ServiceError> {
652-
self.service.set_account_attributes(attributes).await
663+
self.websocket.set_account_attributes(attributes).await
653664
}
654665

655666
/// Update (encrypted) device name
@@ -910,7 +921,7 @@ impl AccountManager {
910921
device_messages.push(msg);
911922
}
912923

913-
self.service
924+
self.websocket
914925
.distribute_pni_keys(
915926
pni_identity_key,
916927
device_messages,
@@ -925,7 +936,6 @@ impl AccountManager {
925936
}
926937
}
927938

928-
#[expect(clippy::result_large_err)]
929939
fn calculate_hmac256(
930940
mac_key: &[u8],
931941
ciphertext: &[u8],
@@ -936,7 +946,6 @@ fn calculate_hmac256(
936946
Ok(mac.finalize().into_bytes())
937947
}
938948

939-
#[expect(clippy::result_large_err)]
940949
pub fn encrypt_device_name<R: rand::Rng + rand::CryptoRng>(
941950
csprng: &mut R,
942951
device_name: &str,
@@ -973,7 +982,6 @@ pub fn encrypt_device_name<R: rand::Rng + rand::CryptoRng>(
973982
Ok(device_name)
974983
}
975984

976-
#[expect(clippy::result_large_err)]
977985
fn decrypt_device_name_from_device_info(
978986
string: &str,
979987
aci: &IdentityKeyPair,
@@ -983,7 +991,6 @@ fn decrypt_device_name_from_device_info(
983991
crate::decrypt_device_name(aci.private_key(), &name)
984992
}
985993

986-
#[expect(clippy::result_large_err)]
987994
pub fn decrypt_device_name(
988995
private_key: &PrivateKey,
989996
device_name: &DeviceName,

src/cipher.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ struct Plaintext {
457457
data: Vec<u8>,
458458
}
459459

460-
#[expect(clippy::comparison_chain, clippy::result_large_err)]
460+
#[expect(clippy::comparison_chain)]
461461
fn add_padding(version: u32, contents: &[u8]) -> Result<Vec<u8>, ServiceError> {
462462
if version < 2 {
463463
Err(ServiceError::PaddingVersion(version))
@@ -480,7 +480,7 @@ fn add_padding(version: u32, contents: &[u8]) -> Result<Vec<u8>, ServiceError> {
480480
}
481481
}
482482

483-
#[expect(clippy::comparison_chain, clippy::result_large_err)]
483+
#[expect(clippy::comparison_chain)]
484484
fn strip_padding_version(
485485
version: u32,
486486
contents: &mut Vec<u8>,
@@ -497,7 +497,6 @@ fn strip_padding_version(
497497
}
498498
}
499499

500-
#[expect(clippy::result_large_err)]
501500
fn strip_padding(contents: &mut Vec<u8>) -> Result<(), ServiceError> {
502501
let new_length = Iso7816::raw_unpad(contents)?.len();
503502
contents.resize(new_length, 0);

src/content.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ impl Content {
7272
}
7373

7474
/// Converts a proto::Content into a public Content, including metadata.
75-
#[expect(clippy::result_large_err)]
7675
pub fn from_proto(
7776
p: crate::proto::Content,
7877
metadata: Metadata,

src/envelope.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::{configuration::SignalingKey, push_service::ServiceError};
88
pub use crate::proto::Envelope;
99

1010
impl Envelope {
11-
#[expect(clippy::result_large_err)]
1211
#[tracing::instrument(skip(input, signaling_key), fields(signaling_key_present = signaling_key.is_some(), input_size = input.len()))]
1312
pub fn decrypt(
1413
input: &[u8],

src/groups_v2/manager.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
proto::GroupContextV2,
1111
push_service::{HttpAuth, HttpAuthOverride, ReqwestExt, ServiceIds},
1212
utils::BASE64_RELAXED,
13+
websocket::{self, SignalWebSocket},
1314
};
1415

1516
use base64::prelude::*;
@@ -38,7 +39,6 @@ pub struct CredentialResponse {
3839
credentials: Vec<TemporalCredential>,
3940
}
4041

41-
#[expect(clippy::result_large_err)]
4242
impl CredentialResponse {
4343
pub fn parse(
4444
self,
@@ -133,21 +133,24 @@ impl<T: CredentialsCache> CredentialsCache for &mut T {
133133

134134
pub struct GroupsManager<C: CredentialsCache> {
135135
service_ids: ServiceIds,
136-
push_service: PushService,
136+
identified_push_service: PushService,
137+
unidentified_websocket: SignalWebSocket<websocket::Unidentified>,
137138
credentials_cache: C,
138139
server_public_params: ServerPublicParams,
139140
}
140141

141142
impl<C: CredentialsCache> GroupsManager<C> {
142143
pub fn new(
143144
service_ids: ServiceIds,
144-
push_service: PushService,
145+
identified_push_service: PushService,
146+
unidentified_websocket: SignalWebSocket<websocket::Unidentified>,
145147
credentials_cache: C,
146148
server_public_params: ServerPublicParams,
147149
) -> Self {
148150
Self {
149151
service_ids,
150-
push_service,
152+
identified_push_service,
153+
unidentified_websocket,
151154
credentials_cache,
152155
server_public_params,
153156
}
@@ -169,7 +172,7 @@ impl<C: CredentialsCache> GroupsManager<C> {
169172
format!("/v1/certificate/auth/group?redemptionStartSeconds={}&redemptionEndSeconds={}&pniAsServiceId=true", today, today_plus_7_days);
170173

171174
let credentials_response: CredentialResponse = self
172-
.push_service
175+
.identified_push_service
173176
.request(
174177
Method::GET,
175178
Endpoint::service(path),
@@ -199,7 +202,6 @@ impl<C: CredentialsCache> GroupsManager<C> {
199202
)
200203
}
201204

202-
#[expect(clippy::result_large_err)]
203205
fn get_authorization_string<R: Rng + CryptoRng>(
204206
&self,
205207
csprng: &mut R,
@@ -257,7 +259,7 @@ impl<C: CredentialsCache> GroupsManager<C> {
257259
let authorization = self
258260
.get_authorization_for_today(csprng, group_secret_params)
259261
.await?;
260-
self.push_service.get_group(authorization).await
262+
self.identified_push_service.get_group(authorization).await
261263
}
262264

263265
#[tracing::instrument(
@@ -270,7 +272,7 @@ impl<C: CredentialsCache> GroupsManager<C> {
270272
group_secret_params: GroupSecretParams,
271273
) -> Result<Option<Vec<u8>>, ServiceError> {
272274
let mut encrypted_avatar = self
273-
.push_service
275+
.unidentified_websocket
274276
.retrieve_groups_v2_profile_avatar(path)
275277
.await?;
276278
let mut result = Vec::with_capacity(10 * 1024 * 1024);
@@ -301,7 +303,6 @@ impl<C: CredentialsCache> GroupsManager<C> {
301303
}
302304
}
303305

304-
#[expect(clippy::result_large_err)]
305306
pub fn decrypt_group(
306307
master_key_bytes: &[u8],
307308
encrypted_group: crate::proto::Group,

src/messagepipe.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ pub use crate::{
1414
},
1515
};
1616

17-
use crate::{push_service::ServiceError, websocket::SignalWebSocket};
17+
use crate::{
18+
push_service::ServiceError,
19+
websocket::{self, SignalWebSocket},
20+
};
1821

1922
#[derive(Debug)]
2023
pub enum Incoming {
@@ -23,20 +26,20 @@ pub enum Incoming {
2326
}
2427

2528
pub struct MessagePipe {
26-
ws: SignalWebSocket,
29+
ws: SignalWebSocket<websocket::Identified>,
2730
credentials: ServiceCredentials,
2831
}
2932

3033
impl MessagePipe {
3134
pub fn from_socket(
32-
ws: SignalWebSocket,
35+
ws: SignalWebSocket<websocket::Identified>,
3336
credentials: ServiceCredentials,
3437
) -> Self {
3538
MessagePipe { ws, credentials }
3639
}
3740

3841
/// Return a SignalWebSocket for sending messages and other purposes beyond receiving messages.
39-
pub fn ws(&self) -> SignalWebSocket {
42+
pub fn ws(&self) -> SignalWebSocket<websocket::Identified> {
4043
self.ws.clone()
4144
}
4245

src/profile_cipher.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use rand::{rand_core, CryptoRng, RngCore};
55
use zkgroup::profiles::ProfileKey;
66

77
use crate::{
8-
profile_name::ProfileName, push_service::SignalServiceProfile, Profile,
8+
profile_name::ProfileName, websocket::profile::SignalServiceProfile,
9+
Profile,
910
};
1011

1112
/// Encrypt and decrypt a [`ProfileName`] and other profile information.

src/proto.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(clippy::all)]
22

33
use rand::{CryptoRng, Rng};
4+
use reqwest::StatusCode;
45
include!(concat!(env!("OUT_DIR"), "/signalservice.rs"));
56
include!(concat!(env!("OUT_DIR"), "/signal.rs"));
67

@@ -66,6 +67,10 @@ impl WebSocketResponseMessage {
6667
}
6768
}
6869
}
70+
71+
pub fn status_code(&self) -> Option<reqwest::StatusCode> {
72+
StatusCode::from_u16(self.status().try_into().ok()?).ok()
73+
}
6974
}
7075

7176
impl SyncMessage {

0 commit comments

Comments
 (0)