Commit Graph

1884 Commits

Author SHA1 Message Date
Bouke Haarsma 9c15de3dcf
Host header is requires for HTTP/1.1 (#1740)
* Host header is requires for HTTP/1.1

* Move bootstrap to allow injection of the connection target

* Pass original connect target in the Host header

* Define ConnectTo before using it
2021-02-02 15:14:12 +00:00
Johannes Weiss ea271eb1f5
docs: advanced performance analysis guide (#1738)
Motivation:

Sometimes, advances performance analysis is required and we didn't have
documents describing this.

Modifications:

Add a document describing advanced performance analysis with `perf`.

Result:

More guides.
2021-02-01 15:34:41 +00:00
Johannes Weiss c5a214f075
B2MD: Don't try to reclaim if continuing to parse (#1733)
Motivation:

B2MD called out to the decoder's `shouldReclaimBytes` after every
parsing attempt, even if the parser said `.continue`.

That's quite pointless because we won't add any bytes into the buffer
before we're trying the parser again.

Modifications:

Only ask the decoder if we should reclaim bytes if the decoder actually
says `.needMoreData`.

Result:

Faster, better, more sensible.
2021-01-29 17:03:04 +00:00
Johannes Weiss ef9e98a592
align all functions to make micro benchmarks more stable (#1739)
Motivation:

After chatting to the Swift perf team, they thought it may be a good
idea to align all functions in our performance tests which may make the
micro benchmarks more stable.

Modifications:

Align all functions/blocks.

Result:

Hopefully more stable micro benchmarks.
2021-01-29 08:32:08 +00:00
GuangGuang a0c968a619
[swift-nio-ssl] fix compile error for swift-nio-ssl (#1734)
Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-01-25 08:49:26 +00:00
Fabian Fett f745421d49
Final language fix (#1732) 2021-01-22 18:39:10 +00:00
Fabian Fett 6b41c18bf6
Fix Codec memory reclaim bug (#1729) 2021-01-21 20:32:20 +00:00
Fabian Fett 0260fc32cf
Replace unwelcoming language in sha1 (#1731) 2021-01-21 16:02:57 +00:00
Fabian Fett 76b4637122
Make language more welcoming (#1728) 2021-01-21 12:45:46 +00:00
Cory Benfield 8ea768b0b8 Add static vars for common HTTP versions (#1723)
Motivation:

I'm sick of typing `.init(major: 1, minor: 1)`.

Modifications:

- Added static vars for common HTTP versions.

Result:

Maybe I'll never type `.init(major: 1, minor: 1)` ever again.
2021-01-19 17:27:02 +00:00
Johannes Weiss 2b821b2ef6
Specialise succeeded Void futures so we allocate less (#1703)
Motivation:

Succeeded `EventLoopFuture<Void>`s are quite important in SwiftNIO, they
happen all over the place. Unfortunately, we usually allocate each time,
unnecessarily.

Modifications:

Offer `EventLoop`s the option to cache succeeded void futures.

Result:

Fewer allocations.
2021-01-15 17:07:15 +00:00
Johannes Weiss 6b4a8197f9
order perf tests by name in docker files (#1720)
Motivation:

When you make a change that affects many performance tests, it's often
easier to just copy the results from CI. Unfortunately, that makes the
diff hard to read because the order is arbitrary.

Modifications:

Sort the list so you can always easily get to the same order as the
docker file by using `| sort` or `:sort` in vim.

Result:

Easier to update perf tests.
2021-01-14 19:03:59 +00:00
Kim de Vos 3ef55a4ae0
Remove CNIOAtomics and CNIOSHA1 as dependency (#1719) 2021-01-13 08:09:35 +00:00
Peter Adams b671e557fd
Only use ascii characters in perf test names. (#1718)
Motivation:

Many other systems don't like non ascii characters.

Modifications:

Change a letter 'a' to a letter 'a' but with a more normal encoding.

Result:

Test names should be in ascii
2021-01-11 07:32:39 +00:00
Cory Benfield 8ea391a77d
Clean up typo in method argument. (#1713)
Motivation:

PR #1710 introduced a typo into the code. This typo was missed because
the argument name was shadowing a variable from parent scope, which was
inadvertently closed over.

Best to avoid that confusion.

Modifications:

- Fixed the typo
- Renamed the argument to reduce the risk of this happening again

Result:

Better code organisation.
2021-01-05 10:23:13 +00:00
Peter Adams 161a5d0a53
Remove error handling for adding/removing handlers functions (#1712)
Motivation:

The handlerAdded and handlerRemoved functions are not throwing.
I can't spot anyway way and exception could actually happen
so no point in catering for the case when one does.

Modifications:

Remove possibility that an exception was thrown when adding or
removing handlers as none of the called functions are throwing.

Result:

Fewer lines of code, less complexity.
2021-01-05 09:41:20 +00:00
Peter Adams f4c87c800d
Remove an allocation from addHandlers (#1710)
* Add allocation test for adding multiple handlers

Motivation:

I believe there is at least 1 avoidable allocation in this area.
Even if there isn't, making sure we don't increase allocations is good.

Modifications:

Add a test of allocations when adding multiple handlers.
Set limits for docker images.

Result:

Allocations when adding multiple handlers are now checked.

* Remove an allocation from addHandlers

Motivation:

Fewer allocations should improve performance.

Modifications:

Split out a sub function from addHandlers.

I originally thought I'd have to change the part of this
function which reads `var handlers = handlers` as there was
a surprising allocation at the beginning of this function.
It seems that breaking out some of the logic is sufficient
to remove an allocation.

Result:

1 fewer allocation.

* Fix up alloc tests.
2020-12-21 13:54:28 +00:00
George Barnett 98c4af8109
Make a few EventLoopFuture functions inlinable (#1708)
Motivation:

Some of the generic EventLoopFuture functions weren't inlinable.

Modifications:

- Make them @inlinable
- Fix typo in name of 'DispathQueue+WithFuture.swift'

Result:

More specialization.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-12-18 16:16:06 +00:00
Cory Benfield 1a2996bfc5
Revert "Retry on EPROTOTYPE on socket writes. (#1706)" (#1707)
This reverts commit 4853e910e8.

While we have been able to observe the effect that this change was
trying to workaround, the change seems to interact poorly with a
different issue in Big Sur that can cause EPROTOTYPE to be consistently
emitted during socket writes on otherwise connected sockets. This would
change a connection-terminating error into a 100% CPU spin that rendered
the event loop entirely useless: a substantial regression.

For this reason, we should back this out until the issue is better
characterised.
2020-12-18 15:32:53 +00:00
Cory Benfield 4853e910e8
Retry on EPROTOTYPE on socket writes. (#1706)
Motivation:

When writing to a network socket on Apple platforms it is possible to
see EPROTOTYPE returned as an error. This is an undocumented and
special-case error code that appears to be associated with socket
shutdown, and so can fire when writing to a socket that is being shut
down by the other side. This should not be fired into the pipeline but
instead should be retried.

Modifications:

- Retry EPROTOTYPE errors on socket write methods.
- Add an (unfortunately) probabilistic test bed.

Result:

Should avoid weird error cases.
2020-12-17 17:45:23 +00:00
Peter Adams 43931b7a7d
Make all imports of CNIOLinux conditional on OS (#1704)
Motivation:

Some users are including NIO in Xcode workspaces
rather than using SPM.  When this is done, if all
imports of CNIOLinux are conditional they can
remove this project from their workspace.

Modifications:

Make all imports of CNIOLinux conditional on Linux,
Android or FreeBSD

Result:

No user visible change.
2020-12-16 10:41:56 +00:00
Johannes Weiss fe10c5c063
Change the `class` restriction on our protocols to `AnyObject` (#1702)
Motivation:

In all contemporary Swift versions, the `class` and the `AnyObject`
protocol restriction is the same. And `class` is deprecated which warns
on newer Swift compilers.

Modifications:

Replace `class` with `AnyObject`.

Result:

No warnings on newer Swift compilers.
2020-12-09 19:43:11 +00:00
Cory Benfield 076fda1521
Use CircularBuffer in EmbeddedChannel. (#1700)
Motivation:

When running load through EmbeddedChannel we spend an enormous amount of
time screwing around with removing things from Arrays. Arrays are not a
natural data type for `removeFirst()`, and in fact that method is
linear-time on Array due to the need for Array to be zero-indexed. Let's
stop using (and indeed misusing) Array on EmbeddedChannel.

While we're here, if we add some judicious @inlinable annotations we can
also save additional work generating results that users don't need.

Modifications:

- Replace arrays with circular buffers (including marked versions).
- Avoid CoWs and extra allocations on flush.
- Make some API methods inlinable to make them cheaper.

Result:

- Much cheaper EmbeddedChannel for benchmark purposes.
2020-12-02 16:01:21 +00:00
Cory Benfield 2bae395344
Remove use of removeAll(keepingCapacity:). (#1699)
Motivation:

As outlined in https://bugs.swift.org/browse/SR-13923,
removeAll(keepingCapacity:) on Array has particularly negative
performance when that Array is not uniquely referenced. In this case, in
EmbeddedChannel, we _arrange_ to multiply reference it. This makes it
swamp our HTTP/2 microbenchmarks, spending more cycles copying this
buffer around than doing anything else.

Modifications:

- Just allocate a new buffer instead.

Result:

Much less copying.
2020-12-01 08:08:06 +00:00
George Barnett 8b47ef29a8
Fix casing of 'SocketAddress.init(packedIpAddress:port:)' (#1698)
Motivation:

A new init was added to `SocketAddress` in #1692, but the casing of
`packedIpAddress` is incorrect, it should be `packedIPAddress`. This
hasn't been released yet so let's fix it while we still can!

Modifications:

- s/packedIpAddress/packedIPAddress

Result:

More consistent API
2020-11-30 17:51:12 +00:00
Cory Benfield 4bf379b156
Implement faster pointer rebasing. (#1696)
Motivation:

I recently discovered that UnsafeRawBufferPointer.init(rebasing:) is
surprisingly expensive, with 7 traps and 11 branches. A simple
replacement can make it a lot cheaper, down to two traps and four
branches. This ends up having pretty drastic effects on
ByteBuffer-heavy NIO code, which often outlines the call to that
initializer and loses the ability to make a bunch of site-local
optimisations.

While this has been potentially fixed upstream with
https://github.com/apple/swift/pull/34879, there is no good reason to
wait until Swift 5.4 for this improvement.

Due to the niche use-case, I didn't bother doing this for _every_
rebasing in the program. In particular, there is at least one
UnsafeBufferPointer(rebasing:) that I didn't do this with, and there are
uses in both NIOTLS and NIOHTTP1 that I didn't change. While we can fix
those if we really need to, it would be nice to avoid this helper
proliferating too far through our codebase.

Modifications:

- Replaced the use of URBP.init(rebasing:) with a custom hand-rolled
  version that avoids Slice.count.

Result:

Cheaper code. One NIOHTTP2 benchmark sees a 2.9% speedup from this
change alone.
2020-11-30 10:02:15 +00:00
buttaface 44d67ba4e0
Update and finish Android port. (#1695)
Motivation:

Be able to run and test swift-nio on Android.

Modifications:

- Remove the custom ifaddrs and use the one from the Android NDK instead.
- Enable a bunch of conditionally-compiled code for Android.
- Add a handful of constants and other Android declarations.
- Cast some types because of mismatches specific to Android.

Result:

Most tests pass on Android AArch64 and ARMv7.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-11-27 11:16:11 +00:00
Rémi Doreau da6cc5141c
Create SocketAddress from packed byte representation (#1692)
Motivation:

A user should be able to create SocketAddress from packed bytes representation.

Modifications:

I added a new SocketAddress initializer which takes the IP address in ByteBuffer form. I have also added tests that ensure the initializer works properly.

Result:

We have a new way to initialize a SocketAddress from a byteBuffer.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-11-27 10:18:47 +00:00
Joshua Rutkowski 2f9ea47738
Conform TimeAmount to AdditiveArithmetic (#1691)
Conforms TimeAmount to AdditiveArithmetic.

Motivation:
TimeAmount does not support -=, +=. Sometimes it is useful to manipulate time amounts when building up a delay and if that iteration fails, we would want to delay += .milliseconds(5) to add 5 milliseconds to our delay and try again.

Modifications:
Conformed TimeAmount to AdditiveArithmetic: added a static zero property and required operators.

Result:
TimeAmount conforms to AdditiveArithmetic.

Co-authored-by: Josh <jrtkski@icloud.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-11-17 15:30:17 +00:00
jemmons 5939c78fca
Removes misleading docs for whenComplete (#1687)
Upon the addition of `Result` in the Swift standard library, apple/swift-nio#734
updated `EventLoopFuture.whenComplete(_:)` to pass a `Result<T, Error>` to
its `callback`, but the documentation still confusingly states:

> Unlike its friends… `whenComplete` does not receive the result of the
> `EventLoopFuture`.

This patch fixes that by removing the (now inaccurate) lines.
2020-11-11 19:23:22 +00:00
Saleem Abdulrasool 255f29d3f3
NIO: implement address resolution on Windows (#1684)
Windows has a slightly different API for address resolution.  Implement
the Windows path for addrinfo resolution.
2020-11-02 17:02:35 +00:00
Saleem Abdulrasool 245ce96490
NIO: implement network interface enumeration for Windows (#1647)
Partially implement network interface enumeration.  This is sufficient
to build up the structures for basic operations.  Although the interface
information is incomplete, this provides enough structure to continue
porting the rest of the NIO interfaces.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-10-28 16:20:02 +00:00
Peter Adams 91eab6d836
Add multiple channel handlers in a single async call. (#1683)
Motivation:

Curently adding multiple channel handlers makes a call to the
async version of addHandler for each handler resulting in
n+1 futures.  It feels better to use just one future and add
all the handlers synchoronously.

Modifications:

Change sync functions with take a promise to instead return a Result.
Feed this back until reaching addHandlers.

Result:

Multiple handlers can be added more quickly.
2020-10-27 16:14:51 +00:00
George Barnett 74bedaf43b
Add watchOS deployment to PodSpec build script (#1679)
Motivation:

We support watchOS 6+ with SwiftNIO Transport Services; as such we should
include watchOS as a deployment target for our CocoaPods.

Modifications:

- Add a watchOS deployment target to `build_podspecs.sh`
- Update docs

Result:

Users can deploy to watchOS 6+ with CocoaPods.
2020-10-21 09:00:01 +01:00
Saleem Abdulrasool 366850acdd
NIO: implement `sendmsg` and `recvmsg` on Windows (#1674)
`WSASendMsg` and `WSARecvMsg` are not directly accessible to use.
Instead, one must perform an IOCTL on the socket to retrieve the
extension point and then use that function pointer to perform the
operation.  Use this to implement the functionality on Windows.
2020-10-20 08:22:20 +01:00
Saleem Abdulrasool 20e63d07dc
NIO: extract control message handling into a separate protocol (#1678)
These are part of the BSD sockets APIs, but not directly related to the
socket interfaces.  Create an extension point to permit the different
platforms to shuffle their implementation into place.  This provides a
nicer spelling for the functions and enables the codepaths on Windows as
well.
2020-10-19 16:18:57 +01:00
Saleem Abdulrasool 1cdbf763fb
NIO: reflow some comments (NFC) (#1677) 2020-10-14 18:05:40 +01:00
Saleem Abdulrasool d8c5a5ec84
NIO: expose `LINGER` as a public type on Windows (#1675)
The Windows `LINGER` type is meant to be exposed as it is a low-level
system detail for `SocketChannelOptions`.  See #1673 for relevant
discussion.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-10-14 08:54:37 +01:00
Saleem Abdulrasool 70ca7aad2b
NIO: silence error on Windows (#1668)
The `ignoreSIGPIPE` does nothing on Windows.  However, add an overload
to differentiate between a socket and file descriptor as they may be
different.  This is the case on Windows, where file descriptors are
32-bit but socket are 64-bit.

fixup! e51406c61972420c43734b1d089712bc408e097b
2020-10-14 08:25:28 +01:00
Saleem Abdulrasool 8e59cd159e
NIO: carve away more of `System.swift` on Windows (#1669)
`System` interfaces should be considered deprecated and not be used.
This removes more of the interfaces from Windows as the socket
interfaces are now part of BSDSocketAPI.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-10-13 10:17:24 +01:00
George Barnett 984af7f4eb
Fix incorrect new names for deprecated APIs (#1672)
Motivation:

Some of the deprecated APIs on the client, server and datagram
bootstraps included the type name in the "rename" field. Since the
underlying type hasn't changed, this isn't quite right results in the
typename being erroneously included when applying a fix-it in Xcode.

Modifications:

- Remove unnecessary typename from a few rename fields.

Result:

Fix-its work as expected.
2020-10-12 13:03:08 +01:00
tomer doron d9d4918333
remove symbolicate-linux-fatal from Docker (#1670)
motivation: we are not actually using symbolicate-linux-fatal in any meaningful way in CI and it's pinned to the master branch which has been removed

changes: remove symbolicate-linux-fatal fetching from Docker
2020-10-08 13:16:12 +01:00
Andrius e6b7d718a8
HTTPObjectAggregator implementation (#1664)
* HTTPServerObjectAggregator for requests

* Apply suggestions from code review

Co-authored-by: Cory Benfield <lukasa@apple.com>

* most of code review comments addressed

* tidy up state machine close

* bad line breaks

* more verbose error reporting

* removes expect:continue functionality due to #1422

* public type naming and error handling tweaks

* wrong expectation in test

* do not quietly swallow unexpected errors in channelRead

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-10-08 11:37:32 +01:00
Saleem Abdulrasool d2372de507
NIO: correct return value for messaging on Windows (#1667)
The return type failed to correctly convert the result to the return
value type.  Explicitly perform the return value initialization.
2020-10-06 10:00:12 +01:00
Saleem Abdulrasool 5d57ca0f3a
NIO: implement `cleanupSocket(unixDomainSocketPath:)` for Windows (#1654)
* NIO: implement `cleanupSocket(unixDomainSocketPath:)` for Windows

This adds an initial implementation for the UDS clean up path on
Windows.  Unlike Unix, you cannot simply `stat` the destination to
determine if it is a UDS endpoint.

One must first create a file handle from the path.  Assuming that we are
able to create that, we should verify that the file that we are dealing
with is a not a disk type as the subsequent checks will fail.  Now, we
can use the file handle to query the information of the file.  This will
allow us to determine if it is a reparse point.  If not, it is
impossible for it to be a UDS as a UDS endpoint is a reparse point with
the tag IO_REPARSE_TAG_AF_UNIX.  Once we know that we have a reparse
point, we must query the kernel for information about it via the
`DeviceIoControl` system call (perform an ioctl in Unix speak).  The
returned buffer's tag will identify if we have a UDS.

For the next dance, we must now _close_ the handle as the handle being
left open will cause the subsequent `DeleteFileW` to fail due to there
being an open handle.  Once we have cleaned up the file handle that we
created, we can safely attempt to remove the file via `DeleteFileW`.

This should hopefully be sufficiently robust from possible error
scenarios for the removal of a UDS endpoint.

* NIO: improve the UDS cleanup path on Windows

Instead of doing the complex close-handle dance, instead prefer
`SetFileInformationByHandle` which:
1. avoids a second UTF-8 -> UCS-2 conversion
2. avoids the need for the handle closing dance
3. avoids a third re-query of the handle
4. enables us to use "POSIX" deletion semantics (file is immediately
   removed from the namespace but data streams are left intact)

This comes at the cost of being Windows 10 centric, which I find a
reasonable trade-off as Windows 7 has been EOL'ed by Microsoft, and more
importantly, Unix Domain Sockets are only available on Windows 10!

Thanks to @adierking for the reminder about SetFileInformationByHandle!
2020-10-05 12:49:28 +01:00
Fabian Fett 7c92a3e4d8
NIOUDPServer use AddressedEnvelope as InboundIn and OutboundOut (#1666) 2020-10-02 17:08:54 +01:00
George Barnett bbb0e92702
Print the usage if no args ar provided to the build_podspecs script (#1665)
Motivation:

The information printed when invoking `build_podspecs.sh` without
arguments is outdated.

Modifications:

- Print usage information when invoking without arguments.

Result:

- 'build_podspecs.sh' is more helpful when you can't remember how it
  should be invoked
2020-10-01 17:37:55 +01:00
Cory Benfield c3e2359c55
Minor cleanups of Windows compatability code. (#1663)
Motivation:

Cleanup some noise that came in with some previous Windows compat
patches.

Modifications:

- Move INVALID_SOCKET to NIOBSDSocket, and refer to it by a better name
  there.
- Comment in an empty block to indicate that it's supposed to be empty.

Result:

Bit cleaner code.
2020-09-30 19:55:21 +01:00
Graeme Jenkinson b5c1696033
Provide a convenience API for dispatching blocking work (#1563) (#1662)
Motivation:

SwiftNIO lacks a convenience API for performing blocking IO / tasks. As
this is a fairly common task it then requires the clients to make ad hoc
implementations that address this requirement.

Modifications:

Extension to DispatchQueue with the following method to schedule a work
item to the `DispatchQueue` and return and `EventLoopFuture` for the
result returned:

- `asyncWithFuture<NewValue>(eventLoop: EventLoop, _ callbackMayBlock: @escaping () throws -> NewValue) -> EventLoopFuture<NewValue>`

Added new unit tests for this function both when the promise succeeds
and fails.

Extention to EventLoopFuture with the following public functions:

- `flatMapBlocking<NewValue)(onto queue DispatchQueue, _ callbackMayBlock: @escpaing (Value) throws -> NewValue) -> EventLoopFuture<NewValue>`
- `whenSuccessBlocking(onto queue DispatchQueue, _ callbackMayBlock: @escaping (Value) -> Void) -> EventLoopFuture<NewValue>`
- `whenFailureBlocking()onto queue DispatchQueue, _ callbackMayBlock: @escaping (Error) -> Void) -> EventLoopFuture<NewValue>`
- `whenCompleteBlocking(onto queue DispatchQueue, _ callbackMayBlock: @escaping (Result<Value, Error>) -> Void) -> EventLoopFuture<NewValue>`

These functions may all be called safely with callbacks that perform blocking IO / Tasks.

Added new unit tests to EventLoopFutureTest.swift for each new function.

Result:

New public API for `EventLoopFuture` that allows scheduling of blocking IO / Tasks.
2020-09-30 17:04:21 +01:00
Graeme Jenkinson 7c42e5a45d
A helper for easily unwrapping Optional values in an EventLoopFuture (#1656)
Motivation:

Unwrapping an `Optional` value from an `EventLoopFuture` is a fairly
common requirement that currently involves the client writing
boilerplate code, for example:

```
extension EventLoopFuture {
    func unwrapOptional<T>(orError error: Swift.Error) -> EventLoopFuture<T> where Value == T? {
        self.flatMapThrowing { value in
            guard let value = value else {
                throw error
            }
            return value
        }
    }
}
```

As this is a fairly common requirement adding an extension of
`EventLoopFuture` to unwrap `Optional` values would remove this
burden from clients.

Modifications:

Added Extension to `EventLoopFuture` containing the following functions:

- `unwrap<NewValue>(orError: Error)`: Unwraps a future returning a new
  `EventLoopFuture` with the same value as the resolved future when
  its value is Optional.some(...)`, otherwise the `Error` passed in
  the `orError` parameter is thrown

- func unwrap<NewValue>(orReplace: NewValue)`: Unwraps a future returning a new
  `EventLoopFuture` with either: the value passed in the `orReplace`
  parameter when the future resolved with value `Optional.none`, or
  the same value otherwise.

- func unwrap<NewValue>(orElse: @escaping ()- > NewValue): Unwraps a future
  returning a new `EventLoopFuture` with either: the value returned
  by the closure passed in the `orElse` parameter when the future
  resolved with value `Optional.none`, or the same value otherwise.

Added new unit tests for each new `unwrap(orXXX:)` function.

Result:

Client's no longer have to write their own boilerplate code.
2020-09-30 13:47:14 +01:00