Using Linux's `epoll(7)` interface, a `EPOLLHUP` condition is
signalled for the reading end of a pipe or socket when the other end
is closed for writing. This may happen in combination with `EPOLLIN`
being signalled (if further data is available for reading), or with
`EPOLLIN`.
If `EPOLLHUP` is signalled without `EPOLLIN` it indicates an immediate
EOF condition, which will result in the next `read()` suceeding with 0
bytes read. It is thus not required to handle `EPOLLHUP` specially in
the reader, but we need to indicate readiness upon encountering it.
Looking at the `kqueue` and `windows` mio backends, they seem to be
turn a detected EOF and connection reset into `mio::Ready::hup()`
events, so it may be reasonable to speculate that this change is an
improvement for these platforms as well.
Fixes#117.
* Move to `std::net` as it's all purely UDP related
* Rename to `UdpCodec` and `UdpFramed` to give a consistent `Udp` prefix
* Add `RecvDgram`, rename `SendDGram` to `SendDgram`
* Touch up some style here and there
This commit makes a few changes to the Sink implementation on Framed:
* Backpressure is implemented for `start_send`. If the write buffer is
over 8KiB and can't be flushed, no new items are accepted.
* 0 length writes to the upstream transport are translated into a
`WriteZero` error, as with `io::Write::write_all`. `write_all` checks
for and ignores `Interrupted` errors, but I do not think this is
necessary for non-blocking writes.
* In `poll_complete`, the upstream transport is not flushed until
*after* writing the entire write buffer.
traits into `Codec`
A previous commit refactored such that `Encode` and `Decode` are
implemented directly on the types being encoded or decoded. This was
thought to be less expressive but more convenient than having a separate
notion of a (stateful) encoder or decoder.
However, there are certain situations where the approach is just too
limiting: you're required to implemented `Decode` and `Encode` for types
you don't "own" and can't newtype.
This commit moves back to a setup where `Self` represents the
encoder/decoder state; it also merges the two traits into a single
`Codec` trait, since they are currently always used together.
- Gets rid of `easy` module, instead providing framing support directly
in the `io` module.
- In particular, adds a framing adapter directly to the `Io` trait,
which gives you a Stream + Sink object. That object can then be
`split` into separate `Stream` and `Sink` objects if needed.
- Deprecates the `FramedIo` trait; that's now just Stream + Sink.
- Updates the line framing test to use the stream/sink combinators.
Typically this happens automatically as the `E` in `PollEvented<E>` is an owned
reference (e.g. a `TcpStream`) where dropping that will close the resource,
automatically unregistering it from the event loop. In some situations, however,
this isn't always the case, so the deregistering needs to happen manually.
This commit makes a few tweaks to the new `easy` module:
- Rename `Parse` to `Decode`, and `Serialize` to `Encode`.
- Don't use `Poll` for the `decode` method; we prefer to reserve
that type for actual aync events, and in particular for a `NotReady`
result to imply that some task scheduling has taken place. Instead,
use an internal `Option`.
This commit extracts the concrete implementation of `FrameIo` in tokio-proto to
tokio-core under the name `EasyFramed`. This extraction is accompanied with a
new `EasyBuf` buffer type to work with when parsing types.
The purpose of this movement is to provide a clear and easy entry point at the
`FramedIo` layer for those who need it. Eventually these buffer types will get
replaced or moved to the `bytes` crate, but in the interest of an 0.1 release
and remaining backwards compatible with the tokio-core 0.1 release this is
adding a separate module.
The other read futures (read_exact, read_until, etc.) all expose their
concrete future types so that function signatures can return them, but
until now `read()` didn't. Exposing it with the name "Read" causes
naming conflicts with the std::io::Read trait, so the easiest thing to
do is to just change the name. Importing std::io::Read under a different
name would've been an option too, but that would probably be annoying
for consumers in the same way it's annoying for us.
The original PR (https://github.com/tokio-rs/tokio-core/pull/29) decided
that "read" was a better name than "read_some", so I'm leaving the top
level functions unchanged. I don't have a strong opinion about it one
way or the other, but I *do* think it's worth bikeshedding a little bit.
Python's asyncio library actually ended up with a very similar issue
around naming inconsistency between the sync and async worlds, and we
can hopefully avoid repeating that: https://bugs.python.org/issue22279