renet/src/socket/mod.rs

161 lines
5.4 KiB
Rust
Raw Normal View History

2016-12-15 01:39:44 +08:00
//! Communication between endpoints.
//!
//! The `socket` module deals with *network endpoints* and *buffering*.
//! It provides interfaces for accessing buffers of data, and protocol state machines
//! for filling and emptying these buffers.
//!
//! The programming interface implemented here differs greatly from the common Berkeley socket
//! interface. Specifically, in the Berkeley interface the buffering is implicit:
//! the operating system decides on the good size for a buffer and manages it.
//! The interface implemented by this module uses explicit buffering: you decide on the good
//! size for a buffer, allocate it, and let the networking stack use it.
use core::marker::PhantomData;
2016-12-15 01:39:44 +08:00
#[cfg(feature = "socket-raw")]
mod raw;
#[cfg(feature = "socket-icmp")]
mod icmp;
#[cfg(feature = "socket-udp")]
mod udp;
#[cfg(feature = "socket-tcp")]
mod tcp;
2017-01-11 12:05:41 +08:00
mod set;
mod ref_;
2016-12-15 01:39:44 +08:00
#[cfg(feature = "socket-raw")]
pub use self::raw::{PacketBuffer as RawPacketBuffer,
SocketBuffer as RawSocketBuffer,
RawSocket};
2017-06-18 18:14:20 +08:00
#[cfg(feature = "socket-icmp")]
pub use self::icmp::{PacketBuffer as IcmpPacketBuffer,
SocketBuffer as IcmpSocketBuffer,
Endpoint as IcmpEndpoint,
IcmpSocket};
#[cfg(feature = "socket-udp")]
pub use self::udp::{PacketBuffer as UdpPacketBuffer,
SocketBuffer as UdpSocketBuffer,
UdpSocket};
#[cfg(feature = "socket-tcp")]
pub use self::tcp::{SocketBuffer as TcpSocketBuffer,
State as TcpState,
TcpSocket};
2016-12-19 03:40:11 +08:00
pub use self::set::{Set as SocketSet, Item as SocketSetItem, Handle as SocketHandle};
2017-01-11 12:05:41 +08:00
pub use self::set::{Iter as SocketSetIter, IterMut as SocketSetIterMut};
pub use self::ref_::Ref as SocketRef;
pub(crate) use self::ref_::Session as SocketSession;
/// A network socket.
///
2016-12-17 13:12:45 +08:00
/// This enumeration abstracts the various types of sockets based on the IP protocol.
/// To downcast a `Socket` value to a concrete socket, use the [AnySocket] trait,
/// e.g. to get `UdpSocket`, call `UdpSocket::downcast(socket)`.
///
/// It is usually more convenient to use [SocketSet::get] instead.
///
/// [AnySocket]: trait.AnySocket.html
/// [SocketSet::get]: struct.SocketSet.html#method.get
2017-01-12 12:28:34 +08:00
#[derive(Debug)]
2016-12-17 14:27:08 +08:00
pub enum Socket<'a, 'b: 'a> {
#[cfg(feature = "socket-raw")]
2017-06-18 18:14:20 +08:00
Raw(RawSocket<'a, 'b>),
#[cfg(feature = "socket-icmp")]
Icmp(IcmpSocket<'a, 'b>),
#[cfg(feature = "socket-udp")]
2016-12-23 15:30:57 +08:00
Udp(UdpSocket<'a, 'b>),
#[cfg(feature = "socket-tcp")]
2016-12-23 15:30:57 +08:00
Tcp(TcpSocket<'a>),
2016-12-17 13:12:45 +08:00
#[doc(hidden)]
__Nonexhaustive(PhantomData<(&'a (), &'b ())>)
2016-12-17 13:12:45 +08:00
}
/// Network socket metadata.
///
/// This includes things that only external (to the socket, that is) code
/// is interested in, but which are more conveniently stored inside the socket itself.
#[derive(Debug, Default)]
pub(crate) struct SocketMeta {
/// Handle of this socket within its enclosing `SocketSet`.
/// Mainly useful for debug output.
pub(crate) handle: SocketHandle,
/// A lower limit on the timestamp returned from the socket's `poll_at()` method.
pub(crate) hushed_until: Option<u64>,
}
macro_rules! dispatch_socket {
($self_:expr, |$socket:ident [$( $mut_:tt )*]| $code:expr) => ({
match $self_ {
#[cfg(feature = "socket-raw")]
2017-06-18 18:14:20 +08:00
&$( $mut_ )* Socket::Raw(ref $( $mut_ )* $socket) => $code,
#[cfg(feature = "socket-icmp")]
&$( $mut_ )* Socket::Icmp(ref $( $mut_ )* $socket) => $code,
#[cfg(feature = "socket-udp")]
&$( $mut_ )* Socket::Udp(ref $( $mut_ )* $socket) => $code,
#[cfg(feature = "socket-tcp")]
&$( $mut_ )* Socket::Tcp(ref $( $mut_ )* $socket) => $code,
&$( $mut_ )* Socket::__Nonexhaustive(_) => unreachable!()
}
})
}
2016-12-17 14:27:08 +08:00
impl<'a, 'b> Socket<'a, 'b> {
/// Return the socket handle.
#[inline]
pub fn handle(&self) -> SocketHandle {
self.meta().handle
}
pub(crate) fn meta(&self) -> &SocketMeta {
dispatch_socket!(self, |socket []| &socket.meta)
}
pub(crate) fn meta_mut(&mut self) -> &mut SocketMeta {
dispatch_socket!(self, |socket [mut]| &mut socket.meta)
}
pub(crate) fn poll_at(&self) -> Option<u64> {
let poll_at = dispatch_socket!(self, |socket []| socket.poll_at());
self.meta().hushed_until.or(poll_at)
}
}
impl<'a, 'b> SocketSession for Socket<'a, 'b> {
fn finish(&mut self) {
dispatch_socket!(self, |socket [mut]| socket.finish())
}
}
2016-12-17 13:12:45 +08:00
/// A conversion trait for network sockets.
pub trait AnySocket<'a, 'b>: SocketSession + Sized {
fn downcast<'c>(socket_ref: SocketRef<'c, Socket<'a, 'b>>) ->
Option<SocketRef<'c, Self>>;
2017-06-18 18:14:20 +08:00
}
macro_rules! from_socket {
2017-07-25 01:00:00 +08:00
($socket:ty, $variant:ident) => {
impl<'a, 'b> AnySocket<'a, 'b> for $socket {
fn downcast<'c>(ref_: SocketRef<'c, Socket<'a, 'b>>) ->
Option<SocketRef<'c, Self>> {
match SocketRef::into_inner(ref_) {
&mut Socket::$variant(ref mut socket) => Some(SocketRef::new(socket)),
_ => None,
}
2017-07-25 01:00:00 +08:00
}
2017-06-18 18:14:20 +08:00
}
}
}
2016-12-21 03:51:52 +08:00
#[cfg(feature = "socket-raw")]
from_socket!(RawSocket<'a, 'b>, Raw);
#[cfg(feature = "socket-icmp")]
from_socket!(IcmpSocket<'a, 'b>, Icmp);
#[cfg(feature = "socket-udp")]
from_socket!(UdpSocket<'a, 'b>, Udp);
#[cfg(feature = "socket-tcp")]
from_socket!(TcpSocket<'a>, Tcp);