1use crate::error::{Error, Result};
2use crate::action::Action;
3use crate::packages::{Channel, Package, BoardArch, TargetArch};
4
5use std::collections::HashSet;
6use std::marker::PhantomData;
7use std::result::Result as StdResult;
8
9use tokio::fs::File;
10use tokio::io::{AsyncReadExt, AsyncSeekExt, SeekFrom};
11
12use stream_api::{IntoMessage, FromMessage};
13use stream_api::message::{
14 Message, IntoMessage, FromMessage, PacketBytes
15};
16use stream_api::error::MessageError;
17use stream_api::request::Request;
18
19use serde::{Serialize, Deserialize};
20
21use crypto::signature::Signature;
22use crypto::hash::{Hasher, Hash};
23use crypto::token::Token;
24
25use bytes::{BytesRead, BytesReadRef, BytesWrite};
26
27pub type DeviceId = Token<32>;
30
31#[derive(Debug, Clone, Default, Serialize, Deserialize,
53 IntoMessage, FromMessage)]
54#[message(json)]
55pub struct EmptyJson;
56
57
58#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
62#[serde(rename_all = "camelCase")]
63#[message(json)]
64pub struct PackageInfoReq {
65 pub channel: Channel,
66 pub arch: BoardArch,
67 pub name: String,
68 pub device_id: Option<DeviceId>
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
74#[serde(rename_all = "camelCase")]
75#[message(json)]
76pub struct PackageInfo {
77 pub package: Option<Package>
79}
80
81impl Request for PackageInfoReq {
82 type Action = Action;
83 type Response = PackageInfo;
84 type Error = Error;
85
86 const ACTION: Action = Action::PackageInfo;
87}
88
89
90#[derive(Debug, Clone, Serialize, Deserialize, IntoMessage, FromMessage)]
92#[serde(rename_all = "camelCase")]
93#[message(json)]
94pub struct SetPackageInfoReq {
95 pub package: Package,
96 pub whitelist: HashSet<DeviceId>,
98 #[serde(default)]
99 pub auto_whitelist_limit: u32
100}
101
102impl Request for SetPackageInfoReq {
103 type Action = Action;
104 type Response = EmptyJson;
105 type Error = Error;
106
107 const ACTION: Action = Action::SetPackageInfo;
108}
109
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
115#[serde(rename_all = "camelCase")]
116pub struct GetFileReq<B> {
117 pub hash: Hash,
118 #[serde(skip)]
119 _bytes: PhantomData<B>
120}
121
122impl<B> GetFileReq<B> {
123 pub fn new(hash: Hash) -> Self {
124 Self {
125 hash,
126 _bytes: PhantomData
127 }
128 }
129}
130
131impl<B> IntoMessage<Action, B> for GetFileReq<B>
132where B: PacketBytes {
133 fn into_message(self) -> StdResult<Message<Action, B>, MessageError> {
134 stream_api::encdec::json::encode(self)
135 }
136}
137
138impl<B> FromMessage<Action, B> for GetFileReq<B>
139where B: PacketBytes {
140 fn from_message(msg: Message<Action, B>) -> StdResult<Self, MessageError> {
141 stream_api::encdec::json::decode(msg)
142 }
143}
144
145#[derive(Debug)]
146pub struct GetFile<B> {
147 inner: Message<Action, B>
149}
150
151impl<B> GetFile<B>
152where B: PacketBytes {
153 pub async fn from_file(mut file: File) -> Result<Self> {
155 let mut msg = Message::new();
156
157 let buf_size = file.metadata().await
159 .map(|m| m.len() as usize + 1)
160 .unwrap_or(0);
161
162 let mut body = msg.body_mut();
163 body.reserve(buf_size);
164
165 unsafe {
166 let v = body.as_mut_vec();
168 file.read_to_end(v).await
169 .map_err(|e| Error::Other(
170 format!("could not read file {}", e)
171 ))?;
172 }
173
174 Ok(Self { inner: msg })
175 }
176
177 pub fn empty() -> Self {
178 Self { inner: Message::new() }
179 }
180
181 pub fn is_empty(&self) -> bool {
182 self.inner.body().len() == 0
183 }
184
185 pub fn file(&self) -> &[u8] {
186 self.inner.body().inner()
187 }
188
189 pub fn hash(&self) -> Hash {
191 Hasher::hash(self.file())
192 }
193}
194
195impl<B> IntoMessage<Action, B> for GetFile<B>
196where B: PacketBytes {
197 fn into_message(self) -> StdResult<Message<Action, B>, MessageError> {
198 Ok(self.inner)
199 }
200}
201
202impl<B> FromMessage<Action, B> for GetFile<B>
203where B: PacketBytes {
204 fn from_message(msg: Message<Action, B>) -> StdResult<Self, MessageError> {
205 Ok(Self { inner: msg })
206 }
207}
208
209impl<B> Request for GetFileReq<B> {
210 type Action = Action;
211 type Response = GetFile<B>;
212 type Error = Error;
213
214 const ACTION: Action = Action::GetFile;
215}
216
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
222#[serde(rename_all = "camelCase")]
223pub struct GetFilePartReq<B> {
224 pub hash: Hash,
225 pub start: u64,
226 pub len: u64,
229 #[serde(skip)]
230 _bytes: PhantomData<B>
231}
232
233impl<B> GetFilePartReq<B> {
234 pub fn new(hash: Hash, start: u64, len: u64) -> Self {
235 Self {
236 hash, start, len,
237 _bytes: PhantomData
238 }
239 }
240}
241
242impl<B> IntoMessage<Action, B> for GetFilePartReq<B>
243where B: PacketBytes {
244 fn into_message(self) -> StdResult<Message<Action, B>, MessageError> {
245 stream_api::encdec::json::encode(self)
246 }
247}
248
249impl<B> FromMessage<Action, B> for GetFilePartReq<B>
250where B: PacketBytes {
251 fn from_message(msg: Message<Action, B>) -> StdResult<Self, MessageError> {
252 stream_api::encdec::json::decode(msg)
253 }
254}
255
256#[derive(Debug)]
257pub struct GetFilePart<B> {
258 inner: Message<Action, B>
267}
268
269impl<B> GetFilePart<B>
270where B: PacketBytes {
271 fn new(msg: Message<Action, B>) -> Result<Self> {
272 if msg.body().len() < 8 {
274 return Err(Error::Request(
275 "GetFilePart expects at least 8bytes".into()
276 ))
277 }
278
279 Ok(Self { inner: msg })
280 }
281
282 pub async fn from_file(
284 mut file: File,
285 start: u64,
286 len: u64
287 ) -> Result<Self> {
288 let mut msg = Message::new();
289
290 let total_file_len = file.metadata().await
291 .map_err(|e| Error::Internal(e.to_string()))?
292 .len();
293
294 let rem_max_len = total_file_len.checked_sub(start)
296 .ok_or(Error::StartUnreachable)?;
297
298 let len = len.min(rem_max_len);
299
300 let mut body = msg.body_mut();
301 body.reserve((8 + len + 1) as usize);
302 body.write_u64(total_file_len);
303
304 if len == 0 {
305 return Ok(Self { inner: msg })
306 }
307
308 file.seek(SeekFrom::Start(start)).await
309 .map_err(|e| Error::Internal(
310 format!("seeking file failed {}", e)
311 ))?;
312
313 let mut file_reader = file.take(len);
315
316 unsafe {
317 let v = body.as_mut_vec();
319 file_reader.read_to_end(v).await
320 .map_err(|e| Error::Internal(
321 format!("could not read file {}", e)
322 ))?;
323 }
324
325 Ok(Self { inner: msg })
326 }
327
328 pub fn total_file_len(&self) -> u64 {
329 let mut body = self.inner.body();
330 body.read_u64()
331 }
332
333 pub fn file_part(&self) -> &[u8] {
334 let mut body = self.inner.body();
335 let _ = body.read_u64();
336 body.remaining_ref()
337 }
338}
339
340impl<B> IntoMessage<Action, B> for GetFilePart<B>
341where B: PacketBytes {
342 fn into_message(self) -> StdResult<Message<Action, B>, MessageError> {
343 Ok(self.inner)
344 }
345}
346
347impl<B> FromMessage<Action, B> for GetFilePart<B>
348where B: PacketBytes {
349 fn from_message(msg: Message<Action, B>) -> StdResult<Self, MessageError> {
350 Self::new(msg).map_err(|e| MessageError::Other(e.to_string().into()))
351 }
352}
353
354impl<B> Request for GetFilePartReq<B> {
355 type Action = Action;
356 type Response = GetFilePart<B>;
357 type Error = Error;
358
359 const ACTION: Action = Action::GetFilePart;
360}
361
362#[derive(Debug, Clone)]
363pub struct GetFileBuilder {
364 hash: Hash,
365 total_len: Option<u64>,
366 bytes: Vec<u8>,
367 part_size: u64
369}
370
371impl GetFileBuilder {
372 pub fn new(hash: Hash, part_size: u64) -> Self {
374 Self {
375 hash, part_size,
376 total_len: None,
377 bytes: vec![]
378 }
379 }
380
381 #[doc(hidden)]
382 pub fn next_req<B>(&self) -> GetFilePartReq<B> {
383 GetFilePartReq::new(
384 self.hash.clone(),
385 self.bytes.len() as u64,
387 self.part_size
389 )
390 }
391
392 #[doc(hidden)]
393 pub fn add_resp<B>(&mut self, resp: GetFilePart<B>)
394 where B: PacketBytes {
395 self.total_len = Some(resp.total_file_len());
396 self.bytes.extend_from_slice(resp.file_part());
397 }
398
399 pub fn is_complete(&self) -> bool {
400 self.total_len.map(|l| self.bytes.len() as u64 >= l)
401 .unwrap_or(false)
402 }
403
404 pub fn file(&self) -> &[u8] {
406 &self.bytes
407 }
408
409 pub fn hash(&self) -> Hash {
411 Hasher::hash(self.file())
412 }
413}
414
415
416#[derive(Debug)]
420pub struct SetFileReq<B> {
421 signature: Signature,
422 message: Message<Action, B>
424}
425
426impl<B> SetFileReq<B>
427where
428 B: PacketBytes
429{
430 pub async fn new(sign: Signature, mut file: File) -> Result<Self> {
431 let mut msg = Message::new();
432
433 let buf_size = file.metadata().await
435 .map(|m| m.len() as usize + 1)
436 .unwrap_or(0);
437
438 let mut body = msg.body_mut();
439 body.reserve(buf_size + Signature::LEN);
440
441 body.write(sign.to_bytes());
442
443 unsafe {
444 let v = body.as_mut_vec();
446 file.read_to_end(v).await
447 .map_err(|e| Error::Other(
448 format!("could not read file {}", e)
449 ))?;
450 }
451
452 Ok(Self {
453 signature: sign,
454 message: msg
455 })
456 }
457
458 pub fn from_bytes(sign: Signature, ctn: &[u8]) -> Self {
459 let mut msg = Message::new();
460
461 let mut body = msg.body_mut();
462 body.write(sign.to_bytes());
463 body.write(ctn);
464
465 Self {
466 signature: sign,
467 message: msg
468 }
469 }
470
471 pub fn signature(&self) -> &Signature {
472 &self.signature
473 }
474
475 pub fn hash(&self) -> Hash {
477 Hasher::hash(self.file())
478 }
479
480 pub fn file(&self) -> &[u8] {
481 let body = self.message.body();
482 &body.inner()[Signature::LEN..]
483 }
484}
485
486impl<B> IntoMessage<Action, B> for SetFileReq<B>
487where
488 B: PacketBytes
489{
490 fn into_message(self) -> StdResult<Message<Action, B>, MessageError> {
491 Ok(self.message)
492 }
493}
494
495impl<B> FromMessage<Action, B> for SetFileReq<B>
496where
497 B: PacketBytes
498{
499 fn from_message(msg: Message<Action, B>) -> StdResult<Self, MessageError> {
500 if msg.body().len() <= Signature::LEN {
501 return Err(MessageError::Other("no signature".into()))
502 }
503
504 let sign = Signature::from_slice(
505 msg.body().read(Signature::LEN)
506 );
507
508 Ok(Self {
509 signature: sign,
510 message: msg
511 })
512 }
513}
514
515impl<B> Request for SetFileReq<B> {
516 type Action = Action;
517 type Response = EmptyJson;
518 type Error = Error;
519
520 const ACTION: Action = Action::SetFile;
521}
522
523
524pub type AuthKey = Token<32>;
525
526#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
527#[message(json)]
528pub struct AuthenticateReaderReq {
529 pub key: AuthKey
530}
531
532impl Request for AuthenticateReaderReq {
533 type Action = Action;
534 type Response = EmptyJson;
535 type Error = Error;
536
537 const ACTION: Action = Action::AuthenticateReader;
538}
539
540
541#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
542#[message(json)]
543pub struct AuthenticateWriter1Req {
544 pub channel: Channel
545}
546
547pub type Challenge = Token<32>;
548
549#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
550#[message(json)]
551pub struct AuthenticateWriter1 {
552 pub challenge: Challenge
553}
554
555impl Request for AuthenticateWriter1Req {
556 type Action = Action;
557 type Response = AuthenticateWriter1;
558 type Error = Error;
559
560 const ACTION: Action = Action::AuthenticateWriter1;
561}
562
563
564#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
565#[message(json)]
566pub struct AuthenticateWriter2Req {
567 pub signature: Signature
568}
569
570impl Request for AuthenticateWriter2Req {
571 type Action = Action;
572 type Response = EmptyJson;
573 type Error = Error;
574
575 const ACTION: Action = Action::AuthenticateWriter2;
576}
577
578
579#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
581#[message(json)]
582pub struct NewAuthKeyReaderReq;
583
584#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
585#[message(json)]
586#[repr(transparent)]
587pub struct NewAuthKeyReader(pub AuthKey);
588
589impl Request for NewAuthKeyReaderReq {
590 type Action = Action;
591 type Response = NewAuthKeyReader;
592 type Error = Error;
593
594 const ACTION: Action = Action::NewAuthKeyReader;
595}
596
597
598#[derive(Debug, Serialize, Deserialize, IntoMessage, FromMessage)]
602#[message(json)]
603pub struct ChangeWhitelistReq {
604 pub arch: TargetArch,
605 pub name: String,
606 pub version: Hash,
607 pub whitelist: HashSet<DeviceId>,
608 #[serde(default)]
609 pub add: bool,
610 #[serde(default)]
616 pub auto_whitelist_limit: u32
617}
618
619impl Request for ChangeWhitelistReq {
620 type Action = Action;
621 type Response = EmptyJson;
622 type Error = Error;
623
624 const ACTION: Action = Action::ChangeWhitelist;
625}