Skip to content

Commit 9079e0f

Browse files
Phillip CloudLucioFranco
authored andcommitted
fix(codec): Properly decode partial DATA frames (#83)
1 parent 5d0a795 commit 9079e0f

2 files changed

Lines changed: 45 additions & 10 deletions

File tree

tonic/src/codec/decode.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ impl<T> Streaming<T> {
187187
}
188188

189189
if let State::ReadBody { len, .. } = &self.state {
190-
if buf.remaining() < *len {
190+
// if we haven't read enough of the message then return and keep
191+
// reading
192+
if buf.remaining() < *len || self.buf.len() < *len + 5 {
191193
return Ok(None);
192194
}
193195

tonic/src/codec/tests.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ struct Msg {
2323
async fn decode() {
2424
let decoder = ProstDecoder::<Msg>::default();
2525

26-
let data = Vec::from(&[0u8; 1024][..]);
26+
let data = vec![0u8; 10000];
27+
let data_len = data.len();
2728
let msg = Msg { data };
2829

2930
let mut buf = BytesMut::new();
@@ -34,11 +35,20 @@ async fn decode() {
3435
buf.put_u32_be(len as u32);
3536
msg.encode(&mut buf).unwrap();
3637

37-
let body = MockBody(buf.freeze(), 0, 100);
38+
let body = MockBody {
39+
data: buf.freeze(),
40+
partial_len: 10005,
41+
count: 0,
42+
};
3843

3944
let mut stream = Streaming::new_request(decoder, body);
4045

41-
while let Some(_) = stream.message().await.unwrap() {}
46+
let mut i = 0usize;
47+
while let Some(msg) = stream.message().await.unwrap() {
48+
assert_eq!(msg.data.len(), data_len);
49+
i += 1;
50+
}
51+
assert_eq!(i, 1);
4252
}
4353

4454
#[tokio::test]
@@ -61,20 +71,43 @@ async fn encode() {
6171
}
6272

6373
#[derive(Debug)]
64-
struct MockBody(Bytes, usize, usize);
74+
struct MockBody {
75+
data: Bytes,
76+
77+
// the size of the partial message to send
78+
partial_len: usize,
79+
80+
// the number of times we've sent
81+
count: usize,
82+
}
6583

6684
impl Body for MockBody {
6785
type Data = Data;
6886
type Error = Status;
6987

7088
fn poll_data(
7189
mut self: Pin<&mut Self>,
72-
_cx: &mut Context<'_>,
90+
cx: &mut Context<'_>,
7391
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
74-
if self.1 > self.2 {
75-
self.1 += 1;
76-
let data = Data(self.0.clone().into_buf());
77-
Poll::Ready(Some(Ok(data)))
92+
// every other call to poll_data returns data
93+
let should_send = self.count % 2 == 0;
94+
let data_len = self.data.len();
95+
let partial_len = self.partial_len;
96+
let count = self.count;
97+
if data_len > 0 {
98+
let result = if should_send {
99+
let response = self
100+
.data
101+
.split_to(if count == 0 { partial_len } else { data_len })
102+
.into_buf();
103+
Poll::Ready(Some(Ok(Data(response))))
104+
} else {
105+
cx.waker().wake_by_ref();
106+
Poll::Pending
107+
};
108+
// make some fake progress
109+
self.count += 1;
110+
result
78111
} else {
79112
Poll::Ready(None)
80113
}

0 commit comments

Comments
 (0)