384 Commits

Author SHA1 Message Date
Toralf Wittner
def2093c9a Remove bytes dependency.
The motivation for this change is the worry, that streams which do not
consume their buffers in a timely manner prevent `BytesMut` from reusing
their storage space, instead forcing it to allocate more memory.

This PR removes `bytes` completely and instead uses `Vec<u8>`s. The
reclamation of storage is left to the allocator.

While at it we also remove the `BufWriter` from `Io`. Often client code
already uses buffers and always adding another buffer layer seems
misguided. After all clients may always provide `Connection::new` with
a `BufWriter` type.
2020-03-17 18:22:53 +01:00
Toralf Wittner
247f715796 Merge branch 'develop' 2020-02-28 11:19:05 +01:00
Toralf Wittner
e559aa2795 Update CHANGELOG and increment version to 0.4.4. 2020-02-28 11:17:40 +01:00
Toralf Wittner
524589e813 Merge pull request #76 from twittner/dispose-on-error
Close control and stream channels on error.
2020-02-28 10:58:48 +01:00
Toralf Wittner
2c68345106 Close control and stream channels on error.
While `Connection::next_stream` must not be called after `Ok(None)`
or `Err(_)` client code may still attempt to submit control commands.
To ensure those are not pending forever, we close and drain the
control channel so further command submissions return immediately.

We already drop all streams when encountering an error which
prevents them from submitting more stream commands but while we
are at it we also close the stream command channel and drop all
enqueued messages now.

Finally we also rework `Control::close` and `Control::poll_close`
to map a closed channel to an early Ok as it means the connection
is already closed. This explicit mapping seems more appropriate
than returning an `Err(ConnectionError::Closed)`.
2020-02-27 09:57:25 +01:00
Toralf Wittner
58056d83e7 Merge branch 'develop' 2020-02-18 13:25:06 +01:00
Toralf Wittner
15d96b2609 Update CHANGELOG and increment to version 0.4.3. 2020-02-18 12:17:13 +01:00
Toralf Wittner
ddbd062664 Merge pull request #75 from twittner/update-nohash-hasher
Update nohash-hasher to v0.2.0.
2020-02-17 14:29:06 +01:00
Toralf Wittner
7438a50ce7 Update nohash-hasher to v0.2.0. 2020-02-17 12:58:16 +01:00
Toralf Wittner
86c906af8c Merge branch 'develop' 2020-02-04 15:59:58 +01:00
Toralf Wittner
374eaa5576 Merge pull request #74 from twittner/prepare-release
Prepare release 0.4.2.
2020-02-04 15:58:39 +01:00
Toralf Wittner
3dc0dfb875 Prepare release 0.4.2.
Update the CHANGELOG, increment the version number and explain
`Config::set_lazy_open` better.
2020-02-04 13:58:10 +01:00
Toralf Wittner
5f563c5ed2 Add trace log for initial window update frame. 2020-02-04 12:27:08 +01:00
Toralf Wittner
1db8c039a9 Merge pull request #73 from twittner/syn-ack
Send `ACK`s and enable deferred `SYN`s.
2020-02-04 11:05:21 +01:00
Toralf Wittner
b13d69d166 Fix doc comments.
Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com>
2020-02-04 10:44:39 +01:00
Toralf Wittner
19f4eb8874 Use enum struct for StreamCommand::CloseStream. 2020-01-30 12:51:55 +01:00
Toralf Wittner
c0f051d1ef Move flag setting logic into stream module.
This saves us from having to lookup the stream each time a `SendFrame`
stream command is processed in `Connection`.
2020-01-29 20:48:33 +01:00
Toralf Wittner
a5541a1ab6 Add an option to open outbound streams lazily.
The current behaviour is to always immediately send a `WindowUpdate`
frame to the remote when opening an outbound frame. While we do not wait
for an acknowledgement before we continue to send data over the stream,
we could also hold off and set the initial SYN flag in the first data
frame that is being sent over the new stream to the remote. The newly
added option `lazy_open` enables this. This should eventually become the
new default.

Implementation notice:

We currently check if we need to set flags when receiving a command from
the stream to send a frame. We might move this into the `stream` module
and make this decision local to the stream instead of looking up the
stream by ID. This would only require a bit more investigation for the
close case as the stream does currently not send a frame in this case on
which it could set the flag.
2020-01-29 18:30:45 +01:00
Toralf Wittner
58b078b4b9 Send back ACKs and use more principled casts.
Up to now we never replied to opened inbound streams with an ACK flag,
despite the fact that the spec clearly demands this behaviour. While we
continue to ignore any ACK flags we receive, with this change we properly
set an ACK flag if required.

