Commit Graph

97 Commits

Author SHA1 Message Date
Cory Benfield 2937017e27
Add user event fired when waiting for connectivity. (#95)
Motivation:

On Apple's devices it is considered a best practice to wait for network
connectivity in cases when a connection request cannot immediately be
satisfied, rather than erroring out. This reflects the dynamic and fluid
network environment on Apple devices, with their many network interfaces
and complex interactions between radios, VPNs, and network devices.

While NIOTS supports this model of interaction (and indeed uses it out
of the box), and supports configuring it (by setting
`NIOTSChannelOptions.waitForActivity`), a key pillar is missing:
observability. Right now we don't actually _tell_ the user when we're
waiting for connectivity. This makes it difficult to act on this
information.

Modifications:

- Added a user event, `NIOTSNetworkEvents.WaitingForConnectivity` that
  is fired when connectivity could not be established, but the situation
  may change in future.

Result:

Our users can tell their users when they're waiting for something!
2020-06-17 09:38:07 +01:00
Pasi Salenius 7e330732f2
New channel options exposing properties of underlying NWConnection (#90)
* Initial draft implementation of new channel options for NWConnection.currentPath, metadata for a given NWProtocol, establishment report and data transfer report. Add a new error for not existing connection. Add tests for all of these. The data transfer report option has to be implemented in another way, as the collection of the final data transfer report does not seem very straightforward.

* Fix incorrect available attributes. Make the Value of NIOTSEstablishmentReportOption an EventLoopFuture returning an optional report. Move handling of NIOTSEstablishmentReportOption and NIOTSDataTransferReportOption to getOption0. Remove nwConnection0().

* Use full type on currentPath too.

* Add a DispatchQueue to do collect of the pending data transfer report, use a DispatchGroup to wait for completion of report collection. Remove redundant attribute. Fix nits related to spacing and file header.

* Fix available attributes for tests too.
2020-06-01 11:52:56 +01:00
George Barnett 998422e195
Add a note about failing child channel initializers (#89)
Motivation:

It's not obvious what happens when `childChannelInitializer` returns a
failed future. See https://github.com/apple/swift-nio/pull/1516

Modifications:

Add a note to the `childChannelInitializer` documentation.

Result:

Better docs.
2020-05-15 13:50:44 +01:00
Gwynne Raskind 4eb9bebfb8
Per additional discussion and feedback in apple/swift-nio#1508, we're removing the message parameter from the precondition assertion methods entirely. Added a couple of missing @inlinables to match the declarations now present over there as well. (#85) 2020-05-07 12:50:39 +01:00
Gwynne Raskind fe7e340f41
Update `NIOTSEventLoop` per apple/swift-nio#1508 (#84)
Motivation:

See apple/swift-nio#1508 for rationale

Modifications:

Provides implementations of `preconditionInEventLoop(_:file:line:)` and `preconditionNotInEventLoop(_:file:line:)`.

Result:

NIOTSEventLoop will now use dispatchPrecondition(condition:) for the in/not in preconditions instead of relying on the default implementation, yielding improved correctness.
2020-05-07 10:27:27 +01:00
Peter Adams 7c74f62ea7
Deduplicate ChannelOptions.Storage. (#80) 2020-04-21 21:16:19 +01:00
Adam Fowler 8228db3917
Add canImport(Network) to NIOTSBootstraps.swift (#77) 2020-04-03 18:16:51 +01:00
Johannes Weiss 409fddd45c
bootstraps: offer ELG validation (#76)
Motivation:

Today, we just expect the ELGs passed to the bootstraps to be the
correct ones, if not, we crash.

Modifications:

Offer an alternative validatingGroup: init that just returns nil
if the ELGs are of the wrong types.

Result:

Easier to work with multi-stack systems for example when the user might
pass an ELG for either NIO on Sockets or NIO on Network.framework.

This is the NIOTS companion for https://github.com/apple/swift-nio/pull/1464
2020-04-03 15:57:03 +01:00
Marcus Liotta 7f98392c5d
FilterEmptyWritesHandler (#72)
Add filter removing empty writes to remedy a bug in Network Framework. This is a work in progress, after some initial discussions and suggestions by @weissi.

Motivation:

There is a known bug in Network Framework affecting iOS devices, which will stall a TCP connection after an empty, zero length write. This bug is not found in Network Framework on MacOS. While the bug fix will be rolled out in future versions of iOS it may take some time. Also, to better support the current and older versions of iOS where the bug remains, @weissi suggested to add a ChannelOutboundHandler, that filters out empty writes.

Modifications:

Add a FilterEmptyWritesHandler, which on affected iOS versions can be added by default to all Channels.
Unit tests for all additions and modifications.

Result:

With this workaround NIOTransportServices can support all iOS versions with Network Framework.
2020-04-03 11:36:26 +01:00
Johannes Weiss cefc7014fc
fix license headers (#73) 2020-03-25 15:43:40 +00:00
Johannes Weiss 46cc01e461
universal bootstrap (#69) 2020-03-24 15:57:31 +00:00
Cory Benfield fc80bf018b
Stop syncing onto queues. (#71)
Motivation:

Syncing onto the event loop queues is essentially never acceptable: we
can't appropriately guard against it going terribly wrong.

Modifications:

- Use locks instead, locks are good.

Result:

Removes some crashes.
Resolves #70.
2020-03-06 13:27:39 +00:00
Cory Benfield c7f06384dc Adopt NIOAtomic (#67)
Motivation:

We deprecated Atomic because we made a new, better one. We should use
it.

Modifications:

Replaced all use of Atomic with NIOAtomic.

Result:

Better performance, fewer compiler warnings.
2019-12-10 12:35:02 +00:00
Cory Benfield 6e8c20ed70 Take advantage of flatSubmit. (#62)
Motivation:

We can remove a couple of unnecessary flatMap { $0 } operations by way
of using flatSubmit, added in NIO 2.9.0.

Modifications:

- Replace flatMap { $0 } with flatSubmit().

Result:

Remove some code noise.
2019-10-23 17:49:32 -07:00
Cory Benfield e30bf63ea1 Namespace ChannelOptions. (#61)
Motivation:

In NIO 2.9.0 we moved all first-party `ChannelOption` types into their
own namespace. That was a good idea, but NIOTS uses them too and so it
now encounters build warnings. Additionally, NIOTS defines its own
`ChannelOption`s, and so should namespace those as well.

Modifications:

- Updated the code to use the namespaced `ChannelOption` types.
- Namespaced our own.

Result:

More namespacing.
2019-10-23 17:26:25 -07:00
Johannes Weiss 720645045c Bootstrap: test that returning futures from foreign ELs are okay (#55)
Motivation:

NIO on BSD Sockets had an issue where it wouldn't tolerate futures from
foreign EventLoops being returned from the channel initializers. NIOTS
should also have a test that tests this situation despite the fact that
it didn't have the same bug.

Modification:

- add a test case
- add more assertions

Result:

Better tests.
2019-08-16 17:16:14 +01:00
Cory Benfield 217f948d9b
Add a bind timeout. (#54)
Motivation:

In Network.framework it is possible for a bind operation to take a while
to complete if it ends up waiting for appropriate network conditions. As
a result, unlike in the POSIX case, we need to give users the ability
to configure the maximum amount of time they'd be willing to wait for a
bind call to succeed.

Modifications:

- Add a bind timeout.

Result:

Users won't have to wait forever.
2019-08-06 11:28:44 +01:00
Cory Benfield 6cba688855 Correctly autoRead through the pipeline (#52)
Motivation:

When autoRead is on, the pipeline must observe the read calls in order
to be able to exert backpressure. Otherwise, autoRead is a
zero-backpressure mode, which isn't great.

Correctly call pipeline.read instead of self.read0 to avoid this.

Modifications:

- Updated NIOTSConnectionChannel to call pipeline.read().

Result:

Backpressure can be exerted.
2019-07-23 14:37:49 +01:00
George Barnett eec3aed641 Fix availability for NWEndpoint (#51)
Motivation:

`NWEndpoint` added a `.url` case for macOS 10.15 which commit afbbead added
support for. However, in doing so it also broke support for 10.14.

Modifications:

Handle `.url` in the `default` case and also remove `@unknown` from the
cases of the switch statements in NIOTSListenerChannel and SocketAddress
init.

Result:

Compiles on 10.14.
2019-07-17 13:05:49 +01:00
George Barnett 23e77df42a Lower EventLoopGroup requirements for creating bootstraps (#49)
* Lower EventLoopGroup requirements for creating bootstraps

Motivation:

In NIO `ClientBootstrap` and `ServerBootstrap` are initialized with an
`EventLoopGroup`. Since `EventLoop` conforms to `EventLoopGroup` you can
initialize an bootstrap with an existing event loop. In NIO Transport
Services the bootstraps are initialized with a `NIOTSEventLoopGroup` and
as `NIOTSEventLoop` conforms to `EventLoop` and by extension
`EventLoopGroup` (but not `NIOTSEventLoopGroup`) it is not possible to
initialize a bootstrap with a pre-existing `NIOTSEventLoop`.

Modifications:

Change the bootstrap initializers to accept an `EventLoopGroup`.

Result:

NIO Transport Services bootstraps can be initialized with a
`NIOTSEventLoop`.
2019-07-03 16:50:46 +01:00
Cory Benfield afbbeadf08 Handle .url endpoint in switches over endpoint. (#48)
Motivation:

macOS Catalina brings a .url endpoint to Network.framework, which is
currently causing build warnings. We should tolerate it and silence
those warnings.

Modifications:

Do the right thing when we receive a .url endpoint.

Result:

No build warnings.
2019-06-18 14:31:48 +01:00
Cory Benfield 4d8fb8e887
Enable TCP_NODELAY by default. (#46)
Motivation:

Networking software like SwiftNIO that always has explicit flushes
usually does not benefit from having TCP_NODELAY switched off. The
benefits of having it turned on are usually quite substantial and yet we
forced our users for the longest time to enable it manually.

Quite a bit of engineering time has been lost finding performance
problems and it turns out switching TCP_NODELAY on solves them
magically.

Netty has made the switch to TCP_NODELAY on by default, SwiftNIO should
follow. This patch is the equivalent of apple/swift-nio#1020.

Modifications:

Enable TCP_NODELAY by default.

Result:

If the user forgot to enable TCP_NODELAY, their software should now be
faster.
2019-06-18 14:27:20 +01:00
Cory Benfield b0b3ba5e7f Make NIO Transport Services available on watchOS 6 (#47)
Motivation:

With Network.framework becoming available on watchOS, you should now be
able to run your favourite NIO applications on watchOS 6!

Modifications:

Updated availability annotations to allow NIO TS.

Result:

More NIO on more watches
2019-06-06 22:24:27 -07:00
Cory Benfield d59370d89a
Pass Channels down pipeline not NWConnection (#45)
Motivation:

The expectation is that server channels use Channel as their data type,
but the initial data type in NIOTSListenerChannel was actually
NWConnection. This is unnecessary and it makes it hard to interop
between NIOTS and NIO.

Modifications:

- Initialize the NIOTSConnectionChannel in the NIOTSListenerChannel
instead of in AcceptHandler.
- Added some missing @available annotations in the tests.

Result:

More consistency
2019-05-22 16:40:48 +01:00
George Barnett 3d0713dc43 Annotate code with availability attributes (#42)
* Annotate code with availability attributes

Motivation:

It was not possible to import NIOTS into a project where
Network.framework was not supported by all deployment targets.

Modifications:

All NIOTS code, where applicable, was annotated with availability
attributes.

Result:

It is possible for application developers to import NIOTS on platforms
which do not support Network.framework without a compile time error.
2019-05-10 19:02:02 +01:00
Cory Benfield e95a1e26d5
Allow setting multiple options of the same type. (#40)
Motivation:

While we fixed a bug in SwiftNIO about setting multiple options of the same type in
apple/swift-nio#597, we never brought a fix for that issue forward. We did aim to resolve
this in SwiftNIO 2.0 by providing ChannelOptions.Storage, but unfortunately we forgot to
make the initializer for that type public (see apple/swift-nio#988). While SwiftNIO core
has to get its ducks in a row, users of this library should still be able to set more than
one socket option, in my humble opinion.

Modifications:

- Ported over ChannelOptions.Storage until apple/swift-nio#988 is fixed.
- Transitioned our code to use it.
- Tested it works.

Result:

Users can set multiple channel options.
2019-05-01 14:17:56 +01:00
Cory Benfield 687e79828a Remove unnecessary traps. (#37)
Motivation:

At least in some cases it's possible to have a local or remote address
that we cannot represent in a SocketAddress. In the face of that, we were
unnecessarily crashing. Crashes should probably be avoided there.

Modifications:

- Replace the crashes with throws.

Result:

Fewer crashes, more nils.
2019-04-16 12:29:40 +01:00
Johannes Weiss d68f9d1f8e make NIOTS compile on Linux (#29)
Motivation:

NIOTS will not work on Linux but we can at least make it not fail
compilation when compiled on Linux. That way consumers of the API can
depend on NIOTS but make sure they only use NIOTS when wrapped in a
`#if canImport(Network)` block.

Modification:

Guard everything by `#if canImport(Network)`

Result:

This package will now build on Linux (without providing any useful
code).
2019-03-25 16:49:35 +02:00
Johannes Weiss 1d0cb1040e
don't retain everything until connect timeout expires (#30)
Motivation:

Previously we would use the combination of DispatchQueue.asyncAfter and
a DispatchWorkItem for the connect timeout. If the connection succeeded
we would just cancel the DispatchWorkItem. Unfortunately that will still
keep everything that's captured in the DispatchWorkItem alive until the
deadline has come (because DispatchWorkItem is just a dumb wrapper over
a closure).

Modifications:

use a DispatchSource of type timer source instead.

Result:

- we won't keep the ELG/EL/Channel/... alive until at least the connect
  timeout expires.
- fixes #28
2019-03-22 15:40:02 +00:00
Cory Benfield e1685ae770 Prepare for convergence. (#27)
Motivation:

Once every few thousand years, an event called syzygy (or "convergence")
occurs in our solar system. When these events occur, the fabric of spacetime
becomes thin, allowing reflections of a possible future to appear in our
reality.

This gives a few brave souls the opportunity to experience a future: a
possibility of the way the universe may one day be. But be warned: to
toy with causality is to risk unbearable pain and suffering. Only the
bravest of souls should look too closely at these shadows of the future.

Modifications:

- Chose a firm anchor point in the SwiftNIO timeline.
- Removed the braces that kept time travellers safe.
- Said a quiet prayer.

Result:

Opportunity.
2019-03-15 14:48:05 +00:00
Johannes Weiss 15fe53093c update to latest NIO 2 (#26)
Motivation:

Code should compile and have the latest NIO 2 API.

Modifications:

- rename `ctx` to `context`
- apply all fixits

Result:

compiles again
2019-02-26 13:01:17 +00:00
Cory Benfield 971a6a37ec Bring patches up to new NIO 2 master (#23) 2019-02-26 12:13:54 +00:00
Cory Benfield 72f0815335 Support setting enablePeerToPeer. (#22) (#24)
Motivation:

Some users may wish to use peer-to-peer networking with bonjour.

Modifications:

Expose peer-to-peer networking via a new channel option.

Result:

Users will be able to use peer-to-peer networking

(cherry picked from commit e9c1e41fd1)
2019-02-11 13:12:18 +01:00
Johannes Weiss 4587afdf46 port to latest NIO 2 APIs (#20)
Motivation:

Compiling code is good so let's make it compile again with the latest
NIO APIs.

Modifications:
- made NIOTS use `_NIO1APIShims`
- clicked 'Fix All' a couple of times to adjust the API

Result:
Code compiles again
2019-01-22 15:38:13 +00:00
Johannes Weiss 9fa52bd443 use to NIO 2 (from master branch) and Swift 5 (#18)
Motivation:

SwiftPM from Swift 5.0 brings targets that only support certain systems
which is really handy for this package as it only support macOS 10.14+
and iOS/tvOS 12+

Modifications:

- made use of the Swift 5.0 manifests which can have restrictions on the
  supported platforms
- adapted to NIO 2

Result:

- better development story
- using the latest & greatest
2019-01-18 13:03:21 +00:00
Cory Benfield ea5ba9bd25 Don't transition to .registered unless registration succeeds. (#19)
Motivation:

In some cases, such as when an event loop has been shutdown, channel
registration may fail. In these cases, we would incorrectly attempt to
deregister the channel, which would fail (and in debug builds, assert).
Really, we shouldn't transition into .registered until we know that we have,
in fact, registered.

However, we need to be cautious: we don't want to register unless we
believe we're in an acceptable state to register.

Modifications:

Updated the state enum to perform the registration at the correct
part of the state change function.

Result:

Harder to crash in debug mode
2019-01-08 21:40:57 +00:00
Cory Benfield fb5d37a1e1 Correctly hop across event loops during child channel setup. (#17)
Motivation:

We were inadvertently modifying the registration information of
NIOTSEventLoop objects from multiple threads, which is very not good.

Modifications:

Add an event loop execute to hop loops.

Result:

Thread safe!
2018-12-06 15:02:08 +00:00
Cory Benfield 1761d4eafa Make Channel.isActive thread-safe. (#16)
Motivation:

Sadly I overlooked the fact that Channel.isActive is supposed to be
safe to call from multiple threads: the implementation here was not.

Modifications:

Store the active state into an Atomic.

Result:

It will be thread-safe to ask if a channel is active.
2018-12-06 12:22:58 +00:00
Cory Benfield 5840333f0a Support opting-out of Network.framework waiting state. (#15)
Motivation:

In some cases users may prefer not to wait for Network.framework to
reattempt connection in the future. Users should be able to opt-out of the
default waiting behaviour in those cases.

Modifications:

- Added WaitForActivity ChannelOption.

Result:

Users can configure channels better.
2018-12-03 11:28:20 +00:00
Cory Benfield 73f758b5da Remove invalid assertion. (#13)
Motivation:

It is possible to receive the dataReceived callback after we've called
cancel, mostly because there may be such a block in place in the queue
before that cancel call fires. We should tolerate that.

Modifications:

Removed the invalid assertion.

Result:

Fewer failures.
2018-11-15 10:47:01 +00:00
Johannes Weiss 833b152a21 better diagnostics if unsupported ChannelOption set (#12)
Motivation:

If the user sets an unsupported ChannelOption we should give the best
diagnostics possible.

Modifications:

Add the ChannelOption type to the error message that it's unsupported.

Result:

Happier users
2018-11-09 17:15:35 +00:00
Cory Benfield a9cece8a6d
Support preconditionInEventLoop. (#11)
Motivation:

In SwiftNIO 1.11 we shipped improved interfaces for Channels to support
asserting being in the event loop. This is necessary because Dispatch
provides no non-precondition way to 100% guarantee that you are on a
specific queue, which is a requirement for accurate behaviour of
inEventLoop.

Modifications:

- Added an implementation of preconditionInEventLoop.
- Changed all assertions to use new interface.
- Required NIO 1.11.

Result:

Accurate assertions
2018-11-06 17:44:41 +00:00
Jim Dovey 9e8685be61 Fixes #8, and cleans some switch cases. (#9)
Motivation:

One bugfix, some cleanliness.

Modifications:

`NIOTSListenerChannel.doClose0()` now evaluates and updates `self.bindPromise` irrespective of whether `self.nwListener` had been set.

Also, some case statements could be better: I've swapped `case _ as Thing:` with `case is Thing:`, and I've inlined the `let` value from `case _ as Thing: let thing = x as! Thing` to simply be `case let x as Thing:`.

Result:

If the call to create the `NWListener` in `NIOTSListenerChannel.beginActivating0()` throws an error, any promise passed to that method will now correctly be updated, where before it would be silently ignored, potentially causing a waiting caller to wait forever.

Also, no case statements remain that might cause damage to my tooth enamel.
2018-10-16 10:29:47 +01:00
Jim Dovey e14a834008 Some cleanliness changes. (#7)
* Use DispatchWorkItem.cancel() for cancellation. Make StateManagedChannel.beginActivating() use the same methodology as all the others.

* A needless `if let x = opt` that could be replaced with a question mark.
2018-10-01 05:55:53 +01:00
Cory Benfield 897eb363f5 Handle errors during channel setup. (#2)
Motivation:

If an error is encountered early in the bootstrap process we should
probably not hit an assertion.

Modifications:

Added tests that we don't crash when closing idle channels.

Result:

Fewer crashes.
2018-08-08 19:15:33 +01:00
Cory Benfield 955d1b91e7
Add support for SO_REUSEADDR and SO_REUSEPORT. (#1)
Motivation:

These are commonly-set socket options for channels, and we should
support them when using Transport Services as well.

Modifications:

Pass the socket options through to allowLocalEndpointReuse.

Result:

SO_REUSEADDR and SO_REUSEPORT will be available.
2018-08-08 17:22:02 +01:00
Cory Benfield 6475881aea Initial commit 2018-07-18 17:11:24 +01:00