Commit Graph

908 Commits

Author SHA1 Message Date
George Barnett e2f161ba00
Rebuild the channel when retrying testWriteBufferAtGSOSegmentCountLimit (#2383)
Motivation:

I (foolishly) didn't validate the test fix in #2382, instead I validated
that the original test passed with 61 segments (rather than 64). The
channel needs to be recreated first.

Modifications:

- Rebuild the channel before trying again if 64 segments is too many.

Result:

Test passes.
2023-03-02 02:18:54 -08:00
George Barnett ec6b8ed8c3
Lower the max segment count in tests (#2382)
Motivation:

On older kernel versions testWriteBufferAtGSOSegmentCountLimit fails
because the write fails with EINVAL. This appears to be a kernel bug as
it passes on more recent versions.

Modifications:

- Try again with a lower segment limit if the write fails with EINVAL.

Result:

Less flaky test.
2023-03-01 06:00:24 -08:00
Johannes Weiss a296f30e45
OnLoopSendable: Sendable containers if on EventLoop (#2370)
Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-02-27 07:11:37 -08:00
George Barnett 19b878f461
Add support for UDP_SEGMENT (#2372)
Motivation:

On Linux, the UDP_SEGMENT socket option allows for large buffers to be
written to the kernel and segmented by the kernel (or in some cases the
NIC) into smaller datagrams. This can substantially decrease the number
of syscalls.

This can be set on a per message basis on a per socket basis. This
change adds per socket configuration.

Modifications:

- Add a CNIOLinux function to check whether UDP_SEGMENT is supported on
  that particular Linux.
- Add a helper to `System` to check whether UDP_SEGMENT is supported on
  the current platform.
- On Linux only:
  - add the udp socket option level
  - add the udp_segment socket option
- Add the `DatagramSegmentSize` channel option.
- Get/Set the option in `DatagramChannel`

Results:

UDP GSO is supported on Linux.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-02-27 13:18:58 +00:00
carolinacass 81e5d344e4
Not Holding OnToRunClosure() test updates (#2375)
Motivation:
swift- nio was failing builds that should pass

Modifications:
Adding available to the necessary sections

* Updating test OnToRunClosure

Motivation:
testCancelledScheduledTasksDoNotHoldOnToRunClosure() was not allowed enough time and timing off at moments, causing it to fail occasionally

Modifications:
Added a ConditionLock throughout the code to make sure it only unlocks when the code has waited enough time for it to not hit the precondition failure
2023-02-23 11:03:03 +00:00
George Barnett 4dfae01cc6
Add a pooled recv buffer allocator (#2362)
Motivation:

Channels can read `ChannelOptions.maxMessagesPerRead` times from a
socket in each read cycle. They typically re-use the same buffer for
each read and rely on it CoWing if necessary. If we read more than once
in a cycle then we may CoW the buffer. Instead of reusing one buffer we
can reuse a pool of buffers limited by `maxMessagesPerRead` and cycle
through each, reducing the chance of CoWing the buffers.

Modifications:

- Extend `RecvByteBufferAllocator` to provide the size of the next
  buffer with a default implementation returning `nil`.
- Add an recv buffer pool which lazily grows up to a fixed size and
  attempts to reuse buffers where possible if doing so avoids CoWing.

Results:

Fewer allocations
2023-02-20 17:00:19 +00:00
Cory Benfield 9afaf801e5
Don't retain a task when all we want is a time (#2373)
Motivation:

To know when we next need to wake up, we keep track of what the next
deadline will be. This works great, but in order to keep track of this
UInt64 we save off an entire ScheduledTask. This object is quite wide (6
pointers wide), and two of those pointers require ARC traffic, so doing
this saving produces unnecessary overhead.

Worse, saving this task plays poorly with task cancellation. If the
saved task is cancelled, this has the effect of "retaining" that task
until the next event loop tick. This is unlikely to produce catastrophic
bugs in real programs, where the loop does tick, but it violates our
tests which rigorously assume that we will always drop a task when it is
cancelled. In specific manufactured cases it's possible to produce leaks
of non-trivial duration.

Modifications:

- Wrote a weirdly complex test.
- Moved the implementation of Task.readyIn to a method on NIODeadline
- Saved a NIODeadline instead of a ScheduledTask

Result:

Minor performance improvement in the core event loop processing, minor
correctness improvement.
2023-02-20 07:27:58 -08:00
carolinacass 5db1dfabb0
Building swift-nio with Swift 5.7 for iOS using Xcode 14.0 at 2.48.0. (#2369)
Motivation:
swift- nio was failing builds that should pass

Modifications:
Adding available to the necessary sections
2023-02-17 10:05:43 -08:00
ser 1e7ad9a0db
Pool buffers for ivecs and storage refs in the event loop. (#2358)
* Pool buffers for ivecs and storage refs in the event loop.

* Introduce PoolElement for poolable objects and add some bounds checks for the pooled buffers.

* Some polishes.

* Fix build failure with Swift 5.5/5.6

* User raw pointers instead of typed.
2023-02-07 13:48:26 +00:00
Franz Busch 45167b8006
Fix flaky testTaskCancel_whenStreaming_andNotSuspended (#2355)
# Motivation
Currently `testTaskCancel_whenStreaming_andNotSuspended` is flaky since `didTerminate` can be called after the iterator is dropped. Fixes https://github.com/apple/swift-nio/issues/2354

# Modification
Let's modify that slightly so we hight the condition we want to hit.

# Result
No more flaky tests.
2023-01-25 14:09:22 +00:00
Cory Benfield 4ad2c37338
Avoid integer literals that won't fit. (#2348)
Motivation:

While the "giant buffer" test doesn't run on 32-bit systems, it does
need to compile. That means we can't set a pointer to a value that won't
fit into an Int.

Modifications:

Smaller pointers!

Result:

The compile should work again.
2023-01-13 13:53:17 +00:00
ser c8ec84ef3b
Prepare mmsghdr structure properly. (#2346)
Motivation:

According to the Linux man page the msg_len field supposed to be used to return a number of bytes sent for the particular message.
It does not make a sense to initialize it with a size of the message.

Modifications:

Change msg_leg field initialization, use 0 instead of message size.

Result:

Use sendmmsg() call properly.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-01-12 11:22:56 +00:00
Franz Busch 602989b003
Implement `remoteAddress0` and `localAddress0` on `EmbeddedChannel` (#2345)
# Motivation
`EmbeddedChannel` is often used in testing and currently any code under testing that uses `context.localAddress` cannot be mocked, since `EmbeddedChannelCore` is always throwing.

# Modification
Use the same values for `localAddress` in `localAddress0()`. Same for `remoteAddress`

# Result
We can now properly test code that needs local/remote addresses with `EmbeddedChannel`
2023-01-12 02:55:18 -08:00
Cory Benfield 184df88ec6
Avoid actually allocating a giant buffer (#2347)
Motivation:

Our CI system is beginning to struggle with allocating a giant buffer in
testSliceOfMassiveBufferWithAdvancedReaderIndexIsOk. We can work around
this by faking out the allocation.

Modifications:

- Provide a fake allocator that doesn't actually allocate memory.
- Rewrite the test to use it.

Result:

Test still validates the behaviour but doesn't touch memory anymore.
2023-01-12 02:33:54 -08:00
Ahmad Alhashemi 91e5b3b609
Allow writing and reading empty datagrams (#2341)
Motivation:

Empty UDP datagrams could be used to have a meaning.
Empty datagrams were being silently dropped on write.
Receiving an empty diagram causes an assertion failure (possible DDoS).

Modifications:

Remove early exit when writing empty datagrams and non-empty assertion when reading them.

Result:

We can now write and read empty datagrams.
2023-01-09 02:45:15 -08:00
David Nadoba 7e3b50b38e
Improve performance of tests (#2336) 2022-12-19 10:14:27 -08:00
Johannes Weiss 86e8b5f5b5
add easier async to future conversion (#2334) 2022-12-19 11:05:47 +00:00
David Nadoba 21c22f3535
Fix non Darwin/Linux builds (#2328) 2022-12-02 08:48:54 -08:00
David Nadoba 810544ec41
Add `RawSocketBootstrap` (#2320) 2022-12-01 15:35:04 +01:00
Rick Newton-Rogers 00341c9277
cap read+pread POSIX read sizes at Int32.max (#2323)
Cap NonBlockingFileIO reads at Int32.max

Motivation:

We wish to avoid overly large reads resulting in EINVAL signals being
triggered resulting in errors. We workaround the issiue in the
NonBlockingFileIO level to keep the lower levels as simple as possible.

Modifications:

`NonBlockingFileIO` `read0` amends read `byteCount`s to be `Int32.max` if they are larger than that value.

Result:

Large `NonBlockingFileIO` reads no longer result in precondition
failures.
2022-11-28 13:19:12 +00:00
David Nadoba 0b4edd8329
Add `NIOBSDSocket.ProtocolSubtype` (#2317)
* RawSocket prototype

* Conform `ProtocolSubtype` to `Hashable`

* Add public `NIOIPProtocol` type

Make `ProtocolSubtype` internal

* Subset of IANA protocols with an RFC

* Add `CustomStringConvertible` to `NIOIPProtocol`

* Add `init(_ rawValue: Int)`

* Rename `NIOBSDSocket.ProtocolSubtype.ip` to `.default`

* Add `NIOBSDSocket.ProtocolSubtype.mptcp`

and remove `NIOBSDSocket.mptcpProtocolSubtype`
2022-11-22 06:01:52 -08:00
Franz Busch edced031e7
Fix failing build on MacOS (#2313)
# Motivation
Currently, the main branch fails to build for me since the `testSimpleMPTCP()` can't compile. This is due to the fact that the `getMPTCPInfo()` method is only available on Linux.

# Modification
Add `#if os(Linux)` around the `testSimpleMPTCP()`.

# Result
Main builds on MacOS again.
2022-11-15 01:25:35 -08:00
Franz Busch 0243bb4c8e
Fix `testTaskCancel_whenStreaming_andNotSuspended` flakiness (#2314)
# Motivation
This test has been flaky for some time. This was due to the fact that the consuming Task could have deinited the iterator which has resulted in a call to `didTerminate`.

# Modification
This PR, adds a small sleep in the consuming task to avoid this race.

# Result
No more flakiness in this test.

Co-authored-by: David Nadoba <d_nadoba@apple.com>
2022-11-14 03:20:09 -08:00
taylorswift 75970eb980
add witnesses for ByteBufferView.reserveCapacity(_:), append(_:), and append(contentsOf:) (#2309)
* add witnesses for ByteBufferView.reserveCapacity(_:), append(_:), and append(contentsOf:)

* align with project style

* fix incorrect ByteBufferView implementations, add unit tests

* use withUnsafeBytes(of:) instead of CollectionOfOne in ByteBufferView.append(_:)

* address review comments

* Add missing Linux tests

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-11-14 10:01:25 +00:00
Cory Benfield 558e4f2fb8
MPTCP support on Linux (#2308)
Motivation

MPTCP provides multipath capability for TCP connections. This
allows TCP connections to consume multiple independent network
paths, providing devices with a number of capabilities to
improve throughput, latency, or reliability.

MPTCP is not totally transparent, and requires servers to support
the functionality as well as clients. To that end, we should expose
some MPTCP capability.

Importantly, MPTCP uses a number of new socket flags and options.
To enable us to support this when it is available but gracefully fail
when it is not, we've hardcoded a number of Linux kernel constants
instead of relying on libc to expose them. This is safe to do on Linux
because its syscall layer is ABI stable.

Modifications

- Add ClientBootstrap and ServerBootstrap flags for MPTCP
- Plumb MPTCP through the stack
- Add new socket options for MPTCP

Result

MPTCP is supported on Linux
2022-11-09 11:02:45 +00:00
David Nadoba 6e404d1614
Add `NIOAsyncTestingChannel.waitForOut/InboundWrite()` (#2307) 2022-11-08 11:45:24 +00:00
carolinacass af41276062
Use #fileID/#filePath instead of #file (#2306)
Motivation:

#fileID introduced in Swift 5.3, so no longer need to use #file anywhere

Modifications:

Changed #file to #filePath or #fileID depending on the situation
2022-11-03 16:43:13 +00:00
George Barnett edfceecba1
Add utilties for reading and writing UUIDs (#2045)
Motivation:

UUIDs are often sent over the wire but writing and reading their bytes
to/from a buffer is a bit of a pain.

Modifications:

- Add utilties to 'NIOFoundationCompat' for reading/writing and
  getting/setting a UUID on a `ByteBuffer`.

Result:

Easier to write/read UUIDs to/from a buffer.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-10-31 06:25:28 -07:00
George Barnett 73eb597aa3
Don't unconditionally remove the HTTPServerUpgradeHandler (#2303)
Motivation:

The `HTTPServerUpgradeHandler` removes itself from the pipeline after an
upgrade and unbuffers any unconsumed reads. If an upgrade starts but
does not complete successfully then the pipeline may be left in an
unknown state.

If, for example, the failure occurs before the user provided upgrade
handler is run then unbuffered writes may be unwrapped by the wrong
channel handler as the wrong type leading to a crash.

Modifications:

- Only remove the upgrade handler and forward buffered writes if all
  parts of the upgrade complete successfully.
- If part of the upgrade fails then fire an error into the channel
  pipeline without removing the server upgrade handler.
- Remove a few unnecessary `map`s.
- Make `httpEncoder` non-optional since and remove associated dead code
  since it can never be `nil`.

Result:

Upgrade handling is safer.
2022-10-28 07:32:43 -07:00
Cory Benfield 522f08ca68
Move 5.7 beta APIs to NIOCore (#2300)
Motivation:

As 5.7 has shipped we no longer need to keep these APIs in _NIOBeta.
We're going to do a two-stage removal: first we're going to move the
APIs to NIOCore and keep them in _NIOBeta with deprecations on them. In
a later release, we'll remove the APIs from _NIOBeta entirely.

Modifications:

- Move the TimeAmount + Duration APIs to NIOCore
- Deprecate the APIs in _NIOBeta.

Result:

We're on a path to remove _NIOBeta
2022-10-25 15:38:47 +01:00
Cory Benfield b8d72c770a
Add support for removing channel options (#2297)
Motivation

Some bootstraps may require the ability to remove
Channel options from the ChannelOption storage in
cases where setting a higher-level flag makes those
options unusable. This patch adds that functionality.

Modifications

Add ChannelOptions.Storage.remove

Result

Users can remove channel options from storage
2022-10-24 20:25:42 +01:00
Artem Redkin d0ebe8da5d
adds create directory method (#2296)
Motivation:
Creating directories is a common task.

Modifications:
 - Adds mkdir syscall
 - Adds create directory implementation
 - Test
2022-10-24 15:02:10 +01:00
Artem Redkin 7bfceed5dc
Implements additional file operation in NonBlockingFileIO (#2244)
Motivation:
Basic set of function that NonBlockingFileIO provides is enough to read and write files, but as we get more and more into fully asynchronous world we need other non-blocking file-related function.

Modifications:
 - Adds support for getting file information using lstat
 - Adds ability to create a symlink, delete symlink and read it's destination
 - Adds ability to list directories
 - Adds ability to rename and remove files
2022-10-24 12:58:04 +01:00
David Nadoba c7b4989b02
Remove `#if compiler(>=5.5)` (#2292)
### Motivation
We only support Swift 5.5.2+.

### Modification
Remove all `#if swift(>=5.5)` conditional compilation blocks.

### Result
less branching
2022-10-13 07:17:46 -07:00
carolinacass 788b759d0b
Fix Nightly Build to work with new Swift versions (#2288)
Swift 5.8 has recently changed the name of the function assign to now be called update. Now, they call update like seen in this proposal:
https://github.com/apple/swift-evolution/blob/main/proposals/0370-pointer-family-initialization-improvements.md

Co-authored-by: Carolina Cassedy <ccassedy@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
Co-authored-by: David Nadoba <d_nadoba@apple.com>
2022-10-13 14:29:40 +01:00
Cory Benfield bc4c55b9f9
Get NIO compiling with GM Xcode (#2284)
Motivation

It's good if we compile with the GM Xcode.

Modifications

Guard Duration usability to at least Swift 5.7.1.

Result

NIO compiles on GM Xcode again.

Note that this is technically an API break for those using Xcode 14
Betas. As those users can (and should) update to 14.1 Beta, and we don't
define API stability for Beta xcodes, this is acceptable.
2022-10-07 03:42:34 -07:00
Cory Benfield 5aa44987f8
Correctly manage Content-Length on HEAD responses (#2277)
Motivation

When we receive a HEAD response, it's possible that the response
contains a content-length. llhttp has a bug
(https://github.com/nodejs/llhttp/issues/202) that prevents it from
properly managing that issue, which causes us to incorrectly parse
responses.

Modifications

Forcibly set llhttp's content-length value to 0.

Result

Correctly handle HTTP framing around llhttp's issues.
2022-10-04 06:59:57 -07:00
George Barnett fcca969463
Raise minimum supported Swift version from 5.4 to 5.5 (#2267)
Motivation:

SwiftNIO periodically drops support for older Swift versions. Now that
5.7 has been released, 5.4 will be dropped.

Modifications:

- Remove 5.4 specific Package.swift and docker-compose
- Update the 5.7 docker-compose to use the released 5.7 and move from
  focal (2004) to jammy (2204)
- Remove unused swiftformat from Dockerfile
- Update tools version in syscall wrapper tests to 5.5
- Update docs

Results:

Minimum Swift version is 5.5
2022-09-29 11:47:44 +01:00
Cory Benfield a16e2f54a2
Merge pull request from GHSA-7fj7-39wj-c64f
Motivation

HTTP headers are prevented from containing certain characters that can
potentially affect parsing or interpretation. Inadequately policing this
can lead to vulnerabilities in web applications, most notably HTTP
Response Splitting.

NIO was insufficiently policing the correctness of the header fields we
emit in HTTP/1.1. We've therefore added a new handler that is
automatically added to channel pipelines that will police the validity
of header fields.

For projects that are already running the validation themselves, this
can be easily disabled. Note that by default NIO does not validate
content length is correctly calculated, so applications can have their
framing fall out of sync unless they appropriately calculate this
themselves or use chunked transfer encoding.

Modifications

- Add thorough unit testing to confirm we will not emit invalid header
  fields.
- Error if a user attempts to send an invalid header field.

Result

NIO applications are no longer vulnerable to response splitting by CRLF
injection by default.
2022-09-27 13:09:52 +01:00
Johannes Weiss 5ce13ea045
address additional NIOLockedValueBox review comments (#2270) 2022-09-23 10:26:20 +01:00
Johannes Weiss 4ed8e1e228
rename class Lock to struct NIOLock (#2266) 2022-09-21 07:36:42 -07:00
Franz Busch f144292e5d
Implement a `NIOAsyncWriter` (#2251)
* Implement a `NIOAsyncWriter`

# Motivation
We previously added the `NIOAsyncProducer` to bridge between the NIO channel pipeline and the asynchronous world. However, we still need something to bridge writes from the asynchronous world back to the NIO channel pipeline.

# Modification
This PR adds a new `NIOAsyncWriter` type that allows us to asynchronously `yield` elements to it. On the other side, we can register a `NIOAsyncWriterDelegate` which will get informed about any written elements. Furthermore, the synchronous side can toggle the writability of the `AsyncWriter` which allows it to implement flow control.
A main goal of this type is to be as performant as possible. To achieve this I did the following things:
- Make everything generic and inlinable
- Use a class with a lock instead of an actor
- Provide methods to yield a sequence of things which allows users to reduce the amount of times the lock gets acquired.

# Result
We now have the means to bridge writes from the asynchronous world to the synchronous

* Remove the completion struct and incorporate code review comments

* Fixup some refactoring leftovers

* More code review comments

* Move to holding the lock around the delegate and moved the delegate into the state machine

* Comment fixups

* More doc fixes

* Call finish when the sink deinits

* Refactor the writer to only yield Deques and rename the delegate to NIOAsyncWriterSinkDelegate

* Review

* Fix some warnings

* Fix benchmark sendability

* Remove Failure generic parameter and allow sending of an error through the Sink
2022-09-21 02:53:53 -07:00
Johannes Weiss 26afcecdc2
NIOConcurrency: add NIOLockedValueBox (#2265)
Motivation:

`LockedValueBox` can help programmers to not forget to actually take a
`Lock` when they should.

Modifications:

Add `LockedValue`.

Result:

Hopefully fewer concurrency bugs.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-09-16 09:16:21 -07:00
Cory Benfield 3cfd8ac5d9
Add support for newer LLHTTP status codes (#2269)
Motivation:

We should better tolerate LLHTTP status codes we don't yet know about.

Modifications:

- Added support for the status codes that currently exist
- Add a fallback to the RAW case for the future.

Result:

Better management of LLHTTP status codes
2022-09-16 08:33:40 -07:00
Cory Benfield 6918034260
Update HTTP parser to LLHTTP (#2263)
Motivation:

The node.js HTTP parser library that we use has been unmaintained for some time. We should move to the maintained replacement, which is llhttp. This patch will update our dependency and bring us over to the new library, as well as make any changes we need.

Modifications:

This patch comes in 4 parts, each contained in a separate commit in the PR.

The first commit drops the existing http_parser code and updates some of the repo state for using llhttp.
The second commit rewrites the update script to bring in llhttp instead of http_parser.
The third runs the actual script. You can skip reviewing this except to sanity check the outcome.
The fourth commit updates the NIO code and the tests to get everything working.

In general the substance of the product modifications was minimal. The logic around keeping track of where we are in the buffer and how upgrades work has changed a bit, so that required some fiddling. I also had to add an error reporting path for the delegates to be able to throw specific errors that llhttp no longer checks for. Finally, I removed two tests that were a little overzealous and that llhttp does not police.

Result:

Back on the supported path.
2022-09-13 14:09:57 +01:00
Johannes Weiss f16991836d
helpful error message when compiling without test discovery on >= Swift 5.5 (#2264) 2022-09-07 15:49:48 +01:00
Cory Benfield af95e9d1c6
Widen the tolerance on testSystemCallWrapperPerformance in debug mode (#2259)
Motivation:

We have downstream CI systems testing us that can't meet this
performance requirement. Given that the debug mode tests are only
checking correctness, not perf, we can widen the buffer.

Modifications:

Double the tolerance of testSystemCallWrapperPerformance in debug mode.

Result:

Downstream CI should be more reliable
2022-09-02 05:44:00 -07:00
Franz Busch 6431296d6b
Call finish once the Source is deinited (#2258)
* Call finish once the Source is deinited

# Motivation
We **MUST** call `finish()` when the `Source` deinits otherwise we can have a suspended continuation that never gets resumed.

# Modification
Introduce an internal class to both `Source`s and call `finish()` in their `deinit`s.

# Result
We are now resuming all continuations.

* Remove @unchecked
2022-09-02 10:01:11 +01:00
carolinacass 028cf7e606
HTTPResponseStatus should print code and reason (#2257)
* HTTPResponseStatus should print code and reason

* Update HTTPResponseStatusTests+XCTest.swift

Co-authored-by: Carolina Cassedy <ccassedy@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-08-31 05:37:08 -07:00
Franz Busch 2c453d6e49
Small changes for the `NIOAsyncSequenceProducer` (#2254)
* Small changes for the `NIOAsyncSequenceProducer`

# Motivation
In the PR for the `NIOAsyncWriter`, a couple of comments around naming of `private` properties that needed to be `internal` due to inlinability and other smaller nits came up.

# Modification
This PR includes two things:
1. Fixing up of the small nits like using `_` or getting the imports inside the `#if` checks
2. Changing the public API of the `makeSequence` to be aligned across the throwing and non-throwing one.

# Result
Cleaner code and alinged APIs.

* Fix refactoring left-overs
2022-08-30 16:53:00 +01:00