Files
tokio/src/net/udp/frame.rs
T

180 lines
6.0 KiB
Rust
Raw Normal View History

2016-11-22 11:48:09 -08:00
use std::io;
use std::net::{SocketAddr, Ipv4Addr, SocketAddrV4};
use futures::{Async, Poll, Stream, Sink, StartSend, AsyncSink};
use net::UdpSocket;
2017-12-05 16:55:25 +01:00
/// Encoding of datagrams into frames via buffers.
2016-11-22 11:48:09 -08:00
///
/// This trait is used when constructing an instance of `UdpFramed` and provides
/// the `In` and `Out` types which are decoded and encoded from the socket,
/// respectively.
///
/// Because UDP is a connectionless protocol, the `decode` method receives the
/// address where data came from and the `encode` method is also responsible for
/// determining the remote host to which the datagram should be sent
///
/// The trait itself is implemented on a type that can track state for decoding
/// or encoding, which is particularly useful for streaming parsers. In many
/// cases, though, this type will simply be a unit struct (e.g. `struct
2017-12-05 16:55:25 +01:00
/// MyCodec`).
2016-11-22 11:48:09 -08:00
pub trait UdpCodec {
/// The type of decoded frames.
type In;
/// The type of frames to be encoded.
type Out;
2018-01-16 19:49:59 +03:00
/// The type of unrecoverable frame encoding/decoding errors.
///
/// If an individual message is ill-formed but can be ignored without
/// interfering with the processing of future messages, it may be more
/// useful to report the failure as an `Item`.
///
/// Note that implementors of this trait can simply indicate `type Error =
/// io::Error` to use I/O errors as this type.
type Error: From<io::Error>;
2016-11-22 11:48:09 -08:00
/// Attempts to decode a frame from the provided buffer of bytes.
///
/// This method is called by `UdpFramed` on a single datagram which has been
/// read from a socket. The `buf` argument contains the data that was
/// received from the remote address, and `src` is the address the data came
/// from. Note that typically this method should require the entire contents
/// of `buf` to be valid or otherwise return an error with trailing data.
///
/// Finally, if the bytes in the buffer are malformed then an error is
/// returned indicating why. This informs `Framed` that the stream is now
/// corrupt and should be terminated.
2018-01-16 19:49:59 +03:00
fn decode(&mut self, src: &SocketAddr, buf: &[u8]) -> Result<Self::In, Self::Error>;
2016-11-22 11:48:09 -08:00
/// Encodes a frame into the buffer provided.
///
/// This method will encode `msg` into the byte buffer provided by `buf`.
/// The `buf` provided is an internal buffer of the `Framed` instance and
/// will be written out when possible.
///
/// The encode method also determines the destination to which the buffer
/// should be directed, which will be returned as a `SocketAddr`.
2018-01-16 19:49:59 +03:00
fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> Result<SocketAddr, Self::Error>;
2016-11-22 11:48:09 -08:00
}
/// A unified `Stream` and `Sink` interface to an underlying `UdpSocket`, using
/// the `UdpCodec` trait to encode and decode frames.
///
/// You can acquire a `UdpFramed` instance by using the `UdpSocket::framed`
/// adapter.
2017-10-25 18:03:31 -07:00
#[must_use = "sinks do nothing unless polled"]
2017-12-06 17:19:21 +01:00
#[derive(Debug)]
2016-11-22 11:48:09 -08:00
pub struct UdpFramed<C> {
socket: UdpSocket,
codec: C,
rd: Vec<u8>,
wr: Vec<u8>,
out_addr: SocketAddr,
2017-09-11 15:56:41 +02:00
flushed: bool,
2016-11-22 11:48:09 -08:00
}
impl<C: UdpCodec> Stream for UdpFramed<C> {
type Item = C::In;
2018-01-16 19:49:59 +03:00
type Error = C::Error;
2016-11-22 11:48:09 -08:00
2018-01-16 19:49:59 +03:00
fn poll(&mut self) -> Poll<Option<C::In>, C::Error> {
2016-11-22 11:48:09 -08:00
let (n, addr) = try_nb!(self.socket.recv_from(&mut self.rd));
trace!("received {} bytes, decoding", n);
2018-01-16 19:49:59 +03:00
let frame = self.codec.decode(&addr, &self.rd[..n])?;
2016-11-22 11:48:09 -08:00
trace!("frame decoded from buffer");
Ok(Async::Ready(Some(frame)))
}
}
impl<C: UdpCodec> Sink for UdpFramed<C> {
type SinkItem = C::Out;
2018-01-16 19:49:59 +03:00
type SinkError = C::Error;
2016-11-22 11:48:09 -08:00
2018-01-16 19:49:59 +03:00
fn start_send(&mut self, item: C::Out) -> StartSend<C::Out, C::Error> {
2017-09-11 15:56:41 +02:00
trace!("sending frame");
if !self.flushed {
match try!(self.poll_complete()) {
Async::Ready(()) => {},
Async::NotReady => return Ok(AsyncSink::NotReady(item)),
2016-11-22 11:48:09 -08:00
}
}
2018-01-16 19:49:59 +03:00
self.out_addr = self.codec.encode(item, &mut self.wr)?;
2017-09-11 15:56:41 +02:00
self.flushed = false;
trace!("frame encoded; length={}", self.wr.len());
2016-11-22 11:48:09 -08:00
Ok(AsyncSink::Ready)
}
2018-01-16 19:49:59 +03:00
fn poll_complete(&mut self) -> Poll<(), C::Error> {
2017-09-11 15:56:41 +02:00
if self.flushed {
2016-11-22 11:48:09 -08:00
return Ok(Async::Ready(()))
}
2017-09-11 15:56:41 +02:00
trace!("flushing frame; length={}", self.wr.len());
2016-11-22 11:48:09 -08:00
let n = try_nb!(self.socket.send_to(&self.wr, &self.out_addr));
trace!("written {}", n);
2017-09-11 15:56:41 +02:00
2016-11-22 11:48:09 -08:00
let wrote_all = n == self.wr.len();
self.wr.clear();
2017-09-11 15:56:41 +02:00
self.flushed = true;
2016-11-22 11:48:09 -08:00
if wrote_all {
Ok(Async::Ready(()))
} else {
Err(io::Error::new(io::ErrorKind::Other,
2018-01-16 19:49:59 +03:00
"failed to write entire datagram to socket").into())
2016-11-22 11:48:09 -08:00
}
}
2017-02-05 17:06:57 -08:00
2018-01-16 19:49:59 +03:00
fn close(&mut self) -> Poll<(), C::Error> {
2017-02-05 17:06:57 -08:00
try_ready!(self.poll_complete());
Ok(().into())
}
2016-11-22 11:48:09 -08:00
}
pub fn new<C: UdpCodec>(socket: UdpSocket, codec: C) -> UdpFramed<C> {
UdpFramed {
socket: socket,
codec: codec,
out_addr: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0)),
rd: vec![0; 64 * 1024],
wr: Vec::with_capacity(8 * 1024),
2017-09-11 15:56:41 +02:00
flushed: true,
2016-11-22 11:48:09 -08:00
}
}
impl<C> UdpFramed<C> {
/// Returns a reference to the underlying I/O stream wrapped by `Framed`.
///
2017-12-05 16:55:25 +01:00
/// # Note
///
/// Care should be taken to not tamper with the underlying stream of data
/// coming in as it may corrupt the stream of frames otherwise being worked
/// with.
2016-11-22 11:48:09 -08:00
pub fn get_ref(&self) -> &UdpSocket {
&self.socket
}
/// Returns a mutable reference to the underlying I/O stream wrapped by
/// `Framed`.
///
2017-12-05 16:55:25 +01:00
/// # Note
///
/// Care should be taken to not tamper with the underlying stream of data
/// coming in as it may corrupt the stream of frames otherwise being worked
/// with.
2016-11-22 11:48:09 -08:00
pub fn get_mut(&mut self) -> &mut UdpSocket {
&mut self.socket
}
/// Consumes the `Framed`, returning its underlying I/O stream.
pub fn into_inner(self) -> UdpSocket {
self.socket
}
}