Additionally, this PR makes casting of header and frame types more
principled. Instead of arbitrary casts only casts from `()` to `Data`,
`WindowUpdate` and `Ping` are allowed. We also model a binary sum type and
provide introductions from `T` to `Either<T, U>` and `T` to `Either<U, T>`
but no projections. This allows a more type-safe `StreamCommand` whose
`SendFrame` constructor only accepts `Frame<Either<Data, WindowUpdate>>`
values which is what we expect coming from streams.
2020-01-29 16:53:27 +01:00
Toralf Wittner
9816660bff Merge branch 'develop' 2020-01-28 11:30:34 +01:00
Toralf Wittner
2cac578e3a Update CHANGELOG and increment version to 0.4.1 2020-01-28 10:44:56 +01:00
Toralf Wittner
ab12b4717d Map connection resets to ConnectionError::Closed. (#72)
When encountering an I/O error with `ErrorKind::ConnectionReset`, map
this to a `ConnectionError::Closed` value. The remote may have closed
the connection and a host implementing a "half-duplex" close sequence
would send us a RST when we send data because we have not noticed the
close yet. By mapping this case to a `ConnectionError::Closed` error,
we effectively treat this case like any other connection close.
2020-01-28 10:34:11 +01:00
Toralf Wittner
172ab6551c Merge branch 'develop' 2019-12-30 11:53:01 +01:00
Toralf Wittner
b1d1713feb Prepare release 0.4.0 2019-12-30 11:52:31 +01:00
Toralf Wittner
035770ecc0 Merge branch 'develop' 2019-12-20 12:08:49 +01:00
Toralf Wittner
6d72fd4b99 Replace __Nonexhaustive with #[non_exhaustive] (#71) 2019-12-19 18:15:50 +01:00
Toralf Wittner
b9b2d86d38 Prepare 0.3 release. (#69)
Update CHANGELOG.
2019-12-05 15:57:52 +01:00
Toralf Wittner
db09e0d8a9 Add futures::stream::Stream impl for Stream. (#70)
The impl. produces `Packet`s which are simply newtype wrappers around
`Bytes` and expose only an `AsRef<[u8]>` interface. The
`futures::stream::Stream` implementation is more efficient than the
`AsyncRead` one as it does not need to copy the bytes.
2019-12-05 15:57:07 +01:00
Toralf Wittner
b62fb15cf2 Add test for Pausable. (#68) 2019-12-03 16:20:32 +01:00
Toralf Wittner
1ce27d0ac1 Allocate the whole frame body at once. (#67)
Instead of reading large bodies in `BLOCKSIZE` steps, ensure that the
buffer is large enough to hold the whole body which may result in less
`poll_read` calls.
2019-12-03 11:19:44 +01:00
Toralf Wittner
db11f03275 Merge pull request #65 from twittner/bytes-0.5 2019-12-02 17:41:51 +01:00
Toralf Wittner
41bb52765a Refactor unsafe code. 2019-12-02 00:05:59 +01:00
Toralf Wittner
855389a26c Use transmute to cast &mut [MaybeUninit<u8>]. 2019-11-28 14:55:56 +01:00
Toralf Wittner
0d1d0f1ea9 Update async-std dev-dependency. 2019-11-27 23:40:05 +01:00
Toralf Wittner
69cf362bca Update to bytes-0.5
Some notable changes:

- `BytesMut::bytes_mut` now returns a `&mut [MaybeUninit<u8>]` as it may
contain uninitialised memory. Since we resize our buffer which implies
initialisation, we can just cast this slice to a `&mut [u8]` and use it
directly.

- `BytesMut::remaining_mut` no longer gives the length of the
`BytesMut::bytes_mut` as the `BufMut` implementation grows the buffer as
needed. So, to figure out if we need to reserve another BLOCKSIZE chunk we
now check how much capacity is left.

- `futures_codec` has been removed from tests as it has not updated to
bytes-0.5. The tests now work directly with the stream as `AsyncRead`
and `AsyncWrite` impl.
2019-11-27 14:51:18 +01:00
Toralf Wittner
93dd1b3093 Do not export stream::State. (#64) 2019-11-27 14:49:49 +01:00
Toralf Wittner
c52bb455cf Merge pull request #63 from twittner/eof
Fix EOF handling in `Io::poll_next`.
2019-11-23 12:39:38 +01:00
Toralf Wittner
afd5b5d12f Fix EOF handling in Io::poll_next.
Currently we always error when reading 0 bytes, however the correct
thing to do is to signal the end of the stream iff there are no unparsed
bytes in our buffer.
2019-11-22 16:11:12 +01:00
Toralf Wittner
ac49b977d2 Merge pull request #62 from twittner/develop
Make `Stream::state` private to the crate.
2019-11-20 10:41:06 +01:00
Toralf Wittner
c39a6a803d Make Stream::state private to the crate.
Keep the public API surface minimal. We may at some point replace the
`Mutex` around `Shared` with a futures-aware lock at which point
`Stream::state` would no longer be a synchronous method. As the method
is not used externally yet it is best not to introduce at this point.
Since we nevertheless use this in our tests, smoke.rs has been moved
crate.
2019-11-20 10:25:51 +01:00
Toralf Wittner
c5c95e8524 Merge pull request #60 from twittner/futures-0.3
Update to futures-0.3
2019-11-15 15:32:42 +01:00
Toralf Wittner
a93b9af9e4 Update async-std to 1.0. 2019-11-11 18:57:07 +01:00
Toralf Wittner
432af5e0e5 Remove use_unitialised_read_buffer feature. 2019-11-11 18:38:33 +01:00
Toralf Wittner
25ef6e2e24 Update to futures-0.3.
- Remove `futures_codec` dependency.
- Replace `header::Codec` with `header::{encode, decode}` functions.
- Add `frame::io` module which contains the `Io` type which decodes
frames, implements `futures::stream::Stream` and also allows writing
frames (buffered) to the socket.
- Remove the `tokio` benchmarks as they are very similar to the
`async-std` ones and allow us to remove one (dev) dependency.
- Add a `use_unitialised_read_buffer` feature to allow reading from the
`AsyncRead` value without having to zero memory first which has a
noticable cost. Since the initializer parts for `AsyncRead` are unstable
we provide this opt-in feature instead.
2019-11-11 18:10:57 +01:00
Toralf Wittner
035a2a93c6 Merge pull request #59 from twittner/develop
Upgrade to async/await and futures-preview.
2019-11-06 14:40:46 +01:00
Toralf Wittner
bdb72399ae Address review suggestions. 2019-11-06 08:28:42 +01:00
Toralf Wittner
3dd2f96907 Make explicit that cancellation is not supported.
In order to make `Connection` cancellation-safe we would need to store a
bunch of data in `Self` across yield points. This complicates matters
and requires even more work to make it efficient so for the time being
cancellation is not supported.
2019-11-05 18:26:15 +01:00
Toralf Wittner
b19f495d87 Add Drop impl for Connection.
We want to make sure that even if users do not drive
`Connection::next_stream` to completion that all `Stream`s are closed
and pending `Waker`s notified when we have reached end of life, so we
close them all in a `Drop` impl.

Also, since we close the socket anyway only when things work out the way
they should be we move the close call to the location where it is
expected to happen, namely when reaching the end of the control command
queue.
2019-11-05 16:02:30 +01:00
Toralf Wittner
ec769056f9 Fix Connection::next.
The current implementation based on `futures::select!` may miss values
produced by some of the selected futures. Because only one value is
(pseudo-randomly) returned when multiple futures are ready, the
non-selected one may be ignored. This can happen for instance if we
got a new inbound connection stream, which we return to the caller which
causes all futures to be dropped and the other values that were ready to
be dropped too. We need to make sure to always process all produced
values which is what this PR attempts to do.
2019-11-04 00:52:20 +01:00
Toralf Wittner
560dc67858 Refactor closing of connections.
The problem we face is that we have an unbounded number of `Control`s
which can all issue close commands. We want them all to be informed when
we have done so but we need to make sure that by closing the command
queue we do not generate false positives. The strategy here is to split
the command queue into two, one for streams and one for controls. As
soon as we receive a close (control) command, we close the stream
commands receiver, and only process any pending stream commands while
not processing any more control commands. Only after completing this
process do we resume processing control commands but only to inform all
controls that have issued a command that we are closed.
2019-11-03 23:50:07 +01:00