wasmer_vnet/
lib.rs

1use std::fmt;
2use std::net::IpAddr;
3use std::net::Ipv4Addr;
4use std::net::Ipv6Addr;
5use std::net::Shutdown;
6use std::net::SocketAddr;
7use std::sync::mpsc;
8use std::sync::Arc;
9use std::sync::Mutex;
10use std::time::Duration;
11use thiserror::Error;
12
13pub use bytes::Bytes;
14pub use bytes::BytesMut;
15
16pub type Result<T> = std::result::Result<T, NetworkError>;
17
18/// Socket descriptors are also file descriptors and so
19/// all file operations can also be used on sockets
20pub type SocketDescriptor = wasmer_vfs::FileDescriptor;
21
22/// Represents an IP address and its netmask
23#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
24pub struct IpCidr {
25    pub ip: IpAddr,
26    pub prefix: u8,
27}
28
29/// Represents a routing entry in the routing table of the interface
30#[derive(Clone, Debug)]
31pub struct IpRoute {
32    pub cidr: IpCidr,
33    pub via_router: IpAddr,
34    pub preferred_until: Option<Duration>,
35    pub expires_at: Option<Duration>,
36}
37
38/// An implementation of virtual networking
39pub trait VirtualNetworking: fmt::Debug + Send + Sync + 'static {
40    /// Establishes a web socket connection
41    /// (note: this does not use the virtual sockets and is standalone
42    ///        functionality that works without the network being connected)
43    fn ws_connect(&self, url: &str) -> Result<Box<dyn VirtualWebSocket + Sync>>;
44
45    /// Makes a HTTP request to a remote web resource
46    /// The headers are separated by line breaks
47    /// (note: this does not use the virtual sockets and is standalone
48    ///        functionality that works without the network being connected)
49    fn http_request(
50        &self,
51        url: &str,
52        method: &str,
53        headers: &str,
54        gzip: bool,
55    ) -> Result<SocketHttpRequest>;
56
57    /// Bridges this local network with a remote network, which is required in
58    /// order to make lower level networking calls (such as UDP/TCP)
59    fn bridge(&self, network: &str, access_token: &str, security: StreamSecurity) -> Result<()>;
60
61    /// Disconnects from the remote network essentially unbridging it
62    fn unbridge(&self) -> Result<()>;
63
64    /// Acquires an IP address on the network and configures the routing tables
65    fn dhcp_acquire(&self) -> Result<Vec<IpAddr>>;
66
67    /// Adds a static IP address to the interface with a netmask prefix
68    fn ip_add(&self, ip: IpAddr, prefix: u8) -> Result<()>;
69
70    /// Removes a static (or dynamic) IP address from the interface
71    fn ip_remove(&self, ip: IpAddr) -> Result<()>;
72
73    /// Clears all the assigned IP addresses for this interface
74    fn ip_clear(&self) -> Result<()>;
75
76    /// Lists all the IP addresses currently assigned to this interface
77    fn ip_list(&self) -> Result<Vec<IpCidr>>;
78
79    /// Returns the hardware MAC address for this interface
80    fn mac(&self) -> Result<[u8; 6]>;
81
82    /// Adds a default gateway to the routing table
83    fn gateway_set(&self, ip: IpAddr) -> Result<()>;
84
85    /// Adds a specific route to the routing table
86    fn route_add(
87        &self,
88        cidr: IpCidr,
89        via_router: IpAddr,
90        preferred_until: Option<Duration>,
91        expires_at: Option<Duration>,
92    ) -> Result<()>;
93
94    /// Removes a routing rule from the routing table
95    fn route_remove(&self, cidr: IpAddr) -> Result<()>;
96
97    /// Clears the routing table for this interface
98    fn route_clear(&self) -> Result<()>;
99
100    /// Lists all the routes defined in the routing table for this interface
101    fn route_list(&self) -> Result<Vec<IpRoute>>;
102
103    /// Creates a low level socket that can read and write Ethernet packets
104    /// directly to the interface
105    fn bind_raw(&self) -> Result<Box<dyn VirtualRawSocket + Sync>>;
106
107    /// Lists for TCP connections on a specific IP and Port combination
108    /// Multiple servers (processes or threads) can bind to the same port if they each set
109    /// the reuse-port and-or reuse-addr flags
110    fn listen_tcp(
111        &self,
112        addr: SocketAddr,
113        only_v6: bool,
114        reuse_port: bool,
115        reuse_addr: bool,
116    ) -> Result<Box<dyn VirtualTcpListener + Sync>>;
117
118    /// Opens a UDP socket that listens on a specific IP and Port combination
119    /// Multiple servers (processes or threads) can bind to the same port if they each set
120    /// the reuse-port and-or reuse-addr flags
121    fn bind_udp(
122        &self,
123        addr: SocketAddr,
124        reuse_port: bool,
125        reuse_addr: bool,
126    ) -> Result<Box<dyn VirtualUdpSocket + Sync>>;
127
128    /// Creates a socket that can be used to send and receive ICMP packets
129    /// from a paritcular IP address
130    fn bind_icmp(&self, addr: IpAddr) -> Result<Box<dyn VirtualIcmpSocket + Sync>>;
131
132    /// Opens a TCP connection to a particular destination IP address and port
133    fn connect_tcp(
134        &self,
135        addr: SocketAddr,
136        peer: SocketAddr,
137        timeout: Option<Duration>,
138    ) -> Result<Box<dyn VirtualTcpSocket + Sync>>;
139
140    /// Performs DNS resolution for a specific hostname
141    fn resolve(
142        &self,
143        host: &str,
144        port: Option<u16>,
145        dns_server: Option<IpAddr>,
146    ) -> Result<Vec<IpAddr>>;
147}
148
149/// Holds the interface used to work with a pending HTTP request
150#[derive(Debug)]
151pub struct SocketHttpRequest {
152    /// Used to send the request bytes to the HTTP server
153    /// (once all bytes are send the sender should be closed)
154    pub request: Option<mpsc::Sender<Vec<u8>>>,
155    /// Used to receive the response bytes from the HTTP server
156    /// (once all the bytes have been received the receiver will be closed)
157    pub response: Option<mpsc::Receiver<Vec<u8>>>,
158    /// Used to receive all the headers from the HTTP server
159    /// (once all the headers have been received the receiver will be closed)
160    pub headers: Option<mpsc::Receiver<(String, String)>>,
161    /// Used to watch for the status
162    pub status: Arc<Mutex<mpsc::Receiver<Result<HttpStatus>>>>,
163}
164
165/// Represents the final result of a HTTP request
166#[derive(Debug)]
167pub struct HttpStatus {
168    /// Indicates if the HTTP request was redirected to another URL / server
169    pub redirected: bool,
170    /// Size of the data held in the response receiver
171    pub size: usize,
172    /// Status code returned by the server
173    pub status: u16,
174    /// Status text returned by the server
175    pub status_text: String,
176}
177
178#[derive(Debug)]
179pub struct SocketReceive {
180    /// Data that was received
181    pub data: Bytes,
182    /// Indicates if the data was truncated (e.g. UDP packet)
183    pub truncated: bool,
184}
185
186#[derive(Debug)]
187pub struct SocketReceiveFrom {
188    /// Data that was received
189    pub data: Bytes,
190    /// Indicates if the data was truncated (e.g. UDP packet)
191    pub truncated: bool,
192    /// Peer sender address of the data
193    pub addr: SocketAddr,
194}
195
196pub trait VirtualTcpListener: fmt::Debug + Send + Sync + 'static {
197    /// Accepts an connection attempt that was made to this listener
198    fn accept(&self) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)>;
199
200    /// Accepts an connection attempt that was made to this listener (or times out)
201    fn accept_timeout(
202        &self,
203        timeout: Duration,
204    ) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)>;
205
206    /// Sets the accept timeout
207    fn set_timeout(&mut self, timeout: Option<Duration>) -> Result<()>;
208
209    /// Gets the accept timeout
210    fn timeout(&self) -> Result<Option<Duration>>;
211
212    /// Returns the local address of this TCP listener
213    fn addr_local(&self) -> Result<SocketAddr>;
214
215    /// Sets how many network hops the packets are permitted for new connections
216    fn set_ttl(&mut self, ttl: u8) -> Result<()>;
217
218    /// Returns the maximum number of network hops before packets are dropped
219    fn ttl(&self) -> Result<u8>;
220}
221
222pub trait VirtualSocket: fmt::Debug + Send + Sync + 'static {
223    /// Sets how many network hops the packets are permitted for new connections
224    fn set_ttl(&mut self, ttl: u32) -> Result<()>;
225
226    /// Returns the maximum number of network hops before packets are dropped
227    fn ttl(&self) -> Result<u32>;
228
229    /// Returns the local address for this socket
230    fn addr_local(&self) -> Result<SocketAddr>;
231
232    /// Returns the status/state of the socket
233    fn status(&self) -> Result<SocketStatus>;
234}
235
236#[derive(Debug, Copy, Clone, PartialEq, Eq)]
237pub enum SocketStatus {
238    Opening,
239    Opened,
240    Closed,
241    Failed,
242}
243
244#[derive(Debug, Copy, Clone, PartialEq, Eq)]
245pub enum StreamSecurity {
246    Unencrypted,
247    AnyEncyption,
248    ClassicEncryption,
249    DoubleEncryption,
250}
251
252/// Interface used for sending and receiving data from a web socket
253pub trait VirtualWebSocket: fmt::Debug + Send + Sync + 'static {
254    /// Sends out a datagram or stream of bytes on this socket
255    fn send(&mut self, data: Bytes) -> Result<usize>;
256
257    /// FLushes all the datagrams
258    fn flush(&mut self) -> Result<()>;
259
260    /// Recv a packet from the socket
261    fn recv(&mut self) -> Result<SocketReceive>;
262}
263
264/// Connected sockets have a persistent connection to a remote peer
265pub trait VirtualConnectedSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
266    /// Determines how long the socket will remain in a TIME_WAIT
267    /// after it disconnects (only the one that initiates the close will
268    /// be in a TIME_WAIT state thus the clients should always do this rather
269    /// than the server)
270    fn set_linger(&mut self, linger: Option<Duration>) -> Result<()>;
271
272    /// Returns how long the socket will remain in a TIME_WAIT
273    /// after it disconnects
274    fn linger(&self) -> Result<Option<Duration>>;
275
276    /// Sends out a datagram or stream of bytes on this socket
277    fn send(&mut self, data: Bytes) -> Result<usize>;
278
279    /// FLushes all the datagrams
280    fn flush(&mut self) -> Result<()>;
281
282    /// Recv a packet from the socket
283    fn recv(&mut self) -> Result<SocketReceive>;
284
285    /// Peeks for a packet from the socket
286    fn peek(&mut self) -> Result<SocketReceive>;
287}
288
289/// Connectionless sockets are able to send and receive datagrams and stream
290/// bytes to multiple addresses at the same time (peer-to-peer)
291pub trait VirtualConnectionlessSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
292    /// Sends out a datagram or stream of bytes on this socket
293    /// to a specific address
294    fn send_to(&mut self, data: Bytes, addr: SocketAddr) -> Result<usize>;
295
296    /// Recv a packet from the socket
297    fn recv_from(&mut self) -> Result<SocketReceiveFrom>;
298
299    /// Peeks for a packet from the socket
300    fn peek_from(&mut self) -> Result<SocketReceiveFrom>;
301}
302
303/// ICMP sockets are low level devices bound to a specific address
304/// that can send and receive ICMP packets
305pub trait VirtualIcmpSocket:
306    VirtualConnectionlessSocket + fmt::Debug + Send + Sync + 'static
307{
308}
309
310pub trait VirtualRawSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
311    /// Sends out a raw packet on this socket
312    fn send(&mut self, data: Bytes) -> Result<usize>;
313
314    /// FLushes all the datagrams
315    fn flush(&mut self) -> Result<()>;
316
317    /// Recv a packet from the socket
318    fn recv(&mut self) -> Result<SocketReceive>;
319
320    /// Tells the raw socket and its backing switch that all packets
321    /// should be received by this socket even if they are not
322    /// destined for this device
323    fn set_promiscuous(&mut self, promiscuous: bool) -> Result<()>;
324
325    /// Returns if the socket is running in promiscuous mode whereby it
326    /// will receive all packets even if they are not destined for the
327    /// local interface
328    fn promiscuous(&self) -> Result<bool>;
329}
330
331#[derive(Debug, Copy, Clone, PartialEq, Eq)]
332pub enum TimeType {
333    ReadTimeout,
334    WriteTimeout,
335    AcceptTimeout,
336    ConnectTimeout,
337    Linger,
338}
339
340pub trait VirtualTcpSocket: VirtualConnectedSocket + fmt::Debug + Send + Sync + 'static {
341    /// Sets the timeout for a specific action on the socket
342    fn set_opt_time(&mut self, ty: TimeType, timeout: Option<Duration>) -> Result<()>;
343
344    /// Returns one of the previous set timeouts
345    fn opt_time(&self, ty: TimeType) -> Result<Option<Duration>>;
346
347    /// Sets the receive buffer size which acts as a trottle for how
348    /// much data is buffered on this side of the pipe
349    fn set_recv_buf_size(&mut self, size: usize) -> Result<()>;
350
351    /// Size of the receive buffer that holds all data that has not
352    /// yet been read
353    fn recv_buf_size(&self) -> Result<usize>;
354
355    /// Sets the size of the send buffer which will hold the bytes of
356    /// data while they are being sent over to the peer
357    fn set_send_buf_size(&mut self, size: usize) -> Result<()>;
358
359    /// Size of the send buffer that holds all data that is currently
360    /// being transmitted.
361    fn send_buf_size(&self) -> Result<usize>;
362
363    /// When NO_DELAY is set the data that needs to be transmitted to
364    /// the peer is sent immediately rather than waiting for a bigger
365    /// batch of data, this reduces latency but increases encapsulation
366    /// overhead.
367    fn set_nodelay(&mut self, reuse: bool) -> Result<()>;
368
369    /// Indicates if the NO_DELAY flag is set which means that data
370    /// is immediately sent to the peer without waiting. This reduces
371    /// latency but increases encapsulation overhead.
372    fn nodelay(&self) -> Result<bool>;
373
374    /// Returns the address (IP and Port) of the peer socket that this
375    /// is conencted to
376    fn addr_peer(&self) -> Result<SocketAddr>;
377
378    /// Causes all the data held in the send buffer to be immediately
379    /// flushed to the destination peer
380    fn flush(&mut self) -> Result<()>;
381
382    /// Shuts down either the READER or WRITER sides of the socket
383    /// connection.
384    fn shutdown(&mut self, how: Shutdown) -> Result<()>;
385}
386
387pub trait VirtualUdpSocket:
388    VirtualConnectedSocket + VirtualConnectionlessSocket + fmt::Debug + Send + Sync + 'static
389{
390    /// Connects to a destination peer so that the normal
391    /// send/recv operations can be used.
392    fn connect(&mut self, addr: SocketAddr) -> Result<()>;
393
394    /// Sets a flag that means that the UDP socket is able
395    /// to receive and process broadcast packets.
396    fn set_broadcast(&mut self, broadcast: bool) -> Result<()>;
397
398    /// Indicates if the SO_BROADCAST flag is set which means
399    /// that the UDP socket will receive and process broadcast
400    /// packets
401    fn broadcast(&self) -> Result<bool>;
402
403    /// Sets a flag that indicates if multicast packets that
404    /// this socket is a member of will be looped back to
405    /// the sending socket. This applies to IPv4 addresses
406    fn set_multicast_loop_v4(&mut self, val: bool) -> Result<()>;
407
408    /// Gets a flag that indicates if multicast packets that
409    /// this socket is a member of will be looped back to
410    /// the sending socket. This applies to IPv4 addresses
411    fn multicast_loop_v4(&self) -> Result<bool>;
412
413    /// Sets a flag that indicates if multicast packets that
414    /// this socket is a member of will be looped back to
415    /// the sending socket. This applies to IPv6 addresses
416    fn set_multicast_loop_v6(&mut self, val: bool) -> Result<()>;
417
418    /// Gets a flag that indicates if multicast packets that
419    /// this socket is a member of will be looped back to
420    /// the sending socket. This applies to IPv6 addresses
421    fn multicast_loop_v6(&self) -> Result<bool>;
422
423    /// Sets the TTL for IPv4 multicast packets which is the
424    /// number of network hops before the packet is dropped
425    fn set_multicast_ttl_v4(&mut self, ttl: u32) -> Result<()>;
426
427    /// Gets the TTL for IPv4 multicast packets which is the
428    /// number of network hops before the packet is dropped
429    fn multicast_ttl_v4(&self) -> Result<u32>;
430
431    /// Tells this interface that it will subscribe to a
432    /// particular multicast address. This applies to IPv4 addresses
433    fn join_multicast_v4(&mut self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<()>;
434
435    /// Tells this interface that it will unsubscribe to a
436    /// particular multicast address. This applies to IPv4 addresses
437    fn leave_multicast_v4(&mut self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<()>;
438
439    /// Tells this interface that it will subscribe to a
440    /// particular multicast address. This applies to IPv6 addresses
441    fn join_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<()>;
442
443    /// Tells this interface that it will unsubscribe to a
444    /// particular multicast address. This applies to IPv6 addresses
445    fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<()>;
446
447    /// Returns the remote address of this UDP socket if it has been
448    /// connected to a specific target destination address
449    fn addr_peer(&self) -> Result<Option<SocketAddr>>;
450}
451
452#[derive(Debug, Default)]
453pub struct UnsupportedVirtualNetworking {}
454
455impl VirtualNetworking for UnsupportedVirtualNetworking {
456    fn ws_connect(&self, _url: &str) -> Result<Box<dyn VirtualWebSocket + Sync>> {
457        Err(NetworkError::Unsupported)
458    }
459
460    fn http_request(
461        &self,
462        _url: &str,
463        _method: &str,
464        _headers: &str,
465        _gzip: bool,
466    ) -> Result<SocketHttpRequest> {
467        Err(NetworkError::Unsupported)
468    }
469
470    fn bridge(&self, _network: &str, _access_token: &str, _security: StreamSecurity) -> Result<()> {
471        Err(NetworkError::Unsupported)
472    }
473
474    fn unbridge(&self) -> Result<()> {
475        Err(NetworkError::Unsupported)
476    }
477
478    fn dhcp_acquire(&self) -> Result<Vec<IpAddr>> {
479        Err(NetworkError::Unsupported)
480    }
481
482    fn ip_add(&self, _ip: IpAddr, _prefix: u8) -> Result<()> {
483        Err(NetworkError::Unsupported)
484    }
485
486    fn ip_remove(&self, _ip: IpAddr) -> Result<()> {
487        Err(NetworkError::Unsupported)
488    }
489
490    fn ip_clear(&self) -> Result<()> {
491        Err(NetworkError::Unsupported)
492    }
493
494    fn ip_list(&self) -> Result<Vec<IpCidr>> {
495        Err(NetworkError::Unsupported)
496    }
497
498    fn mac(&self) -> Result<[u8; 6]> {
499        Err(NetworkError::Unsupported)
500    }
501
502    fn gateway_set(&self, _ip: IpAddr) -> Result<()> {
503        Err(NetworkError::Unsupported)
504    }
505
506    fn route_add(
507        &self,
508        _cidr: IpCidr,
509        _via_router: IpAddr,
510        _preferred_until: Option<Duration>,
511        _expires_at: Option<Duration>,
512    ) -> Result<()> {
513        Err(NetworkError::Unsupported)
514    }
515
516    fn route_remove(&self, _cidr: IpAddr) -> Result<()> {
517        Err(NetworkError::Unsupported)
518    }
519
520    fn route_clear(&self) -> Result<()> {
521        Err(NetworkError::Unsupported)
522    }
523
524    fn route_list(&self) -> Result<Vec<IpRoute>> {
525        Err(NetworkError::Unsupported)
526    }
527
528    fn bind_raw(&self) -> Result<Box<dyn VirtualRawSocket + Sync>> {
529        Err(NetworkError::Unsupported)
530    }
531
532    fn bind_icmp(&self, _addr: IpAddr) -> Result<Box<dyn VirtualIcmpSocket + Sync>> {
533        Err(NetworkError::Unsupported)
534    }
535
536    fn listen_tcp(
537        &self,
538        _addr: SocketAddr,
539        _only_v6: bool,
540        _reuse_port: bool,
541        _reuse_addr: bool,
542    ) -> Result<Box<dyn VirtualTcpListener + Sync>> {
543        Err(NetworkError::Unsupported)
544    }
545
546    fn connect_tcp(
547        &self,
548        _addr: SocketAddr,
549        _peer: SocketAddr,
550        _timeout: Option<Duration>,
551    ) -> Result<Box<dyn VirtualTcpSocket + Sync>> {
552        Err(NetworkError::Unsupported)
553    }
554
555    fn bind_udp(
556        &self,
557        _addr: SocketAddr,
558        _reuse_port: bool,
559        _reuse_addr: bool,
560    ) -> Result<Box<dyn VirtualUdpSocket + Sync>> {
561        Err(NetworkError::Unsupported)
562    }
563
564    fn resolve(
565        &self,
566        _host: &str,
567        _port: Option<u16>,
568        _dns_server: Option<IpAddr>,
569    ) -> Result<Vec<IpAddr>> {
570        Err(NetworkError::Unsupported)
571    }
572}
573
574#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
575pub enum NetworkError {
576    /// The handle given was not usable
577    #[error("invalid fd")]
578    InvalidFd,
579    /// File exists
580    #[error("file exists")]
581    AlreadyExists,
582    /// The filesystem has failed to lock a resource.
583    #[error("lock error")]
584    Lock,
585    /// Something failed when doing IO. These errors can generally not be handled.
586    /// It may work if tried again.
587    #[error("io error")]
588    IOError,
589    /// The address was in use
590    #[error("address is in use")]
591    AddressInUse,
592    /// The address could not be found
593    #[error("address could not be found")]
594    AddressNotAvailable,
595    /// A pipe was closed
596    #[error("broken pipe (was closed)")]
597    BrokenPipe,
598    /// The connection was aborted
599    #[error("connection aborted")]
600    ConnectionAborted,
601    /// The connection request was refused
602    #[error("connection refused")]
603    ConnectionRefused,
604    /// The connection was reset
605    #[error("connection reset")]
606    ConnectionReset,
607    /// The operation was interrupted before it could finish
608    #[error("operation interrupted")]
609    Interrupted,
610    /// Invalid internal data, if the argument data is invalid, use `InvalidInput`
611    #[error("invalid internal data")]
612    InvalidData,
613    /// The provided data is invalid
614    #[error("invalid input")]
615    InvalidInput,
616    /// Could not perform the operation because there was not an open connection
617    #[error("connection is not open")]
618    NotConnected,
619    /// The requested device couldn't be accessed
620    #[error("can't access device")]
621    NoDevice,
622    /// Caller was not allowed to perform this operation
623    #[error("permission denied")]
624    PermissionDenied,
625    /// The operation did not complete within the given amount of time
626    #[error("time out")]
627    TimedOut,
628    /// Found EOF when EOF was not expected
629    #[error("unexpected eof")]
630    UnexpectedEof,
631    /// Operation would block, this error lets the caller know that they can try again
632    #[error("blocking operation. try again")]
633    WouldBlock,
634    /// A call to write returned 0
635    #[error("write returned 0")]
636    WriteZero,
637    /// The operation is not supported.
638    #[error("unsupported")]
639    Unsupported,
640    /// Some other unhandled error. If you see this, it's probably a bug.
641    #[error("unknown error found")]
642    UnknownError,
643}
644
645pub fn net_error_into_io_err(net_error: NetworkError) -> std::io::Error {
646    use std::io::ErrorKind;
647    match net_error {
648        NetworkError::InvalidFd => ErrorKind::BrokenPipe.into(),
649        NetworkError::AlreadyExists => ErrorKind::AlreadyExists.into(),
650        NetworkError::Lock => ErrorKind::BrokenPipe.into(),
651        NetworkError::IOError => ErrorKind::BrokenPipe.into(),
652        NetworkError::AddressInUse => ErrorKind::AddrInUse.into(),
653        NetworkError::AddressNotAvailable => ErrorKind::AddrNotAvailable.into(),
654        NetworkError::BrokenPipe => ErrorKind::BrokenPipe.into(),
655        NetworkError::ConnectionAborted => ErrorKind::ConnectionAborted.into(),
656        NetworkError::ConnectionRefused => ErrorKind::ConnectionRefused.into(),
657        NetworkError::ConnectionReset => ErrorKind::ConnectionReset.into(),
658        NetworkError::Interrupted => ErrorKind::Interrupted.into(),
659        NetworkError::InvalidData => ErrorKind::InvalidData.into(),
660        NetworkError::InvalidInput => ErrorKind::InvalidInput.into(),
661        NetworkError::NotConnected => ErrorKind::NotConnected.into(),
662        NetworkError::NoDevice => ErrorKind::BrokenPipe.into(),
663        NetworkError::PermissionDenied => ErrorKind::PermissionDenied.into(),
664        NetworkError::TimedOut => ErrorKind::TimedOut.into(),
665        NetworkError::UnexpectedEof => ErrorKind::UnexpectedEof.into(),
666        NetworkError::WouldBlock => ErrorKind::WouldBlock.into(),
667        NetworkError::WriteZero => ErrorKind::WriteZero.into(),
668        NetworkError::Unsupported => ErrorKind::Unsupported.into(),
669        NetworkError::UnknownError => ErrorKind::BrokenPipe.into(),
670    }
671}
672
673pub fn io_err_into_net_error(net_error: std::io::Error) -> NetworkError {
674    use std::io::ErrorKind;
675    match net_error.kind() {
676        ErrorKind::BrokenPipe => NetworkError::BrokenPipe,
677        ErrorKind::AlreadyExists => NetworkError::AlreadyExists,
678        ErrorKind::AddrInUse => NetworkError::AddressInUse,
679        ErrorKind::AddrNotAvailable => NetworkError::AddressNotAvailable,
680        ErrorKind::ConnectionAborted => NetworkError::ConnectionAborted,
681        ErrorKind::ConnectionRefused => NetworkError::ConnectionRefused,
682        ErrorKind::ConnectionReset => NetworkError::ConnectionReset,
683        ErrorKind::Interrupted => NetworkError::Interrupted,
684        ErrorKind::InvalidData => NetworkError::InvalidData,
685        ErrorKind::InvalidInput => NetworkError::InvalidInput,
686        ErrorKind::NotConnected => NetworkError::NotConnected,
687        ErrorKind::PermissionDenied => NetworkError::PermissionDenied,
688        ErrorKind::TimedOut => NetworkError::TimedOut,
689        ErrorKind::UnexpectedEof => NetworkError::UnexpectedEof,
690        ErrorKind::WouldBlock => NetworkError::WouldBlock,
691        ErrorKind::WriteZero => NetworkError::WriteZero,
692        ErrorKind::Unsupported => NetworkError::Unsupported,
693        _ => NetworkError::UnknownError,
694    }
695}