iron_os_packages_api/
client.rs1use crate::action::Action;
2use crate::error::{Result, Error};
3use crate::packages::{Channel, Package, BoardArch, TargetArch};
4use crate::requests::{
5 PackageInfoReq, DeviceId,
6 SetPackageInfoReq,
7 GetFileReq, GetFile,
8 GetFileBuilder,
9 SetFileReq,
10 AuthKey, AuthenticateReaderReq,
11 AuthenticateWriter1Req, AuthenticateWriter2Req,
12 NewAuthKeyReaderReq,
13 ChangeWhitelistReq
14};
15
16use std::time::Duration;
17use std::collections::HashSet;
18
19use stream_api::client::{Config, Client as StreamClient, EncryptedBytes};
20
21use crypto::signature::{PublicKey, Keypair};
22use crypto::hash::Hash;
23
24use tokio::net::{TcpStream, ToSocketAddrs};
25
26const TIMEOUT: Duration = Duration::from_secs(10);
27
28
29pub struct Client {
30 inner: StreamClient<Action, EncryptedBytes>
31}
32
33impl Client {
34 pub async fn connect<A>(addr: A, pub_key: PublicKey) -> Result<Self>
35 where A: ToSocketAddrs {
36 let stream = TcpStream::connect(addr).await
37 .map_err(|e| Error::Other(format!("could not connect {}", e)))?;
38 Ok(Self {
39 inner: StreamClient::<_, EncryptedBytes>::new_encrypted(
40 stream,
41 Config {
42 timeout: TIMEOUT,
43 body_limit: 0
44 },
45 None,
46 pub_key
47 )
48 })
49 }
50
51 pub async fn package_info(
53 &self,
54 channel: Channel,
55 arch: BoardArch,
56 device_id: Option<DeviceId>,
57 name: String
58 ) -> Result<Option<Package>> {
59 let req = PackageInfoReq { channel, arch, name, device_id };
60 self.inner.request(req).await
61 .map(|r| r.package)
62 }
63
64 pub async fn set_package_info(
66 &self,
67 package: Package,
68 whitelist: HashSet<DeviceId>,
69 auto_whitelist_limit: u32
70 ) -> Result<()> {
71 let req = SetPackageInfoReq {
72 package, whitelist, auto_whitelist_limit
73 };
74 self.inner.request(req).await
75 .map(|_r| ())
76 }
77
78 pub async fn get_file(
81 &self,
82 hash: Hash
83 ) -> Result<GetFile<EncryptedBytes>> {
84 let req = GetFileReq::new(hash);
85 self.inner.request(req).await
86 }
87
88 pub async fn get_file_with_builder(
94 &self,
95 builder: &mut GetFileBuilder
96 ) -> Result<()> {
97 let r = builder.next_req();
98 let resp = self.inner.request(r).await?;
99 builder.add_resp(resp);
100
101 Ok(())
102 }
103
104 pub async fn set_file(
106 &self,
107 req: SetFileReq<EncryptedBytes>
108 ) -> Result<()> {
109 self.inner.request(req).await
110 .map(|_| ())
111 }
112
113 pub async fn authenticate_reader(&self, key: AuthKey) -> Result<()> {
115 self.inner.request(AuthenticateReaderReq { key }).await
116 .map(|_| ())
117 }
118
119 pub async fn authenticate_writer(
121 &self,
122 channel: &Channel,
123 key: &Keypair
124 ) -> Result<()> {
125 let resp = self.inner.request(AuthenticateWriter1Req {
126 channel: *channel
127 }).await?;
128 self.inner.request(AuthenticateWriter2Req {
129 signature: key.sign(&resp.challenge)
130 }).await
131 .map(|_| ())
132 }
133
134 pub async fn new_auth_key_reader(&self) -> Result<AuthKey> {
136 self.inner.request(NewAuthKeyReaderReq).await
137 .map(|r| r.0)
138 }
139
140 pub async fn change_whitelist(
146 &self,
147 arch: TargetArch,
148 name: String,
149 version: Hash,
150 whitelist: HashSet<DeviceId>,
151 add: bool,
153 auto_whitelist_limit: u32
154 ) -> Result<()> {
155 self.inner.request(ChangeWhitelistReq {
156 arch, name, version, whitelist, add,
157 auto_whitelist_limit
158 }).await
159 .map(|_| ())
160 }
161
162 pub async fn close(self) {
163 let _ = self.inner.close().await;
164 }
165}