Skip to content

Commit b6b14c7

Browse files
authored
Merge pull request #28 from trevarj/jade-serial-fix
bhwi-cli(jade): fix serial transport reading
2 parents 141f094 + f2ac0e7 commit b6b14c7

3 files changed

Lines changed: 49 additions & 41 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
1+
use async_trait::async_trait;
12
pub use bhwi::jade::JADE_DEVICE_IDS;
3+
use serde_cbor::Value;
24

35
#[cfg(feature = "emulators")]
46
pub mod tcp;
7+
8+
#[async_trait(?Send)]
9+
pub trait CborStream {
10+
async fn write_all(&mut self, command: &[u8]) -> Result<(), std::io::Error>;
11+
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error>;
12+
13+
/// Reads from the client until a complete CBOR value is received.
14+
async fn read_cbor_message(&mut self) -> Result<Vec<u8>, std::io::Error> {
15+
let mut buf = Vec::new();
16+
let mut chunk = [0u8; 1024];
17+
18+
loop {
19+
let n = self.read(&mut chunk).await?;
20+
if n == 0 {
21+
return Err(std::io::Error::other(
22+
"stream ended before complete CBOR message",
23+
));
24+
}
25+
buf.extend_from_slice(&chunk[..n]);
26+
let mut cursor = std::io::Cursor::new(&buf);
27+
match serde_cbor::from_reader::<Value, _>(&mut cursor) {
28+
Ok(_) => return Ok(buf),
29+
Err(e) if e.is_io() || e.is_eof() => continue,
30+
Err(e) => return Err(std::io::Error::other(e)),
31+
}
32+
}
33+
}
34+
}
Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use async_trait::async_trait;
2-
use serde_cbor::Value;
32

4-
use crate::Transport;
3+
use crate::{Transport, transport::jade::CborStream};
54

65
pub struct TcpTransport<C> {
76
pub client: C,
@@ -14,38 +13,11 @@ impl<C> TcpTransport<C> {
1413
}
1514

1615
#[async_trait(?Send)]
17-
pub trait TcpClient {
18-
async fn write_all(&mut self, command: &[u8]) -> Result<(), std::io::Error>;
19-
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error>;
20-
}
21-
22-
#[async_trait(?Send)]
23-
impl<C: TcpClient> Transport for TcpTransport<C> {
16+
impl<C: CborStream> Transport for TcpTransport<C> {
2417
type Error = std::io::Error;
2518

2619
async fn exchange(&mut self, command: &[u8], _encrypted: bool) -> Result<Vec<u8>, Self::Error> {
2720
self.client.write_all(command).await?;
28-
29-
let mut buf = Vec::new();
30-
let mut temp = [0u8; 1024];
31-
32-
// HACK: i don't know a better way right now!
33-
loop {
34-
let n = self.client.read(&mut temp).await?;
35-
// XXX: what happens when n is 0?
36-
buf.extend_from_slice(&temp[..n]);
37-
let mut cursor = std::io::Cursor::new(&buf);
38-
match serde_cbor::from_reader::<Value, _>(&mut cursor) {
39-
Ok(_) => {
40-
return Ok(buf);
41-
}
42-
Err(e) if e.is_io() => {
43-
continue; // read more bytes
44-
}
45-
Err(e) => {
46-
return Err(std::io::Error::other(e));
47-
}
48-
}
49-
}
21+
self.client.read_cbor_message().await
5022
}
5123
}

bhwi-cli/src/jade.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ use anyhow::Result;
44
use async_trait::async_trait;
55
use bhwi_async::{
66
HttpClient, Jade, Transport,
7-
transport::jade::{
8-
JADE_DEVICE_IDS,
9-
tcp::{TcpClient as TcpClientTrait, TcpTransport},
10-
},
7+
transport::jade::{CborStream, JADE_DEVICE_IDS, tcp::TcpTransport},
118
};
129
use bitcoin::Network;
1310
use futures::{TryStreamExt, stream::iter};
@@ -51,11 +48,20 @@ impl SerialTransport {
5148
impl Transport for SerialTransport {
5249
type Error = std::io::Error;
5350
async fn exchange(&mut self, command: &[u8], _encrypted: bool) -> Result<Vec<u8>, Self::Error> {
51+
self.write_all(command).await?;
52+
self.read_cbor_message().await
53+
}
54+
}
55+
56+
#[async_trait(?Send)]
57+
impl CborStream for SerialTransport {
58+
async fn write_all(&mut self, command: &[u8]) -> Result<(), std::io::Error> {
59+
let mut stream = self.stream.lock().await;
60+
Ok(stream.write_all(command).await?)
61+
}
62+
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
5463
let mut stream = self.stream.lock().await;
55-
stream.write_all(command).await?;
56-
let mut buf = vec![];
57-
stream.read_to_end(&mut buf).await?;
58-
Ok(buf)
64+
Ok(stream.read(buf).await?)
5965
}
6066
}
6167

@@ -153,7 +159,7 @@ impl HttpClient for PinServerClient {
153159
Ok(self
154160
.inner
155161
.post(url)
156-
.header("Content-Type", "application/octet-stream")
162+
.header("Content-Type", "application/json")
157163
.body(request.to_vec())
158164
.send()
159165
.await?
@@ -174,7 +180,7 @@ impl TcpClient {
174180
}
175181

176182
#[async_trait(?Send)]
177-
impl TcpClientTrait for TcpClient {
183+
impl CborStream for TcpClient {
178184
async fn write_all(&mut self, command: &[u8]) -> Result<(), std::io::Error> {
179185
Ok(self.stream.write_all(command).await?)
180186
}

0 commit comments

Comments
 (0)