1 use super::compression::{decompress, CompressionEncoding, CompressionSettings}; 2 use super::{BufferSettings, DecodeBuf, Decoder, DEFAULT_MAX_RECV_MESSAGE_SIZE, HEADER_SIZE}; 3 use crate::{body::Body, metadata::MetadataMap, Code, Status}; 4 use bytes::{Buf, BufMut, BytesMut}; 5 use http::{HeaderMap, StatusCode}; 6 use http_body::Body as HttpBody; 7 use http_body_util::BodyExt; 8 use std::{ 9 fmt, future, 10 pin::Pin, 11 task::ready, 12 task::{Context, Poll}, 13 }; 14 use tokio_stream::Stream; 15 use tracing::{debug, trace}; 16 17 /// Streaming requests and responses. 18 /// 19 /// This will wrap some inner [`Body`] and [`Decoder`] and provide an interface 20 /// to fetch the message stream and trailing metadata 21 pub struct Streaming<T> { 22 decoder: Box<dyn Decoder<Item = T, Error = Status> + Send + 'static>, 23 inner: StreamingInner, 24 } 25 26 struct StreamingInner { 27 body: Body, 28 state: State, 29 direction: Direction, 30 buf: BytesMut, 31 trailers: Option<HeaderMap>, 32 decompress_buf: BytesMut, 33 encoding: Option<CompressionEncoding>, 34 max_message_size: Option<usize>, 35 } 36 37 impl<T> Unpin for Streaming<T> {} 38 39 #[derive(Debug, Clone)] 40 enum State { 41 ReadHeader, 42 ReadBody { 43 compression: Option<CompressionEncoding>, 44 len: usize, 45 }, 46 Error(Option<Status>), 47 } 48 49 #[derive(Debug, PartialEq, Eq)] 50 enum Direction { 51 Request, 52 Response(StatusCode), 53 EmptyResponse, 54 } 55 56 impl<T> Streaming<T> { 57 /// Create a new streaming response in the grpc response format for decoding a response [Body] 58 /// into message of type T new_response<B, D>( decoder: D, body: B, status_code: StatusCode, encoding: Option<CompressionEncoding>, max_message_size: Option<usize>, ) -> Self where B: HttpBody + Send + 'static, B::Error: Into<crate::BoxError>, D: Decoder<Item = T, Error = Status> + Send + 'static,59 pub fn new_response<B, D>( 60 decoder: D, 61 body: B, 62 status_code: StatusCode, 63 encoding: Option<CompressionEncoding>, 64 max_message_size: Option<usize>, 65 ) -> Self 66 where 67 B: HttpBody + Send + 'static, 68 B::Error: Into<crate::BoxError>, 69 D: Decoder<Item = T, Error = Status> + Send + 'static, 70 { 71 Self::new( 72 decoder, 73 body, 74 Direction::Response(status_code), 75 encoding, 76 max_message_size, 77 ) 78 } 79 80 /// Create empty response. For creating responses that have no content (headers + trailers only) new_empty<B, D>(decoder: D, body: B) -> Self where B: HttpBody + Send + 'static, B::Error: Into<crate::BoxError>, D: Decoder<Item = T, Error = Status> + Send + 'static,81 pub fn new_empty<B, D>(decoder: D, body: B) -> Self 82 where 83 B: HttpBody + Send + 'static, 84 B::Error: Into<crate::BoxError>, 85 D: Decoder<Item = T, Error = Status> + Send + 'static, 86 { 87 Self::new(decoder, body, Direction::EmptyResponse, None, None) 88 } 89 90 /// Create a new streaming request in the grpc response format for decoding a request [Body] 91 /// into message of type T new_request<B, D>( decoder: D, body: B, encoding: Option<CompressionEncoding>, max_message_size: Option<usize>, ) -> Self where B: HttpBody + Send + 'static, B::Error: Into<crate::BoxError>, D: Decoder<Item = T, Error = Status> + Send + 'static,92 pub fn new_request<B, D>( 93 decoder: D, 94 body: B, 95 encoding: Option<CompressionEncoding>, 96 max_message_size: Option<usize>, 97 ) -> Self 98 where 99 B: HttpBody + Send + 'static, 100 B::Error: Into<crate::BoxError>, 101 D: Decoder<Item = T, Error = Status> + Send + 'static, 102 { 103 Self::new( 104 decoder, 105 body, 106 Direction::Request, 107 encoding, 108 max_message_size, 109 ) 110 } 111 new<B, D>( decoder: D, body: B, direction: Direction, encoding: Option<CompressionEncoding>, max_message_size: Option<usize>, ) -> Self where B: HttpBody + Send + 'static, B::Error: Into<crate::BoxError>, D: Decoder<Item = T, Error = Status> + Send + 'static,112 fn new<B, D>( 113 decoder: D, 114 body: B, 115 direction: Direction, 116 encoding: Option<CompressionEncoding>, 117 max_message_size: Option<usize>, 118 ) -> Self 119 where 120 B: HttpBody + Send + 'static, 121 B::Error: Into<crate::BoxError>, 122 D: Decoder<Item = T, Error = Status> + Send + 'static, 123 { 124 let buffer_size = decoder.buffer_settings().buffer_size; 125 Self { 126 decoder: Box::new(decoder), 127 inner: StreamingInner { 128 body: Body::new( 129 body.map_frame(|frame| { 130 frame.map_data(|mut buf| buf.copy_to_bytes(buf.remaining())) 131 }) 132 .map_err(|err| Status::map_error(err.into())), 133 ), 134 state: State::ReadHeader, 135 direction, 136 buf: BytesMut::with_capacity(buffer_size), 137 trailers: None, 138 decompress_buf: BytesMut::new(), 139 encoding, 140 max_message_size, 141 }, 142 } 143 } 144 } 145 146 impl StreamingInner { decode_chunk( &mut self, buffer_settings: BufferSettings, ) -> Result<Option<DecodeBuf<'_>>, Status>147 fn decode_chunk( 148 &mut self, 149 buffer_settings: BufferSettings, 150 ) -> Result<Option<DecodeBuf<'_>>, Status> { 151 if let State::ReadHeader = self.state { 152 if self.buf.remaining() < HEADER_SIZE { 153 return Ok(None); 154 } 155 156 let compression_encoding = match self.buf.get_u8() { 157 0 => None, 158 1 => { 159 { 160 if self.encoding.is_some() { 161 self.encoding 162 } else { 163 // https://grpc.github.io/grpc/core/md_doc_compression.html 164 // An ill-constructed message with its Compressed-Flag bit set but lacking a grpc-encoding 165 // entry different from identity in its metadata MUST fail with INTERNAL status, 166 // its associated description indicating the invalid Compressed-Flag condition. 167 return Err(Status::internal( "protocol error: received message with compressed-flag but no grpc-encoding was specified")); 168 } 169 } 170 } 171 f => { 172 trace!("unexpected compression flag"); 173 let message = if let Direction::Response(status) = self.direction { 174 format!( 175 "protocol error: received message with invalid compression flag: {} (valid flags are 0 and 1) while receiving response with status: {}", 176 f, status 177 ) 178 } else { 179 format!("protocol error: received message with invalid compression flag: {} (valid flags are 0 and 1), while sending request", f) 180 }; 181 return Err(Status::internal(message)); 182 } 183 }; 184 185 let len = self.buf.get_u32() as usize; 186 let limit = self 187 .max_message_size 188 .unwrap_or(DEFAULT_MAX_RECV_MESSAGE_SIZE); 189 if len > limit { 190 return Err(Status::out_of_range( 191 format!( 192 "Error, decoded message length too large: found {} bytes, the limit is: {} bytes", 193 len, limit 194 ), 195 )); 196 } 197 198 self.buf.reserve(len); 199 200 self.state = State::ReadBody { 201 compression: compression_encoding, 202 len, 203 } 204 } 205 206 if let State::ReadBody { len, compression } = self.state { 207 // if we haven't read enough of the message then return and keep 208 // reading 209 if self.buf.remaining() < len || self.buf.len() < len { 210 return Ok(None); 211 } 212 213 let decode_buf = if let Some(encoding) = compression { 214 self.decompress_buf.clear(); 215 216 if let Err(err) = decompress( 217 CompressionSettings { 218 encoding, 219 buffer_growth_interval: buffer_settings.buffer_size, 220 }, 221 &mut self.buf, 222 &mut self.decompress_buf, 223 len, 224 ) { 225 let message = if let Direction::Response(status) = self.direction { 226 format!( 227 "Error decompressing: {}, while receiving response with status: {}", 228 err, status 229 ) 230 } else { 231 format!("Error decompressing: {}, while sending request", err) 232 }; 233 return Err(Status::internal(message)); 234 } 235 let decompressed_len = self.decompress_buf.len(); 236 DecodeBuf::new(&mut self.decompress_buf, decompressed_len) 237 } else { 238 DecodeBuf::new(&mut self.buf, len) 239 }; 240 241 return Ok(Some(decode_buf)); 242 } 243 244 Ok(None) 245 } 246 247 // Returns Some(()) if data was found or None if the loop in `poll_next` should break poll_frame(&mut self, cx: &mut Context<'_>) -> Poll<Result<Option<()>, Status>>248 fn poll_frame(&mut self, cx: &mut Context<'_>) -> Poll<Result<Option<()>, Status>> { 249 let frame = match ready!(Pin::new(&mut self.body).poll_frame(cx)) { 250 Some(Ok(frame)) => frame, 251 Some(Err(status)) => { 252 if self.direction == Direction::Request && status.code() == Code::Cancelled { 253 return Poll::Ready(Ok(None)); 254 } 255 256 let _ = std::mem::replace(&mut self.state, State::Error(Some(status.clone()))); 257 debug!("decoder inner stream error: {:?}", status); 258 return Poll::Ready(Err(status)); 259 } 260 None => { 261 // FIXME: improve buf usage. 262 return Poll::Ready(if self.buf.has_remaining() { 263 trace!("unexpected EOF decoding stream, state: {:?}", self.state); 264 Err(Status::internal("Unexpected EOF decoding stream.")) 265 } else { 266 Ok(None) 267 }); 268 } 269 }; 270 271 Poll::Ready(if frame.is_data() { 272 self.buf.put(frame.into_data().unwrap()); 273 Ok(Some(())) 274 } else if frame.is_trailers() { 275 if let Some(trailers) = &mut self.trailers { 276 trailers.extend(frame.into_trailers().unwrap()); 277 } else { 278 self.trailers = Some(frame.into_trailers().unwrap()); 279 } 280 281 Ok(None) 282 } else { 283 panic!("unexpected frame: {:?}", frame); 284 }) 285 } 286 response(&mut self) -> Result<(), Status>287 fn response(&mut self) -> Result<(), Status> { 288 if let Direction::Response(status) = self.direction { 289 if let Err(Some(e)) = crate::status::infer_grpc_status(self.trailers.as_ref(), status) { 290 // If the trailers contain a grpc-status, then we should return that as the error 291 // and otherwise stop the stream (by taking the error state) 292 self.trailers.take(); 293 return Err(e); 294 } 295 } 296 Ok(()) 297 } 298 } 299 300 impl<T> Streaming<T> { 301 /// Fetch the next message from this stream. 302 /// 303 /// # Return value 304 /// 305 /// - `Result::Err(val)` means a gRPC error was sent by the sender instead 306 /// of a valid response message. Refer to [`Status::code`] and 307 /// [`Status::message`] to examine possible error causes. 308 /// 309 /// - `Result::Ok(None)` means the stream was closed by the sender and no 310 /// more messages will be delivered. Further attempts to call 311 /// [`Streaming::message`] will result in the same return value. 312 /// 313 /// - `Result::Ok(Some(val))` means the sender streamed a valid response 314 /// message `val`. 315 /// 316 /// ```rust 317 /// # use tonic::{Streaming, Status, codec::Decoder}; 318 /// # use std::fmt::Debug; 319 /// # async fn next_message_ex<T, D>(mut request: Streaming<T>) -> Result<(), Status> 320 /// # where T: Debug, 321 /// # D: Decoder<Item = T, Error = Status> + Send + 'static, 322 /// # { 323 /// if let Some(next_message) = request.message().await? { 324 /// println!("{:?}", next_message); 325 /// } 326 /// # Ok(()) 327 /// # } 328 /// ``` message(&mut self) -> Result<Option<T>, Status>329 pub async fn message(&mut self) -> Result<Option<T>, Status> { 330 match future::poll_fn(|cx| Pin::new(&mut *self).poll_next(cx)).await { 331 Some(Ok(m)) => Ok(Some(m)), 332 Some(Err(e)) => Err(e), 333 None => Ok(None), 334 } 335 } 336 337 /// Fetch the trailing metadata. 338 /// 339 /// This will drain the stream of all its messages to receive the trailing 340 /// metadata. If [`Streaming::message`] returns `None` then this function 341 /// will not need to poll for trailers since the body was totally consumed. 342 /// 343 /// ```rust 344 /// # use tonic::{Streaming, Status}; 345 /// # async fn trailers_ex<T>(mut request: Streaming<T>) -> Result<(), Status> { 346 /// if let Some(metadata) = request.trailers().await? { 347 /// println!("{:?}", metadata); 348 /// } 349 /// # Ok(()) 350 /// # } 351 /// ``` trailers(&mut self) -> Result<Option<MetadataMap>, Status>352 pub async fn trailers(&mut self) -> Result<Option<MetadataMap>, Status> { 353 // Shortcut to see if we already pulled the trailers in the stream step 354 // we need to do that so that the stream can error on trailing grpc-status 355 if let Some(trailers) = self.inner.trailers.take() { 356 return Ok(Some(MetadataMap::from_headers(trailers))); 357 } 358 359 // To fetch the trailers we must clear the body and drop it. 360 while self.message().await?.is_some() {} 361 362 // Since we call poll_trailers internally on poll_next we need to 363 // check if it got cached again. 364 if let Some(trailers) = self.inner.trailers.take() { 365 return Ok(Some(MetadataMap::from_headers(trailers))); 366 } 367 368 // We've polled through all the frames, and still no trailers, return None 369 Ok(None) 370 } 371 decode_chunk(&mut self) -> Result<Option<T>, Status>372 fn decode_chunk(&mut self) -> Result<Option<T>, Status> { 373 match self.inner.decode_chunk(self.decoder.buffer_settings())? { 374 Some(mut decode_buf) => match self.decoder.decode(&mut decode_buf)? { 375 Some(msg) => { 376 self.inner.state = State::ReadHeader; 377 Ok(Some(msg)) 378 } 379 None => Ok(None), 380 }, 381 None => Ok(None), 382 } 383 } 384 } 385 386 impl<T> Stream for Streaming<T> { 387 type Item = Result<T, Status>; 388 poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>389 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { 390 loop { 391 // When the stream encounters an error yield that error once and then on subsequent 392 // calls to poll_next return Poll::Ready(None) indicating that the stream has been 393 // fully exhausted. 394 if let State::Error(status) = &mut self.inner.state { 395 return Poll::Ready(status.take().map(Err)); 396 } 397 398 if let Some(item) = self.decode_chunk()? { 399 return Poll::Ready(Some(Ok(item))); 400 } 401 402 if ready!(self.inner.poll_frame(cx))?.is_none() { 403 break; 404 } 405 } 406 407 Poll::Ready(match self.inner.response() { 408 Ok(()) => None, 409 Err(err) => Some(Err(err)), 410 }) 411 } 412 } 413 414 impl<T> fmt::Debug for Streaming<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result415 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 416 f.debug_struct("Streaming").finish() 417 } 418 } 419 420 #[cfg(test)] 421 static_assertions::assert_impl_all!(Streaming<()>: Send); 422