1use std::{
3 cell::{Cell, RefCell},
4 collections::{BTreeMap, BTreeSet, VecDeque},
5 io,
6 panic::{AssertUnwindSafe, catch_unwind},
7 rc::Rc,
8 time::{Duration, Instant},
9};
10
11use grpc_core::{
12 Codec, Metadata, Request, Response, Status,
13 compression::CompressionAlgorithm,
14 session::{GrpcServerSession, IncomingRequest, SessionConfig},
15 transport::SyncTransport,
16};
17
18use crate::stream::{RequestStream, ResponseSink, StreamDriver, StreamError, server_streams};
19
20fn normalized_content_type(value: &str) -> &str {
21 if value == "application/grpc+proto" {
22 "application/grpc"
23 } else {
24 value
25 }
26}
27fn io_status(error: io::Error) -> Status {
28 Status::unavailable(error.to_string())
29}
30fn stream_status(error: StreamError) -> Status {
31 match error {
32 StreamError::Status(status) => status,
33 StreamError::WouldBlock => Status::internal("blocking stream operation remained pending"),
34 }
35}
36struct ServerInner<T> {
37 session: GrpcServerSession,
38 transport: T,
39 buffer: Vec<u8>,
40 pending_incoming: VecDeque<(Instant, IncomingRequest)>,
41 pending_reap: BTreeSet<i32>,
42 reset_reap: BTreeSet<i32>,
43 closed: bool,
44 draining: bool,
45}
46impl<T: SyncTransport> ServerInner<T> {
47 fn drive(&mut self, blocking: bool, deadline: Option<Instant>) -> Result<usize, Status> {
48 let remaining = |deadline: Option<Instant>| -> Result<Option<Duration>, Status> {
49 let timeout = deadline.map(|at| at.saturating_duration_since(Instant::now()));
50 if timeout.is_some_and(|duration| duration.is_zero()) {
51 Err(Status::deadline_exceeded("request deadline elapsed"))
52 } else {
53 Ok(timeout)
54 }
55 };
56 remaining(deadline)?;
57 self.transport.set_nonblocking(true).map_err(io_status)?;
58 self.flush()?;
59 let mut result = loop {
60 match self.transport.read(&mut self.buffer) {
61 Err(error) if error.kind() == io::ErrorKind::Interrupted => {
62 remaining(deadline)?;
63 }
64 result => break result,
65 }
66 };
67 if blocking && matches!(&result, Err(error) if error.kind() == io::ErrorKind::WouldBlock) {
68 self.transport.set_nonblocking(false).map_err(io_status)?;
69 let waited = (|| -> Result<_, Status> {
70 loop {
71 let mut timeout = remaining(deadline)?;
72 if self.session.want_write() || !self.pending_reap.is_empty() {
73 let quantum = Duration::from_millis(1);
74 timeout = Some(timeout.map_or(quantum, |left| left.min(quantum)));
75 }
76 self.transport
77 .set_read_timeout(timeout)
78 .map_err(io_status)?;
79 match self.transport.read(&mut self.buffer) {
80 Err(error) if error.kind() == io::ErrorKind::Interrupted => continue,
81 result => return Ok(result),
82 }
83 }
84 })();
85 self.transport.set_nonblocking(true).map_err(io_status)?;
86 result = waited?;
87 }
88 let count = match result {
89 Ok(0) => {
90 remaining(deadline)?;
91 self.closed = true;
92 return Ok(0);
93 }
94 Ok(count) => count,
95 Err(error)
96 if matches!(
97 error.kind(),
98 io::ErrorKind::WouldBlock | io::ErrorKind::TimedOut
99 ) =>
100 {
101 remaining(deadline)?;
102 return Ok(0);
103 }
104 Err(error) => {
105 remaining(deadline)?;
106 return Err(io_status(error));
107 }
108 };
109 let mut offset = 0;
110 while offset < count {
111 let used = self.session.mem_recv(&self.buffer[offset..count])?;
112 if used == 0 {
113 return Err(Status::internal("HTTP/2 receive made no progress"));
114 }
115 offset += used;
116 while let Some(request) = self.session.pop_incoming_request() {
117 self.pending_incoming.push_back((Instant::now(), request));
118 }
119 }
120 self.flush()?;
121 remaining(deadline)?;
122 Ok(count)
123 }
124 fn flush(&mut self) -> Result<(), Status> {
125 self.transport.set_nonblocking(true).map_err(io_status)?;
126 self.session.flush_to_transport(&mut self.transport)?;
127 self.session.reap_closed_undispatched_streams()?;
128 let ready: Vec<_> = self
129 .pending_reap
130 .iter()
131 .copied()
132 .filter(|id| self.session.stream_outbound_complete(*id))
133 .collect();
134 for id in ready {
135 if !self.reset_reap.contains(&id) {
136 match self.session.is_remote_end_stream(id) {
137 Ok(false) => {
138 self.session.cancel_stream(id, 0)?;
139 self.reset_reap.insert(id);
140 self.session.flush_to_transport(&mut self.transport)?;
141 }
142 Ok(true) => {}
143 Err(_) => {
144 self.reset_reap.insert(id);
145 }
146 }
147 }
148 match self.session.remove_closed_stream(id) {
149 Ok(()) => {}
150 Err(error) if error.code() == grpc_core::Code::FailedPrecondition => continue,
151 Err(error) => return Err(error),
152 }
153 self.pending_reap.remove(&id);
154 self.reset_reap.remove(&id);
155 }
156 Ok(())
157 }
158}
159
160#[derive(Default)]
162pub struct PayloadCodec;
163impl Codec for PayloadCodec {
164 type EncodeItem = Vec<u8>;
165 type DecodeItem = Vec<u8>;
166 type Error = Status;
167 const CONTENT_TYPE: &'static str = "application/grpc";
168 fn encode(&mut self, item: &Vec<u8>, destination: &mut Vec<u8>) -> Result<(), Status> {
169 destination.extend_from_slice(item);
170 Ok(())
171 }
172 fn decode(&mut self, payload: &[u8]) -> Result<Vec<u8>, Status> {
173 Ok(payload.to_vec())
174 }
175}
176
177pub trait ServiceHandler {
180 fn handle(
184 &mut self,
185 requests: RequestStream<Vec<u8>>,
186 responses: &mut ResponseSink<Vec<u8>>,
187 ) -> Result<(), Status>;
188}
189impl<F> ServiceHandler for F
190where
191 F: FnMut(RequestStream<Vec<u8>>, &mut ResponseSink<Vec<u8>>) -> Result<(), Status>,
192{
193 fn handle(
194 &mut self,
195 requests: RequestStream<Vec<u8>>,
196 responses: &mut ResponseSink<Vec<u8>>,
197 ) -> Result<(), Status> {
198 self(requests, responses)
199 }
200}
201
202pub struct ServerStreamDriver<T: SyncTransport, C: Codec> {
204 inner: Rc<RefCell<ServerInner<T>>>,
205 codec: Rc<RefCell<C>>,
206 id: i32,
207 deadline: Option<Instant>,
208 initial: Metadata,
209 trailers: Option<Metadata>,
210 encoding: CompressionAlgorithm,
211 response_initial_sent: bool,
212 complete: Rc<Cell<bool>>,
213}
214impl<T: SyncTransport, C: Codec> ServerStreamDriver<T, C> {
215 fn check_deadline(&self) -> Result<(), StreamError> {
216 if !self.deadline.is_some_and(|at| Instant::now() >= at) {
217 return Ok(());
218 }
219 let status = Status::deadline_exceeded("request deadline elapsed");
220 if !self.complete.get() {
221 let mut inner = self
222 .inner
223 .try_borrow_mut()
224 .map_err(|_| Status::failed_precondition("reentrant server operation"))?;
225 inner.transport.set_nonblocking(true).map_err(io_status)?;
226 inner
227 .session
228 .finish_response(self.id, &status, &Metadata::new())?;
229 self.complete.set(true);
230 inner.pending_reap.insert(self.id);
231 inner.flush()?;
232 }
233 Err(status.into())
234 }
235}
236impl<T: SyncTransport, C: Codec> StreamDriver for ServerStreamDriver<T, C>
237where
238 C::EncodeItem: Sized,
239{
240 type Send = C::EncodeItem;
241 type Receive = C::DecodeItem;
242 fn send(&mut self, message: &Self::Send) -> Result<(), StreamError> {
243 self.check_deadline()?;
244 let mut bytes = Vec::new();
245 self.codec
246 .try_borrow_mut()
247 .map_err(|_| Status::failed_precondition("reentrant codec"))?
248 .encode(message, &mut bytes)
249 .map_err(|error| Status::internal(error.to_string()))?;
250 self.check_deadline()?;
251 let mut inner = self
252 .inner
253 .try_borrow_mut()
254 .map_err(|_| Status::failed_precondition("reentrant server operation"))?;
255 inner.transport.set_nonblocking(true).map_err(io_status)?;
256 if !self.response_initial_sent {
257 inner.session.send_initial_metadata_with_content_type(
258 self.id,
259 &Metadata::new(),
260 self.encoding,
261 C::CONTENT_TYPE,
262 )?;
263 self.response_initial_sent = true;
264 }
265 inner.session.send_message(self.id, &bytes, self.encoding)?;
266 inner.flush()?;
267 Ok(())
268 }
269 fn half_close(&mut self) -> Result<(), StreamError> {
270 Err(Status::failed_precondition("server responses close with final status").into())
271 }
272 fn try_recv_next(&mut self) -> Result<Option<Self::Receive>, StreamError> {
273 self.check_deadline()?;
274 let mut inner = self
275 .inner
276 .try_borrow_mut()
277 .map_err(|_| Status::failed_precondition("reentrant server operation"))?;
278 for attempt in 0..2 {
279 if let Some(message) = inner.session.pop_message(self.id)? {
280 drop(inner);
281 let value = self
282 .codec
283 .try_borrow_mut()
284 .map_err(|_| Status::failed_precondition("reentrant codec"))?
285 .decode(message.payload())
286 .map_err(|error| Status::invalid_argument(error.to_string()))?;
287 self.check_deadline()?;
288 return Ok(Some(value));
289 }
290 if inner.session.is_remote_end_stream(self.id)? {
291 return Ok(None);
292 }
293 if attempt == 0 {
294 inner.drive(false, self.deadline)?;
295 }
296 }
297 if inner.closed {
298 Err(Status::unavailable("transport EOF during request").into())
299 } else {
300 Err(StreamError::WouldBlock)
301 }
302 }
303 fn wait_ready(&mut self) -> Result<(), StreamError> {
304 self.check_deadline()?;
305 let mut inner = self
306 .inner
307 .try_borrow_mut()
308 .map_err(|_| Status::failed_precondition("reentrant server operation"))?;
309 inner.drive(true, self.deadline)?;
310 if inner.closed {
311 Err(Status::unavailable("transport EOF during request").into())
312 } else {
313 Ok(())
314 }
315 }
316 fn finish(&mut self, status: &Status, trailers: &Metadata) -> Result<(), StreamError> {
317 self.check_deadline()?;
318 if self.complete.get() {
319 return Err(Status::failed_precondition("response already finished").into());
320 }
321 let mut inner = self
322 .inner
323 .try_borrow_mut()
324 .map_err(|_| Status::failed_precondition("reentrant server operation"))?;
325 inner.transport.set_nonblocking(true).map_err(io_status)?;
326 inner.session.finish_response(self.id, status, trailers)?;
327 self.complete.set(true);
328 inner.pending_reap.insert(self.id);
329 self.trailers = Some(trailers.clone());
330 inner.flush()?;
331 Ok(())
332 }
333 fn initial_metadata(&self) -> Option<&Metadata> {
334 Some(&self.initial)
335 }
336 fn trailing_metadata(&self) -> Option<&Metadata> {
337 self.trailers.as_ref()
338 }
339 fn cancel(&mut self) {
340 if self.deadline.is_some_and(|at| Instant::now() >= at) {
341 match self.check_deadline() {
342 Err(_) if self.complete.get() => return,
343 Err(_) | Ok(()) => {}
344 }
345 }
346 if !self.complete.get()
347 && let Ok(mut inner) = self.inner.try_borrow_mut()
348 {
349 match inner.session.cancel_stream(self.id, 8) {
350 Ok(()) => {
351 self.complete.set(true);
352 inner.pending_reap.insert(self.id);
353 inner.reset_reap.insert(self.id);
354 }
355 Err(error)
356 if matches!(
357 error.code(),
358 grpc_core::Code::Cancelled | grpc_core::Code::FailedPrecondition
359 ) =>
360 {
361 self.complete.set(true);
362 inner.pending_reap.insert(self.id);
363 inner.reset_reap.insert(self.id);
364 }
365 Err(error) if error.code() == grpc_core::Code::NotFound => self.complete.set(true),
366 Err(_) => inner.closed = true,
367 }
368 }
369 }
370}
371
372type DriverState<T, C> = (ServerStreamDriver<T, C>, Rc<Cell<bool>>);
373
374type Route<T> = Box<dyn FnMut(IncomingRequest, Rc<RefCell<ServerInner<T>>>) -> Result<(), Status>>;
375pub struct SyncServer<T: SyncTransport> {
377 inner: Rc<RefCell<ServerInner<T>>>,
378 routes: BTreeMap<String, Route<T>>,
379}
380impl<T: SyncTransport + 'static> SyncServer<T> {
381 pub fn new(transport: T) -> Result<Self, Status> {
385 Self::with_config(transport, SessionConfig::default())
386 }
387 pub fn with_config(transport: T, config: SessionConfig) -> Result<Self, Status> {
391 Ok(Self {
392 inner: Rc::new(RefCell::new(ServerInner {
393 session: GrpcServerSession::new(config)?,
394 transport,
395 buffer: vec![0; 16 * 1024],
396 pending_incoming: VecDeque::new(),
397 pending_reap: BTreeSet::new(),
398 reset_reap: BTreeSet::new(),
399 closed: false,
400 draining: false,
401 })),
402 routes: BTreeMap::new(),
403 })
404 }
405 fn insert(&mut self, path: &str, handler: Route<T>) -> Result<(), Status> {
406 if !path.starts_with('/')
407 || path
408 .rsplit_once('/')
409 .is_none_or(|(service, method)| service.len() < 2 || method.is_empty())
410 {
411 return Err(Status::invalid_argument(
412 "RPC path must contain service and method",
413 ));
414 }
415 if self.routes.contains_key(path) {
416 return Err(Status::already_exists("RPC path is already registered"));
417 }
418 self.routes.insert(path.to_string(), handler);
419 Ok(())
420 }
421 fn streams<C: Codec>(
422 request: IncomingRequest,
423 inner: Rc<RefCell<ServerInner<T>>>,
424 codec: Rc<RefCell<C>>,
425 ) -> Result<DriverState<T, C>, Status> {
426 let content_type = request.content_type.split(';').next().unwrap_or("").trim();
427 if normalized_content_type(content_type) != normalized_content_type(C::CONTENT_TYPE) {
428 return Err(Status::unimplemented(
429 "request content type does not match registered codec",
430 ));
431 }
432 let deadline = request
433 .timeout
434 .map(|timeout| {
435 Instant::now()
436 .checked_add(timeout)
437 .ok_or_else(|| Status::invalid_argument("request deadline exceeds clock range"))
438 })
439 .transpose()?;
440 let encoding = if request
441 .accept_encoding
442 .split(',')
443 .any(|name| name.trim() == request.request_encoding.as_str())
444 {
445 request.request_encoding
446 } else {
447 CompressionAlgorithm::Identity
448 };
449 let complete = Rc::new(Cell::new(false));
450 Ok((
451 ServerStreamDriver {
452 inner,
453 codec,
454 id: request.stream_id,
455 deadline,
456 initial: request.initial_metadata,
457 trailers: None,
458 encoding,
459 response_initial_sent: false,
460 complete: Rc::clone(&complete),
461 },
462 complete,
463 ))
464 }
465 fn finalize<Resp>(
466 sink: &mut ResponseSink<Resp>,
467 complete: &Cell<bool>,
468 result: Result<(), Status>,
469 ) -> Result<(), Status> {
470 if complete.get() {
471 return Ok(());
472 }
473 let status = match result {
474 Ok(()) => Status::ok(""),
475 Err(status) => status,
476 };
477 let result = sink.finish(status, Metadata::new()).map_err(stream_status);
478 if complete.get() { Ok(()) } else { result }
479 }
480 pub fn register_unary<C, Req, Resp, F>(
484 &mut self,
485 path: &str,
486 codec: C,
487 mut handler: F,
488 ) -> Result<(), Status>
489 where
490 C: Codec<EncodeItem = Resp, DecodeItem = Req> + 'static,
491 Req: 'static,
492 Resp: 'static,
493 F: FnMut(Request<Req>) -> Result<Response<Resp>, Status> + 'static,
494 {
495 let codec = Rc::new(RefCell::new(codec));
496 self.insert(
497 path,
498 Box::new(move |request, inner| {
499 let metadata = request.initial_metadata.clone();
500 let (mut driver, complete) =
501 Self::streams(request, Rc::clone(&inner), Rc::clone(&codec))?;
502 driver.response_initial_sent = true;
503 let id = driver.id;
504 let encoding = driver.encoding;
505 let (mut requests, mut sink) = server_streams(driver);
506 let result = catch_unwind(AssertUnwindSafe(|| {
507 let value = requests
508 .recv_next()
509 .map_err(stream_status)?
510 .ok_or_else(|| Status::invalid_argument("unary request is missing"))?;
511 if requests.recv_next().map_err(stream_status)?.is_some() {
512 return Err(Status::invalid_argument(
513 "unary request has multiple messages",
514 ));
515 }
516 let response = handler(Request::from_parts(metadata, value))?;
517 let (metadata, value) = response.into_parts();
518 inner
519 .borrow_mut()
520 .session
521 .send_initial_metadata_with_content_type(
522 id,
523 &metadata,
524 encoding,
525 C::CONTENT_TYPE,
526 )?;
527 sink.send(&value).map_err(stream_status)
528 }))
529 .unwrap_or_else(|_| Err(Status::internal("service handler panicked")));
530 Self::finalize(&mut sink, &complete, result)
531 }),
532 )
533 }
534 pub fn register_server_streaming<C, Req, Resp, F>(
539 &mut self,
540 path: &str,
541 codec: C,
542 mut handler: F,
543 ) -> Result<(), Status>
544 where
545 C: Codec<EncodeItem = Resp, DecodeItem = Req> + 'static,
546 Req: 'static,
547 Resp: 'static,
548 F: FnMut(Request<Req>, &mut ResponseSink<Resp>) -> Result<(), Status> + 'static,
549 {
550 let codec = Rc::new(RefCell::new(codec));
551 self.insert(
552 path,
553 Box::new(move |request, inner| {
554 let metadata = request.initial_metadata.clone();
555 let (driver, complete) = Self::streams(request, inner, Rc::clone(&codec))?;
556 let (mut requests, mut sink) = server_streams(driver);
557 let result = catch_unwind(AssertUnwindSafe(|| {
558 let value = requests
559 .recv_next()
560 .map_err(stream_status)?
561 .ok_or_else(|| Status::invalid_argument("request is missing"))?;
562 if requests.recv_next().map_err(stream_status)?.is_some() {
563 return Err(Status::invalid_argument("request has multiple messages"));
564 }
565 handler(Request::from_parts(metadata, value), &mut sink)
566 }))
567 .unwrap_or_else(|_| Err(Status::internal("service handler panicked")));
568 Self::finalize(&mut sink, &complete, result)
569 }),
570 )
571 }
572 pub fn register_client_streaming<C, Req, Resp, F>(
576 &mut self,
577 path: &str,
578 codec: C,
579 mut handler: F,
580 ) -> Result<(), Status>
581 where
582 C: Codec<EncodeItem = Resp, DecodeItem = Req> + 'static,
583 Req: 'static,
584 Resp: 'static,
585 F: FnMut(RequestStream<Req>) -> Result<Response<Resp>, Status> + 'static,
586 {
587 let codec = Rc::new(RefCell::new(codec));
588 self.insert(
589 path,
590 Box::new(move |request, inner| {
591 let (mut driver, complete) =
592 Self::streams(request, Rc::clone(&inner), Rc::clone(&codec))?;
593 driver.response_initial_sent = true;
594 let id = driver.id;
595 let encoding = driver.encoding;
596 let (requests, mut sink) = server_streams(driver);
597 let result = catch_unwind(AssertUnwindSafe(|| {
598 let (metadata, value) = handler(requests)?.into_parts();
599 inner
600 .borrow_mut()
601 .session
602 .send_initial_metadata_with_content_type(
603 id,
604 &metadata,
605 encoding,
606 C::CONTENT_TYPE,
607 )?;
608 sink.send(&value).map_err(stream_status)
609 }))
610 .unwrap_or_else(|_| Err(Status::internal("service handler panicked")));
611 Self::finalize(&mut sink, &complete, result)
612 }),
613 )
614 }
615 pub fn register_bidi_streaming<C, Req, Resp, F>(
619 &mut self,
620 path: &str,
621 codec: C,
622 mut handler: F,
623 ) -> Result<(), Status>
624 where
625 C: Codec<EncodeItem = Resp, DecodeItem = Req> + 'static,
626 Req: 'static,
627 Resp: 'static,
628 F: FnMut(RequestStream<Req>, &mut ResponseSink<Resp>) -> Result<(), Status> + 'static,
629 {
630 let codec = Rc::new(RefCell::new(codec));
631 self.insert(
632 path,
633 Box::new(move |request, inner| {
634 let (driver, complete) = Self::streams(request, inner, Rc::clone(&codec))?;
635 let (requests, mut sink) = server_streams(driver);
636 let result = catch_unwind(AssertUnwindSafe(|| handler(requests, &mut sink)))
637 .unwrap_or_else(|_| Err(Status::internal("service handler panicked")));
638 Self::finalize(&mut sink, &complete, result)
639 }),
640 )
641 }
642 pub fn register_service_handler<H: ServiceHandler + 'static>(
646 &mut self,
647 path: &str,
648 mut handler: H,
649 ) -> Result<(), Status> {
650 self.register_bidi_streaming(path, PayloadCodec, move |requests, sink| {
651 handler.handle(requests, sink)
652 })
653 }
654 fn dispatch(&mut self) -> Result<bool, Status> {
655 let request = self.inner.borrow_mut().pending_incoming.pop_front();
656 let Some((received, mut request)) = request else {
657 return Ok(false);
658 };
659 request.timeout = request
660 .timeout
661 .map(|timeout| timeout.saturating_sub(received.elapsed()));
662 let id = request.stream_id;
663 if request.timeout.is_some_and(|timeout| timeout.is_zero()) {
664 let mut inner = self.inner.borrow_mut();
665 inner.session.finish_response(
666 id,
667 &Status::deadline_exceeded("request deadline elapsed"),
668 &Metadata::new(),
669 )?;
670 inner.pending_reap.insert(id);
671 inner.flush()?;
672 return Ok(true);
673 }
674 if let Some(handler) = self.routes.get_mut(&request.path) {
675 let result = handler(request, Rc::clone(&self.inner));
676 if let Err(status) = result {
677 let mut inner = self.inner.borrow_mut();
678 if inner
679 .session
680 .finish_response(id, &status, &Metadata::new())
681 .is_err()
682 {
683 inner.session.cancel_stream(id, 2)?;
684 inner.reset_reap.insert(id);
685 }
686 inner.pending_reap.insert(id);
687 }
688 } else {
689 let mut inner = self.inner.borrow_mut();
690 inner.session.finish_response(
691 id,
692 &Status::unimplemented("RPC path is not registered"),
693 &Metadata::new(),
694 )?;
695 inner.pending_reap.insert(id);
696 }
697 self.inner.borrow_mut().flush()?;
698 Ok(true)
699 }
700 pub fn poll_once(&mut self) -> Result<bool, Status> {
705 self.inner
706 .borrow_mut()
707 .transport
708 .set_nonblocking(true)
709 .map_err(io_status)?;
710 if self.inner.borrow().closed {
711 return Ok(false);
712 }
713 if self.dispatch()? {
714 return Ok(true);
715 }
716 let progress = self.inner.borrow_mut().drive(false, None)? > 0;
717 Ok(self.dispatch()? || progress)
718 }
719 pub fn serve_connection(&mut self) -> Result<(), Status> {
723 loop {
724 if self.inner.borrow().closed {
725 return Ok(());
726 }
727 if self.dispatch()? {
728 continue;
729 }
730 {
731 let mut inner = self.inner.borrow_mut();
732 if inner.draining || inner.session.goaway_received().is_some() {
733 inner.transport.set_nonblocking(true).map_err(io_status)?;
734 inner.flush()?;
735 if !inner.session.want_write() && inner.pending_reap.is_empty() {
736 inner.closed = true;
737 return Ok(());
738 }
739 }
740 inner.drive(true, None)?;
741 }
742 }
743 }
744 pub fn shutdown_with_goaway(&mut self, error_code: u32) -> Result<(), Status> {
749 let mut inner = self.inner.borrow_mut();
750 inner.session.submit_goaway(error_code)?;
751 inner.draining = true;
752 inner.transport.set_nonblocking(true).map_err(io_status)?;
753 inner.flush()?;
754 Ok(())
755 }
756}