1use crate::async_carrier::{self, AsyncCommandSender, DemandBatcher};
17use datum::{Flow, Keep, NotUsed, Sink, Source, StreamCompletion, StreamError, StreamResult};
18use std::net::SocketAddr;
19use std::sync::{Arc, Mutex, mpsc as std_mpsc};
20use tokio::net::{ToSocketAddrs, UdpSocket};
21use tokio::runtime::Handle;
22use tokio::sync::mpsc as tokio_mpsc;
23use tokio::task::JoinHandle;
24
25pub const DEFAULT_MAX_DATAGRAM_SIZE: usize = 65_536;
31
32pub const DEFAULT_RECEIVE_BUFFER: usize = 64;
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct Datagram {
38 pub payload: Vec<u8>,
40 pub remote: SocketAddr,
42}
43
44impl Datagram {
45 #[must_use]
47 pub fn new(payload: impl Into<Vec<u8>>, remote: SocketAddr) -> Self {
48 Self {
49 payload: payload.into(),
50 remote,
51 }
52 }
53
54 #[must_use]
56 pub fn payload(&self) -> &[u8] {
57 &self.payload
58 }
59
60 #[must_use]
62 pub fn remote(&self) -> SocketAddr {
63 self.remote
64 }
65
66 #[must_use]
68 pub fn into_parts(self) -> (Vec<u8>, SocketAddr) {
69 (self.payload, self.remote)
70 }
71
72 #[must_use]
74 pub fn into_payload(self) -> Vec<u8> {
75 self.payload
76 }
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81pub struct UdpBinding {
82 pub local_addr: SocketAddr,
83}
84
85impl UdpBinding {
86 #[must_use]
87 pub fn local_addr(&self) -> SocketAddr {
88 self.local_addr
89 }
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct UdpConnection {
95 pub local_addr: SocketAddr,
96 pub remote_addr: SocketAddr,
97}
98
99impl UdpConnection {
100 #[must_use]
101 pub fn local_addr(&self) -> SocketAddr {
102 self.local_addr
103 }
104
105 #[must_use]
106 pub fn remote_addr(&self) -> SocketAddr {
107 self.remote_addr
108 }
109}
110
111pub struct TokioUdp;
113
114pub type Udp = TokioUdp;
116
117enum ReceiveResponse<T> {
118 Item(T),
119 Error(StreamError),
120}
121
122enum QueueOutcome {
123 Queued,
124 Dropped,
125 Closed,
126}
127
128struct ReceiveResource<T> {
129 receiver: std_mpsc::Receiver<ReceiveResponse<T>>,
130 carrier: UdpCarrier<T>,
131 demand: DemandBatcher,
132}
133
134impl<T> Drop for ReceiveResource<T> {
135 fn drop(&mut self) {
136 self.carrier.close_read();
137 }
138}
139
140enum UdpCarrierCommand<T> {
141 Demand(usize),
142 SendOne(T),
143 SendBatch(Vec<T>),
144 CloseRead,
145 CloseWrite {
146 ack: std_mpsc::Sender<StreamResult<()>>,
147 },
148}
149
150#[derive(Clone)]
151struct UdpCarrier<T> {
152 inner: Arc<UdpCarrierInner<T>>,
153}
154
155struct UdpCarrierInner<T> {
156 commands: AsyncCommandSender<UdpCarrierCommand<T>>,
157 send_errors: Mutex<std_mpsc::Receiver<StreamError>>,
158 task: Mutex<Option<JoinHandle<()>>>,
159}
160
161impl<T> Drop for UdpCarrierInner<T> {
162 fn drop(&mut self) {
163 if let Some(task) = self
164 .task
165 .lock()
166 .unwrap_or_else(|poison| poison.into_inner())
167 .take()
168 {
169 task.abort();
170 }
171 }
172}
173
174impl<T> UdpCarrier<T> {
175 fn close_read(&self) {
176 let _ = self.inner.commands.try_send(UdpCarrierCommand::CloseRead);
177 }
178}
179
180impl<T> UdpCarrier<T>
181where
182 T: Send + 'static,
183{
184 fn request_demand(&self, demand: usize) -> StreamResult<()> {
185 self.inner
186 .commands
187 .send_or_blocking(UdpCarrierCommand::Demand(demand))
188 }
189
190 fn send_items(&self, items: Vec<T>) -> StreamResult<()> {
191 self.inner
192 .commands
193 .send_or_blocking(UdpCarrierCommand::SendBatch(items))
194 }
195
196 fn send_one(&self, item: T) -> StreamResult<()> {
197 self.inner
198 .commands
199 .send_or_blocking(UdpCarrierCommand::SendOne(item))
200 }
201
202 fn close_write(&self) -> StreamResult<()> {
203 self.check_send_error()?;
204 let (ack_sender, ack_receiver) = std_mpsc::channel();
205 self.inner
206 .commands
207 .send_or_blocking(UdpCarrierCommand::CloseWrite { ack: ack_sender })?;
208 match ack_receiver.recv() {
209 Ok(result) => result,
210 Err(_) => Err(abrupt_termination()),
211 }?;
212 self.check_send_error()
213 }
214
215 fn check_send_error(&self) -> StreamResult<()> {
216 match self
217 .inner
218 .send_errors
219 .lock()
220 .expect("UDP carrier send error receiver poisoned")
221 .try_recv()
222 {
223 Ok(error) => Err(error),
224 Err(std_mpsc::TryRecvError::Empty) | Err(std_mpsc::TryRecvError::Disconnected) => {
225 Ok(())
226 }
227 }
228 }
229}
230
231struct SendResource<T> {
232 carrier: UdpCarrier<T>,
233 pending: Vec<T>,
234 batch_size: usize,
235}
236
237type UdpCarrierParts<T> = (
238 UdpCarrier<T>,
239 Option<std_mpsc::Receiver<ReceiveResponse<T>>>,
240);
241
242fn io_error(error: std::io::Error) -> StreamError {
243 StreamError::Failed(error.to_string())
244}
245
246fn abrupt_termination() -> StreamError {
247 StreamError::AbruptTermination
248}
249
250impl TokioUdp {
251 #[must_use]
259 pub fn bind<A>(
260 addr: A,
261 max_datagram_size: usize,
262 receive_buffer: usize,
263 ) -> Source<Datagram, StreamCompletion<UdpBinding>>
264 where
265 A: ToSocketAddrs + Clone + Send + Sync + 'static,
266 {
267 assert!(
268 max_datagram_size > 0,
269 "maximum datagram size must be greater than zero"
270 );
271 assert!(
272 receive_buffer > 0,
273 "receive buffer must be greater than zero"
274 );
275 Source::lazy_future_source(move || {
276 let addr = addr.clone();
277 async move {
278 let handle = Handle::current();
279 let socket = UdpSocket::bind(addr).await.map_err(io_error)?;
280 let local_addr = socket.local_addr().map_err(io_error)?;
281 Ok(datagram_source_from_socket(
282 socket,
283 local_addr,
284 handle,
285 max_datagram_size,
286 receive_buffer,
287 ))
288 }
289 })
290 }
291
292 #[must_use]
295 pub fn bind_default<A>(addr: A) -> Source<Datagram, StreamCompletion<UdpBinding>>
296 where
297 A: ToSocketAddrs + Clone + Send + Sync + 'static,
298 {
299 Self::bind(addr, DEFAULT_MAX_DATAGRAM_SIZE, DEFAULT_RECEIVE_BUFFER)
300 }
301
302 #[must_use]
309 pub fn send_sink<A>(local_addr: A) -> Sink<Datagram, StreamCompletion<NotUsed>>
310 where
311 A: ToSocketAddrs + Clone + Send + Sync + 'static,
312 {
313 Flow::<Datagram, NotUsed>::future_flow(move || {
314 let local_addr = local_addr.clone();
315 async move {
316 let handle = Handle::current();
317 let socket = UdpSocket::bind(local_addr).await.map_err(io_error)?;
318 let carrier = start_datagram_carrier(
319 socket,
320 handle,
321 DEFAULT_MAX_DATAGRAM_SIZE,
322 1,
323 false,
324 true,
325 );
326 Ok(datagram_send_flow_from_carrier(carrier.0, 1))
327 }
328 })
329 .to_mat(Sink::ignore(), Keep::right)
330 }
331
332 #[must_use]
339 pub fn bind_flow<A>(
340 addr: A,
341 max_datagram_size: usize,
342 receive_buffer: usize,
343 ) -> Flow<Datagram, Datagram, StreamCompletion<UdpBinding>>
344 where
345 A: ToSocketAddrs + Clone + Send + Sync + 'static,
346 {
347 assert!(
348 max_datagram_size > 0,
349 "maximum datagram size must be greater than zero"
350 );
351 assert!(
352 receive_buffer > 0,
353 "receive buffer must be greater than zero"
354 );
355 Flow::<Datagram, Datagram>::future_flow(move || {
356 let addr = addr.clone();
357 async move {
358 let handle = Handle::current();
359 let socket = UdpSocket::bind(addr).await.map_err(io_error)?;
360 let local_addr = socket.local_addr().map_err(io_error)?;
361 let (carrier, receiver) = start_datagram_carrier(
362 socket,
363 handle,
364 max_datagram_size,
365 receive_buffer,
366 true,
367 true,
368 );
369 let sink = datagram_send_flow_from_carrier(carrier.clone(), 1)
370 .to_mat(Sink::ignore(), Keep::right);
371 let source = datagram_source_from_carrier(
372 carrier,
373 receiver.expect("UDP bind_flow receiver exists"),
374 local_addr,
375 receive_buffer,
376 );
377 Ok(Flow::from_sink_and_source(sink, source)
378 .map_materialized_value(move |_| UdpBinding { local_addr }))
379 }
380 })
381 }
382
383 #[must_use]
386 pub fn bind_flow_default<A>(addr: A) -> Flow<Datagram, Datagram, StreamCompletion<UdpBinding>>
387 where
388 A: ToSocketAddrs + Clone + Send + Sync + 'static,
389 {
390 Self::bind_flow(addr, DEFAULT_MAX_DATAGRAM_SIZE, DEFAULT_RECEIVE_BUFFER)
391 }
392
393 #[must_use]
400 pub fn connect<A, P>(
401 local_addr: A,
402 peer: P,
403 max_datagram_size: usize,
404 receive_buffer: usize,
405 ) -> Flow<Vec<u8>, Vec<u8>, StreamCompletion<UdpConnection>>
406 where
407 A: ToSocketAddrs + Clone + Send + Sync + 'static,
408 P: ToSocketAddrs + Clone + Send + Sync + 'static,
409 {
410 assert!(
411 max_datagram_size > 0,
412 "maximum datagram size must be greater than zero"
413 );
414 assert!(
415 receive_buffer > 0,
416 "receive buffer must be greater than zero"
417 );
418 Flow::<Vec<u8>, Vec<u8>>::future_flow(move || {
419 let local_addr = local_addr.clone();
420 let peer = peer.clone();
421 async move {
422 let handle = Handle::current();
423 let socket = UdpSocket::bind(local_addr).await.map_err(io_error)?;
424 socket.connect(peer).await.map_err(io_error)?;
425 let connection = UdpConnection {
426 local_addr: socket.local_addr().map_err(io_error)?,
427 remote_addr: socket.peer_addr().map_err(io_error)?,
428 };
429 let (carrier, receiver) = start_connected_carrier(
430 socket,
431 handle,
432 max_datagram_size,
433 receive_buffer,
434 true,
435 true,
436 );
437 let sink = connected_send_flow_from_carrier(carrier.clone(), 1)
438 .to_mat(Sink::ignore(), Keep::right);
439 let source = connected_source_from_carrier(
440 carrier,
441 receiver.expect("connected UDP receiver exists"),
442 receive_buffer,
443 );
444 Ok(Flow::from_sink_and_source(sink, source)
445 .map_materialized_value(move |_| connection))
446 }
447 })
448 }
449
450 #[must_use]
453 pub fn connect_default<A, P>(
454 local_addr: A,
455 peer: P,
456 ) -> Flow<Vec<u8>, Vec<u8>, StreamCompletion<UdpConnection>>
457 where
458 A: ToSocketAddrs + Clone + Send + Sync + 'static,
459 P: ToSocketAddrs + Clone + Send + Sync + 'static,
460 {
461 Self::connect(
462 local_addr,
463 peer,
464 DEFAULT_MAX_DATAGRAM_SIZE,
465 DEFAULT_RECEIVE_BUFFER,
466 )
467 }
468}
469
470fn datagram_source_from_socket(
471 socket: UdpSocket,
472 local_addr: SocketAddr,
473 handle: Handle,
474 max_datagram_size: usize,
475 receive_buffer: usize,
476) -> Source<Datagram, UdpBinding> {
477 let (carrier, receiver) = start_datagram_carrier(
478 socket,
479 handle,
480 max_datagram_size,
481 receive_buffer,
482 true,
483 false,
484 );
485 datagram_source_from_carrier(
486 carrier,
487 receiver.expect("UDP bind receiver exists"),
488 local_addr,
489 receive_buffer,
490 )
491}
492
493fn datagram_source_from_carrier(
494 carrier: UdpCarrier<Datagram>,
495 receiver: std_mpsc::Receiver<ReceiveResponse<Datagram>>,
496 local_addr: SocketAddr,
497 receive_buffer: usize,
498) -> Source<Datagram, UdpBinding> {
499 let receiver = Arc::new(Mutex::new(Some(receiver)));
500 Source::unfold_resource(
501 move || {
502 let receiver = receiver
503 .lock()
504 .expect("UDP receive resource receiver poisoned")
505 .take()
506 .ok_or_else(|| StreamError::Failed("UDP receive source already used".to_owned()))?;
507 let demand = DemandBatcher::new(receive_buffer);
508 carrier.request_demand(demand.initial())?;
509 Ok(ReceiveResource {
510 receiver,
511 carrier: carrier.clone(),
512 demand,
513 })
514 },
515 receive_next_item,
516 close_receive_resource,
517 )
518 .map_materialized_value(move |_| UdpBinding { local_addr })
519}
520
521fn connected_source_from_carrier(
522 carrier: UdpCarrier<Vec<u8>>,
523 receiver: std_mpsc::Receiver<ReceiveResponse<Vec<u8>>>,
524 receive_buffer: usize,
525) -> Source<Vec<u8>, NotUsed> {
526 let receiver = Arc::new(Mutex::new(Some(receiver)));
527 Source::unfold_resource(
528 move || {
529 let receiver = receiver
530 .lock()
531 .expect("connected UDP receive resource receiver poisoned")
532 .take()
533 .ok_or_else(|| {
534 StreamError::Failed("connected UDP receive source already used".to_owned())
535 })?;
536 let demand = DemandBatcher::new(receive_buffer);
537 carrier.request_demand(demand.initial())?;
538 Ok(ReceiveResource {
539 receiver,
540 carrier: carrier.clone(),
541 demand,
542 })
543 },
544 receive_next_item,
545 close_receive_resource,
546 )
547}
548
549fn receive_next_item<T>(resource: &mut ReceiveResource<T>) -> StreamResult<Option<T>>
550where
551 T: Send + 'static,
552{
553 match resource.receiver.recv() {
554 Ok(ReceiveResponse::Item(item)) => {
555 if let Some(demand) = resource.demand.record_consumed() {
556 resource.carrier.request_demand(demand)?;
557 }
558 Ok(Some(item))
559 }
560 Ok(ReceiveResponse::Error(error)) => Err(error),
561 Err(_) => Err(abrupt_termination()),
562 }
563}
564
565fn close_receive_resource<T>(resource: ReceiveResource<T>) -> StreamResult<()>
566where
567 T: Send + 'static,
568{
569 resource.carrier.close_read();
570 Ok(())
571}
572
573fn start_datagram_carrier(
574 socket: UdpSocket,
575 handle: Handle,
576 max_datagram_size: usize,
577 receive_buffer: usize,
578 read_open: bool,
579 write_open: bool,
580) -> UdpCarrierParts<Datagram> {
581 let command_capacity = async_carrier::DEFAULT_COMMAND_BUFFER.max(receive_buffer);
582 let (commands, command_receiver) = async_carrier::command_channel(command_capacity, "UDP");
583 let (send_error_sender, send_error_receiver) = std_mpsc::channel();
584 let (receive_sender, receive_receiver) = if read_open {
585 let (sender, receiver) = std_mpsc::sync_channel(receive_buffer.saturating_add(1));
586 (Some(sender), Some(receiver))
587 } else {
588 (None, None)
589 };
590 let task = handle.spawn(run_datagram_carrier_task(
591 socket,
592 max_datagram_size,
593 receive_sender,
594 send_error_sender,
595 command_receiver,
596 read_open,
597 write_open,
598 ));
599 (
600 UdpCarrier {
601 inner: Arc::new(UdpCarrierInner {
602 commands,
603 send_errors: Mutex::new(send_error_receiver),
604 task: Mutex::new(Some(task)),
605 }),
606 },
607 receive_receiver,
608 )
609}
610
611fn start_connected_carrier(
612 socket: UdpSocket,
613 handle: Handle,
614 max_datagram_size: usize,
615 receive_buffer: usize,
616 read_open: bool,
617 write_open: bool,
618) -> UdpCarrierParts<Vec<u8>> {
619 let command_capacity = async_carrier::DEFAULT_COMMAND_BUFFER.max(receive_buffer);
620 let (commands, command_receiver) =
621 async_carrier::command_channel(command_capacity, "connected UDP");
622 let (send_error_sender, send_error_receiver) = std_mpsc::channel();
623 let (receive_sender, receive_receiver) = if read_open {
624 let (sender, receiver) = std_mpsc::sync_channel(receive_buffer.saturating_add(1));
625 (Some(sender), Some(receiver))
626 } else {
627 (None, None)
628 };
629 let task = handle.spawn(run_connected_carrier_task(
630 socket,
631 max_datagram_size,
632 receive_sender,
633 send_error_sender,
634 command_receiver,
635 read_open,
636 write_open,
637 ));
638 (
639 UdpCarrier {
640 inner: Arc::new(UdpCarrierInner {
641 commands,
642 send_errors: Mutex::new(send_error_receiver),
643 task: Mutex::new(Some(task)),
644 }),
645 },
646 receive_receiver,
647 )
648}
649
650async fn run_datagram_carrier_task(
651 socket: UdpSocket,
652 max_datagram_size: usize,
653 receive_sender: Option<std_mpsc::SyncSender<ReceiveResponse<Datagram>>>,
654 send_error_sender: std_mpsc::Sender<StreamError>,
655 mut commands: tokio_mpsc::Receiver<UdpCarrierCommand<Datagram>>,
656 mut read_open: bool,
657 mut write_open: bool,
658) {
659 let mut buffer = vec![0_u8; max_datagram_size];
660 let mut requested = 0_usize;
661 loop {
662 if !read_open && !write_open {
663 return;
664 }
665
666 if read_open && requested > 0 {
667 tokio::select! {
668 biased;
669 command = commands.recv() => {
670 let Some(command) = command else { return; };
671 if !handle_datagram_command(
672 &socket,
673 command,
674 &receive_sender,
675 &send_error_sender,
676 &mut read_open,
677 &mut write_open,
678 &mut requested,
679 ).await {
680 return;
681 }
682 }
683 received = socket.recv_from(&mut buffer) => {
684 match received {
685 Ok((read, remote)) => {
686 let datagram = Datagram::new(buffer[..read].to_vec(), remote);
687 match try_send_received_item(&receive_sender, datagram) {
688 QueueOutcome::Queued => {
689 requested = requested.saturating_sub(1);
690 }
691 QueueOutcome::Dropped => {
692 requested = 0;
693 if let Err(error) = drain_ready_datagrams(&socket, &mut buffer) {
694 report_carrier_error(&receive_sender, &send_error_sender, error);
695 return;
696 }
697 }
698 QueueOutcome::Closed => {
699 read_open = false;
700 }
701 }
702 }
703 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => {}
704 Err(error) => {
705 report_carrier_error(&receive_sender, &send_error_sender, io_error(error));
706 return;
707 }
708 }
709 }
710 }
711 } else {
712 let Some(command) = commands.recv().await else {
713 return;
714 };
715 if !handle_datagram_command(
716 &socket,
717 command,
718 &receive_sender,
719 &send_error_sender,
720 &mut read_open,
721 &mut write_open,
722 &mut requested,
723 )
724 .await
725 {
726 return;
727 }
728 }
729 }
730}
731
732async fn run_connected_carrier_task(
733 socket: UdpSocket,
734 max_datagram_size: usize,
735 receive_sender: Option<std_mpsc::SyncSender<ReceiveResponse<Vec<u8>>>>,
736 send_error_sender: std_mpsc::Sender<StreamError>,
737 mut commands: tokio_mpsc::Receiver<UdpCarrierCommand<Vec<u8>>>,
738 mut read_open: bool,
739 mut write_open: bool,
740) {
741 let mut buffer = vec![0_u8; max_datagram_size];
742 let mut requested = 0_usize;
743 loop {
744 if !read_open && !write_open {
745 return;
746 }
747
748 if read_open && requested > 0 {
749 tokio::select! {
750 biased;
751 command = commands.recv() => {
752 let Some(command) = command else { return; };
753 if !handle_connected_command(
754 &socket,
755 command,
756 &receive_sender,
757 &send_error_sender,
758 &mut read_open,
759 &mut write_open,
760 &mut requested,
761 ).await {
762 return;
763 }
764 }
765 received = socket.recv(&mut buffer) => {
766 match received {
767 Ok(read) => {
768 match try_send_received_item(&receive_sender, buffer[..read].to_vec()) {
769 QueueOutcome::Queued => {
770 requested = requested.saturating_sub(1);
771 }
772 QueueOutcome::Dropped => {
773 requested = 0;
774 if let Err(error) = drain_ready_connected_datagrams(&socket, &mut buffer) {
775 report_carrier_error(&receive_sender, &send_error_sender, error);
776 return;
777 }
778 }
779 QueueOutcome::Closed => {
780 read_open = false;
781 }
782 }
783 }
784 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => {}
785 Err(error) => {
786 report_carrier_error(&receive_sender, &send_error_sender, io_error(error));
787 return;
788 }
789 }
790 }
791 }
792 } else {
793 let Some(command) = commands.recv().await else {
794 return;
795 };
796 if !handle_connected_command(
797 &socket,
798 command,
799 &receive_sender,
800 &send_error_sender,
801 &mut read_open,
802 &mut write_open,
803 &mut requested,
804 )
805 .await
806 {
807 return;
808 }
809 }
810 }
811}
812
813async fn handle_datagram_command(
814 socket: &UdpSocket,
815 command: UdpCarrierCommand<Datagram>,
816 receive_sender: &Option<std_mpsc::SyncSender<ReceiveResponse<Datagram>>>,
817 send_error_sender: &std_mpsc::Sender<StreamError>,
818 read_open: &mut bool,
819 write_open: &mut bool,
820 requested: &mut usize,
821) -> bool {
822 match command {
823 UdpCarrierCommand::Demand(demand) => {
824 *requested = requested.saturating_add(demand);
825 true
826 }
827 UdpCarrierCommand::SendOne(datagram) => {
828 if !*write_open {
829 let error = StreamError::Failed("UDP write side is closed".to_owned());
830 report_carrier_error(receive_sender, send_error_sender, error);
831 return false;
832 }
833 send_one_datagram(socket, receive_sender, send_error_sender, datagram).await
834 }
835 UdpCarrierCommand::SendBatch(datagrams) => {
836 if !*write_open {
837 let error = StreamError::Failed("UDP write side is closed".to_owned());
838 report_carrier_error(receive_sender, send_error_sender, error);
839 return false;
840 }
841 for datagram in datagrams {
842 if !send_one_datagram(socket, receive_sender, send_error_sender, datagram).await {
843 return false;
844 }
845 }
846 true
847 }
848 UdpCarrierCommand::CloseRead => {
849 *read_open = false;
850 true
851 }
852 UdpCarrierCommand::CloseWrite { ack } => {
853 *write_open = false;
854 let _ = ack.send(Ok(()));
855 true
856 }
857 }
858}
859
860async fn handle_connected_command(
861 socket: &UdpSocket,
862 command: UdpCarrierCommand<Vec<u8>>,
863 receive_sender: &Option<std_mpsc::SyncSender<ReceiveResponse<Vec<u8>>>>,
864 send_error_sender: &std_mpsc::Sender<StreamError>,
865 read_open: &mut bool,
866 write_open: &mut bool,
867 requested: &mut usize,
868) -> bool {
869 match command {
870 UdpCarrierCommand::Demand(demand) => {
871 *requested = requested.saturating_add(demand);
872 true
873 }
874 UdpCarrierCommand::SendOne(payload) => {
875 if !*write_open {
876 let error = StreamError::Failed("connected UDP write side is closed".to_owned());
877 report_carrier_error(receive_sender, send_error_sender, error);
878 return false;
879 }
880 send_one_connected_payload(socket, receive_sender, send_error_sender, payload).await
881 }
882 UdpCarrierCommand::SendBatch(payloads) => {
883 if !*write_open {
884 let error = StreamError::Failed("connected UDP write side is closed".to_owned());
885 report_carrier_error(receive_sender, send_error_sender, error);
886 return false;
887 }
888 for payload in payloads {
889 if !send_one_connected_payload(socket, receive_sender, send_error_sender, payload)
890 .await
891 {
892 return false;
893 }
894 }
895 true
896 }
897 UdpCarrierCommand::CloseRead => {
898 *read_open = false;
899 true
900 }
901 UdpCarrierCommand::CloseWrite { ack } => {
902 *write_open = false;
903 let _ = ack.send(Ok(()));
904 true
905 }
906 }
907}
908
909async fn send_one_datagram(
910 socket: &UdpSocket,
911 receive_sender: &Option<std_mpsc::SyncSender<ReceiveResponse<Datagram>>>,
912 send_error_sender: &std_mpsc::Sender<StreamError>,
913 datagram: Datagram,
914) -> bool {
915 let expected = datagram.payload.len();
916 match socket.send_to(&datagram.payload, datagram.remote).await {
917 Ok(sent) if sent == expected => true,
918 Ok(sent) => {
919 report_carrier_error(
920 receive_sender,
921 send_error_sender,
922 short_send_error(sent, expected),
923 );
924 false
925 }
926 Err(error) => {
927 report_carrier_error(receive_sender, send_error_sender, io_error(error));
928 false
929 }
930 }
931}
932
933async fn send_one_connected_payload(
934 socket: &UdpSocket,
935 receive_sender: &Option<std_mpsc::SyncSender<ReceiveResponse<Vec<u8>>>>,
936 send_error_sender: &std_mpsc::Sender<StreamError>,
937 payload: Vec<u8>,
938) -> bool {
939 let expected = payload.len();
940 match socket.send(&payload).await {
941 Ok(sent) if sent == expected => true,
942 Ok(sent) => {
943 report_carrier_error(
944 receive_sender,
945 send_error_sender,
946 short_send_error(sent, expected),
947 );
948 false
949 }
950 Err(error) => {
951 report_carrier_error(receive_sender, send_error_sender, io_error(error));
952 false
953 }
954 }
955}
956
957fn try_send_received_item<T>(
958 sender: &Option<std_mpsc::SyncSender<ReceiveResponse<T>>>,
959 item: T,
960) -> QueueOutcome
961where
962 T: Send + 'static,
963{
964 let Some(sender) = sender else {
965 return QueueOutcome::Closed;
966 };
967 match sender.try_send(ReceiveResponse::Item(item)) {
968 Ok(()) => QueueOutcome::Queued,
969 Err(std_mpsc::TrySendError::Full(_)) => QueueOutcome::Dropped,
970 Err(std_mpsc::TrySendError::Disconnected(_)) => QueueOutcome::Closed,
971 }
972}
973
974fn drain_ready_datagrams(socket: &UdpSocket, buffer: &mut [u8]) -> StreamResult<()> {
975 loop {
976 match socket.try_recv_from(buffer) {
977 Ok((_read, _remote)) => {}
978 Err(error) if error.kind() == std::io::ErrorKind::WouldBlock => return Ok(()),
979 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => {}
980 Err(error) => return Err(io_error(error)),
981 }
982 }
983}
984
985fn drain_ready_connected_datagrams(socket: &UdpSocket, buffer: &mut [u8]) -> StreamResult<()> {
986 loop {
987 match socket.try_recv(buffer) {
988 Ok(_read) => {}
989 Err(error) if error.kind() == std::io::ErrorKind::WouldBlock => return Ok(()),
990 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => {}
991 Err(error) => return Err(io_error(error)),
992 }
993 }
994}
995
996fn report_carrier_error<T>(
997 receive_sender: &Option<std_mpsc::SyncSender<ReceiveResponse<T>>>,
998 send_error_sender: &std_mpsc::Sender<StreamError>,
999 error: StreamError,
1000) where
1001 T: Send + 'static,
1002{
1003 let _ = send_error_sender.send(error.clone());
1004 if let Some(receive_sender) = receive_sender {
1005 let _ = receive_sender.try_send(ReceiveResponse::Error(error));
1006 }
1007}
1008
1009fn datagram_send_flow_from_carrier(
1010 carrier: UdpCarrier<Datagram>,
1011 batch_size: usize,
1012) -> Flow<Datagram, NotUsed, NotUsed> {
1013 Flow::<Datagram, Datagram>::identity().map_with_resource(
1014 move || {
1015 Ok(SendResource {
1016 carrier: carrier.clone(),
1017 pending: Vec::with_capacity(batch_size),
1018 batch_size,
1019 })
1020 },
1021 |resource, datagram| {
1022 send_datagram(resource, datagram)?;
1023 Ok(NotUsed)
1024 },
1025 close_send_resource,
1026 )
1027}
1028
1029fn connected_send_flow_from_carrier(
1030 carrier: UdpCarrier<Vec<u8>>,
1031 batch_size: usize,
1032) -> Flow<Vec<u8>, NotUsed, NotUsed> {
1033 Flow::<Vec<u8>, Vec<u8>>::identity().map_with_resource(
1034 move || {
1035 Ok(SendResource {
1036 carrier: carrier.clone(),
1037 pending: Vec::with_capacity(batch_size),
1038 batch_size,
1039 })
1040 },
1041 |resource, payload| {
1042 send_connected_payload(resource, payload)?;
1043 Ok(NotUsed)
1044 },
1045 close_send_resource,
1046 )
1047}
1048
1049fn close_send_resource<T>(mut resource: SendResource<T>) -> StreamResult<Option<NotUsed>>
1050where
1051 T: Send + 'static,
1052{
1053 flush_send_resource(&mut resource)?;
1054 resource.carrier.close_write()?;
1055 Ok(None)
1056}
1057
1058fn send_datagram(resource: &mut SendResource<Datagram>, datagram: Datagram) -> StreamResult<()> {
1059 send_item(resource, datagram)
1060}
1061
1062fn send_connected_payload(
1063 resource: &mut SendResource<Vec<u8>>,
1064 payload: Vec<u8>,
1065) -> StreamResult<()> {
1066 send_item(resource, payload)
1067}
1068
1069fn send_item<T>(resource: &mut SendResource<T>, item: T) -> StreamResult<()>
1070where
1071 T: Send + 'static,
1072{
1073 if resource.batch_size <= 1 {
1074 return resource.carrier.send_one(item);
1075 }
1076 resource.pending.push(item);
1077 if resource.pending.len() >= resource.batch_size {
1078 flush_send_resource(resource)?;
1079 }
1080 Ok(())
1081}
1082
1083fn flush_send_resource<T>(resource: &mut SendResource<T>) -> StreamResult<()>
1084where
1085 T: Send + 'static,
1086{
1087 if resource.pending.is_empty() {
1088 return resource.carrier.check_send_error();
1089 }
1090 let pending = std::mem::take(&mut resource.pending);
1091 resource.carrier.send_items(pending)
1092}
1093
1094fn short_send_error(sent: usize, expected: usize) -> StreamError {
1095 StreamError::Failed(format!(
1096 "UDP socket sent {sent} bytes from {expected}-byte datagram"
1097 ))
1098}