1- use crate :: preview2:: host:: network:: util;
2- use crate :: preview2:: network:: SocketAddrUse ;
31use crate :: preview2:: udp:: UdpSocket ;
42use crate :: preview2:: {
53 bindings:: {
@@ -14,17 +12,24 @@ use crate::preview2::{Pollable, SocketError, SocketResult, WasiView};
1412use anyhow:: anyhow;
1513use async_trait:: async_trait;
1614use std:: net:: SocketAddr ;
17- use tokio :: io :: Interest ;
15+ use std :: sync :: Arc ;
1816use wasmtime:: component:: Resource ;
1917
2018/// A `wasi:sockets/udp::udp-socket` instance.
2119/// This is mostly glue code translating between WASI types and concepts (Tables,
2220/// Resources, Pollables, ...) to their idiomatic Rust equivalents.
2321pub struct UdpSocketResource {
24- inner : Box < dyn UdpSocket > ,
22+ inner : Arc < dyn UdpSocket + Send + Sync > ,
2523 udp_state : UdpState ,
2624}
2725
26+ #[ async_trait]
27+ impl Subscribe for UdpSocketResource {
28+ async fn ready ( & mut self ) {
29+ // None of the socket-level operations block natively
30+ }
31+ }
32+
2833/// Theoretical maximum byte size of a UDP datagram, the real limit is lower,
2934/// but we do not account for e.g. the transport layer here for simplicity.
3035/// In practice, datagrams are typically less than 1500 bytes.
@@ -42,7 +47,7 @@ impl<T: WasiView> udp_create_socket::Host for T {
4247 . network
4348 . new_udp_socket ( address_family. into ( ) ) ?;
4449 let resource = UdpSocketResource {
45- inner : socket,
50+ inner : socket. into ( ) ,
4651 udp_state : UdpState :: Default ,
4752 } ;
4853 let socket = self . table_mut ( ) . push ( resource) ?;
@@ -135,11 +140,11 @@ impl<T: WasiView> udp::HostUdpSocket for T {
135140
136141 let incoming_stream = IncomingDatagramStream {
137142 inner : socket. inner . clone ( ) ,
138- remote_address,
143+ is_connected : remote_address. is_some ( ) ,
139144 } ;
140145 let outgoing_stream = OutgoingDatagramStream {
141- inner : socket. inner ,
142- remote_address,
146+ inner : socket. inner . clone ( ) ,
147+ is_connected : remote_address. is_some ( ) ,
143148 send_state : SendState :: Idle ,
144149 } ;
145150
@@ -256,11 +261,14 @@ impl<T: WasiView> udp::HostUdpSocket for T {
256261 Ok ( ( ) )
257262 }
258263
259- fn subscribe ( & mut self , this : Resource < udp:: UdpSocket > ) -> anyhow:: Result < Resource < Pollable > > {
264+ fn subscribe (
265+ & mut self ,
266+ this : Resource < UdpSocketResource > ,
267+ ) -> anyhow:: Result < Resource < Pollable > > {
260268 crate :: preview2:: poll:: subscribe ( self . table_mut ( ) , this)
261269 }
262270
263- fn drop ( & mut self , this : Resource < udp :: UdpSocket > ) -> Result < ( ) , anyhow:: Error > {
271+ fn drop ( & mut self , this : Resource < UdpSocketResource > ) -> Result < ( ) , anyhow:: Error > {
264272 let table = self . table_mut ( ) ;
265273
266274 // As in the filesystem implementation, we assume closing a socket
@@ -283,15 +291,12 @@ impl<T: WasiView> udp::HostIncomingDatagramStream for T {
283291 stream : & IncomingDatagramStream ,
284292 ) -> SocketResult < Option < udp:: IncomingDatagram > > {
285293 let mut buf = [ 0 ; MAX_UDP_DATAGRAM_SIZE ] ;
286- let ( size, received_addr) = stream. inner . try_recv_from ( & mut buf) ?;
294+ let ( size, received_addr) = stream. inner . receive_data ( & mut buf) ?;
287295 debug_assert ! ( size <= buf. len( ) ) ;
288296
289- match stream. remote_address {
290- Some ( connected_addr) if connected_addr != received_addr => {
291- // Normally, this should have already been checked for us by the OS.
292- return Ok ( None ) ;
293- }
294- _ => { }
297+ if stream. is_connected && stream. inner . remote_address ( ) ? != received_addr {
298+ // Normally, this should have already been checked for us by the OS.
299+ return Ok ( None ) ;
295300 }
296301
297302 Ok ( Some ( udp:: IncomingDatagram {
@@ -355,9 +360,8 @@ impl<T: WasiView> udp::HostIncomingDatagramStream for T {
355360#[ async_trait]
356361impl Subscribe for IncomingDatagramStream {
357362 async fn ready ( & mut self ) {
358- // FIXME: Add `Interest::ERROR` when we update to tokio 1.32.
359363 self . inner
360- . ready ( Interest :: READABLE )
364+ . await_readable ( )
361365 . await
362366 . expect ( "failed to await UDP socket readiness" ) ;
363367 }
@@ -395,29 +399,19 @@ impl<T: WasiView> udp::HostOutgoingDatagramStream for T {
395399 }
396400
397401 let provided_addr = datagram. remote_address . map ( SocketAddr :: from) ;
398- let addr = match ( stream. remote_address , provided_addr) {
399- ( None , Some ( addr) ) => {
400- stream
401- . addr_check
402- . check ( & addr , SocketAddrUse :: UdpOutgoingDatagram ) ? ;
403- addr
402+ match ( stream. is_connected , provided_addr) {
403+ ( false , Some ( addr) ) => {
404+ stream. inner . send_data_to ( addr , & datagram . data ) ? ;
405+ }
406+ ( true , None ) => {
407+ stream . inner . send_data ( & datagram . data ) ? ;
404408 }
405- ( Some ( addr) , None ) => addr,
406- ( Some ( connected_addr) , Some ( provided_addr) ) if connected_addr == provided_addr => {
407- connected_addr
409+ ( true , Some ( provided_addr) ) if stream. inner . remote_address ( ) ? == provided_addr => {
410+ stream. inner . send_data ( & datagram. data ) ?;
408411 }
409412 _ => return Err ( ErrorCode :: InvalidArgument . into ( ) ) ,
410413 } ;
411414
412- util:: validate_remote_address ( & addr) ?;
413- util:: validate_address_family ( & addr, & stream. family ) ?;
414-
415- if stream. remote_address == Some ( addr) {
416- stream. inner . try_send ( & datagram. data ) ?;
417- } else {
418- stream. inner . try_send_to ( & datagram. data , addr) ?;
419- }
420-
421415 Ok ( ( ) )
422416 }
423417
@@ -491,9 +485,8 @@ impl Subscribe for OutgoingDatagramStream {
491485 match self . send_state {
492486 SendState :: Idle | SendState :: Permitted ( _) => { }
493487 SendState :: Waiting => {
494- // FIXME: Add `Interest::ERROR` when we update to tokio 1.32.
495488 self . inner
496- . ready ( Interest :: WRITABLE )
489+ . await_writable ( )
497490 . await
498491 . expect ( "failed to await UDP socket readiness" ) ;
499492 self . send_state = SendState :: Idle ;
0 commit comments