Skip to content

Commit

Permalink
Switch to attachments v4 (#330)
Browse files Browse the repository at this point in the history
* Modify Endpoint enum to allow absolute URLs (necessary for CDN2)
* Implement all kinds of attachments v4
* Add fmt::Display for Endpoint
  • Loading branch information
gferon authored Oct 20, 2024
1 parent 72f89cd commit 9540bc0
Show file tree
Hide file tree
Showing 15 changed files with 482 additions and 117 deletions.
12 changes: 4 additions & 8 deletions src/account_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ impl AccountManager {
.service
.request(
Method::GET,
Endpoint::Service,
"/v1/devices/provisioning/code",
Endpoint::service("/v1/devices/provisioning/code"),
HttpAuthOverride::NoOverride,
)?
.send()
Expand Down Expand Up @@ -254,8 +253,7 @@ impl AccountManager {
self.service
.request(
Method::PUT,
Endpoint::Service,
format!("/v1/provisioning/{}", destination),
Endpoint::service(format!("/v1/provisioning/{destination}")),
HttpAuthOverride::NoOverride,
)?
.json(&ProvisioningMessage {
Expand Down Expand Up @@ -594,8 +592,7 @@ impl AccountManager {
self.service
.request(
Method::PUT,
Endpoint::Service,
"/v1/accounts/name",
Endpoint::service("/v1/accounts/name"),
HttpAuthOverride::NoOverride,
)?
.json(&Data {
Expand Down Expand Up @@ -623,8 +620,7 @@ impl AccountManager {
self.service
.request(
Method::PUT,
Endpoint::Service,
"/v1/challenge",
Endpoint::service("/v1/challenge"),
HttpAuthOverride::NoOverride,
)?
.json(&RecaptchaAttributes {
Expand Down
110 changes: 93 additions & 17 deletions src/configuration.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt;
use std::{collections::HashMap, str::FromStr};
use std::{borrow::Cow, collections::HashMap, str::FromStr};

use crate::utils::BASE64_RELAXED;
use base64::prelude::*;
Expand Down Expand Up @@ -74,11 +74,96 @@ pub enum SignalServers {
}

#[derive(Debug)]
pub enum Endpoint {
Service,
Storage,
Cdn(u32),
ContactDiscovery,
pub enum Endpoint<'a> {
Absolute(Url),
Service {
path: Cow<'a, str>,
},
Storage {
path: Cow<'a, str>,
},
Cdn {
cdn_id: u32,
path: Cow<'a, str>,
query: Option<Cow<'a, str>>,
},
ContactDiscovery {
path: Cow<'a, str>,
},
}

impl fmt::Display for Endpoint<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Endpoint::Absolute(url) => write!(f, "absolute URL {url}"),
Endpoint::Service { path } => {
write!(f, "service API call to {path}")
},
Endpoint::Storage { path } => {
write!(f, "storage API call to {path}")
},
Endpoint::Cdn { cdn_id, path, .. } => {
write!(f, "CDN{cdn_id} call to {path}")
},
Endpoint::ContactDiscovery { path } => {
write!(f, "Contact discovery API call to {path}")
},
}
}
}

impl<'a> Endpoint<'a> {
pub fn service(path: impl Into<Cow<'a, str>>) -> Self {
Self::Service { path: path.into() }
}

pub fn cdn(cdn_id: u32, path: impl Into<Cow<'a, str>>) -> Self {
Self::Cdn {
cdn_id,
path: path.into(),
query: None,
}
}

pub fn cdn_url(cdn_id: u32, url: &'a Url) -> Self {
Self::Cdn {
cdn_id,
path: url.path().into(),
query: url.query().map(Into::into),
}
}

pub fn storage(path: impl Into<Cow<'a, str>>) -> Self {
Self::Storage { path: path.into() }
}

pub fn into_url(
self,
service_configuration: &ServiceConfiguration,
) -> Result<Url, url::ParseError> {
match self {
Endpoint::Service { path } => {
service_configuration.service_url.join(&path)
},
Endpoint::Storage { path } => {
service_configuration.storage_url.join(&path)
},
Endpoint::Cdn {
ref cdn_id,
path,
query,
} => {
let mut url = service_configuration.cdn_urls[cdn_id].clone();
url.set_path(&path);
url.set_query(query.as_deref());
Ok(url)
},
Endpoint::ContactDiscovery { path } => {
service_configuration.contact_discovery_url.join(&path)
},
Endpoint::Absolute(url) => Ok(url),
}
}
}

impl FromStr for SignalServers {
Expand Down Expand Up @@ -125,6 +210,7 @@ impl From<&SignalServers> for ServiceConfiguration {
let mut map = HashMap::new();
map.insert(0, "https://cdn-staging.signal.org".parse().unwrap());
map.insert(2, "https://cdn2-staging.signal.org".parse().unwrap());
map.insert(3, "https://cdn3-staging.signal.org".parse().unwrap());
map
},
contact_discovery_url:
Expand All @@ -144,6 +230,7 @@ impl From<&SignalServers> for ServiceConfiguration {
let mut map = HashMap::new();
map.insert(0, "https://cdn.signal.org".parse().unwrap());
map.insert(2, "https://cdn2.signal.org".parse().unwrap());
map.insert(3, "https://cdn3.signal.org".parse().unwrap());
map
},
contact_discovery_url: "https://api.directory.signal.org".parse().unwrap(),
Expand All @@ -156,14 +243,3 @@ impl From<&SignalServers> for ServiceConfiguration {
}
}
}

impl ServiceConfiguration {
pub fn base_url(&self, endpoint: Endpoint) -> &Url {
match endpoint {
Endpoint::Service => &self.service_url,
Endpoint::Storage => &self.storage_url,
Endpoint::Cdn(ref n) => &self.cdn_urls[n],
Endpoint::ContactDiscovery => &self.contact_discovery_url,
}
}
}
10 changes: 7 additions & 3 deletions src/digeststream.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::io::Read;
use std::io::{self, Read, Seek, SeekFrom};

use sha2::{Digest, Sha256};

Expand All @@ -7,22 +7,26 @@ pub struct DigestingReader<'r, R> {
digest: Sha256,
}

impl<'r, R: Read> Read for DigestingReader<'r, R> {
impl<'r, R: Read + Seek> Read for DigestingReader<'r, R> {
fn read(&mut self, tgt: &mut [u8]) -> Result<usize, std::io::Error> {
let amount = self.inner.read(tgt)?;
self.digest.update(&tgt[..amount]);
Ok(amount)
}
}

impl<'r, R: Read> DigestingReader<'r, R> {
impl<'r, R: Read + Seek> DigestingReader<'r, R> {
pub fn new(inner: &'r mut R) -> Self {
Self {
inner,
digest: Sha256::new(),
}
}

pub fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
self.inner.seek(from)
}

pub fn finalize(self) -> Vec<u8> {
// XXX representation is not ideal, but this leaks to the public interface and I don't
// really like exposing the GenericArray.
Expand Down
3 changes: 1 addition & 2 deletions src/groups_v2/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ impl<C: CredentialsCache> GroupsManager<C> {
.push_service
.request(
Method::GET,
Endpoint::Service,
&path,
Endpoint::service(path),
HttpAuthOverride::NoOverride,
)?
.send()
Expand Down
3 changes: 1 addition & 2 deletions src/profile_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ impl ProfileService {
self.push_service
.request(
Method::GET,
Endpoint::Service,
path,
Endpoint::service(path),
HttpAuthOverride::NoOverride,
)?
.send()
Expand Down
9 changes: 3 additions & 6 deletions src/push_service/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ impl PushService {
pub async fn whoami(&mut self) -> Result<WhoAmIResponse, ServiceError> {
self.request(
Method::GET,
Endpoint::Service,
"/v1/accounts/whoami",
Endpoint::service("/v1/accounts/whoami"),
HttpAuthOverride::NoOverride,
)?
.send()
Expand All @@ -157,8 +156,7 @@ impl PushService {
let devices: DeviceInfoList = self
.request(
Method::GET,
Endpoint::Service,
"/v1/devices/",
Endpoint::service("/v1/devices/"),
HttpAuthOverride::NoOverride,
)?
.send()
Expand All @@ -182,8 +180,7 @@ impl PushService {

self.request(
Method::PUT,
Endpoint::Service,
"/v1/accounts/attributes/",
Endpoint::service("/v1/accounts/attributes/"),
HttpAuthOverride::NoOverride,
)?
.json(&attributes)
Expand Down
Loading

0 comments on commit 9540bc0

Please sign in to comment.