Commit Graph

491 Commits

Author SHA1 Message Date
Tanner 0154604408 rename HTTPProtocolUpgrader to HTTPServerProtocolUpgrader (#750)
* rename HTTPProtocolUpgrader to HTTPServerProtocolUpgrader
2019-01-31 11:36:55 +00:00
JovanMilenkovic cf56bfd119 Remove EmbeddedChannel restriction to IOData (#763)
Remove EmbeddedChannel restriction to IOData

Motivation:

You should be able to read any type from the outbound buffer.

Modifications:

Change Embedded channel outboundBuffer and pendingOutboundBuffer to store NIOAny instead of IOData and refactor test code accordingly.

Result:

- Users can test what went through the pipeline without serializing everything and using "if case let" syntax everywhere.
- fixes #551
2019-01-30 19:24:59 +00:00
Gwynne Raskind 8222af4aad Add cancel notification to RepeatedTask (#783)
* Add cancel notification to RepeatedTask

Motivation:

When cancelling a RepeatedTask, it is often desirable to
wait until any still in-progress execution of the task is
finished - for example, to know when a periodic state save
is done before shutting down. The current API provides no
easy way to perform such a wait. With this addition,
repeating tasks can report completion of a cancellation
request regardless of in what state the task was in when the
request was issued.

Modifications:

A default-nil parameter is added to EventLoop.scheduleRepeatedTask(),
to which a promise can be provided; the promise will be
fulfilled at the time of the task's cancellation, plus any
time required for the task to complete running if it was
cancelled during execution. The promise is signaled even if
the cancellation is the result of the task throwing an error.
A default-nil paramter is also added to RepeatedTask.cancel(),
to which a second promise can be passed. This promise is
fulfilled under the same conditions as the first, even if the
first was not given; neither of the promises is dependent
upon the other and both are fulfilled at the same time if
provided. Further calls to cancel() with different promises
will result in fulfillment of each of those promises as well.

Result:

The observed behavior of RepeatedTask.cancel() now optionally
includes deterministic knowledge of when the task is no longer
executing or scheduled to be executed. The API changes are
designed to be additive in form, but the function signatures
do change. Source compatibility is maintained; binary
compatibility is not.
2019-01-29 13:19:12 +00:00
Johannes Weiss 2ad1e21512 CircularBuffer.init: rename initialRingCapacity to initialCapacity
Motivation:

initialRingCapacity is not a great name, initialCapacity is much better

Modifications:

rename CircularBuffer(initialRingCapacity:) to initialCapacity

Result:

more consistent code
2019-01-29 12:29:04 +00:00
Jovan Milenkovic a5838ae22b Replace ByteBufferTest use of deprecated "withUnsafeBytes" with new API
Motivation:

Remove the only warning in the project.

Modifications:

Use new withUnsafeBytes API.

Result:

The project will have no warnings.

(cherry picked from commit b41e50403b)
2019-01-29 11:52:20 +00:00
David Skrundz 0eb85a4478 Add deadlines as an alternative to timeouts (#770)
Add deadlines as an alternative to timeouts

Motivation:

Address #603

Modifications:

- Add NIODeadline type
- Add func scheduleTask<T>(deadline: NIODeadline, _ task: @escaping () throws -> T) -> Scheduled<T>
- Reduce the use of DispatchTime in favor of Time
- Replace timeout calls with deadline calls where it makes sense

Result:

Tasks can be scheduled after an amount of time has passed, or at a certain time.
2019-01-25 19:32:55 +00:00
Nathan Harris 30f1a544d0 Add `whenAllComplete` EventLoopFuture method (#773)
* Add `whenAllComplete` method to group a homogenous array of future results into a single ELF
2019-01-25 10:03:11 +00:00
Johannes Weiss 3563b9d795
provide ELF.flatMapResult (#778)
Motivation:

ELFs and the stdlib's Result should be as compatible as possible so a
flatMapResult function which lifts and combines a result into an
EventLoopFuture sounds like a good idea.

Modifications:

add `flatMapResult` which does what it says.

Result:

more interop between `Result` and `EventLoopFuture`.
2019-01-24 20:11:00 +00:00
Johannes Weiss f3294dd803 rename ELF.mapIfError to ELF.recover (#777)
Motivation:

The name `mapIfError` implied that you can transform the error value but
really that's never what it did. Instead, it allowed you to recover
from a failure.

Modifications:

- rename `mapIfError` to `recover`

Result:

cleaner method names
2019-01-24 17:09:13 +00:00
Johannes Weiss c4ff795dda
remove ELP.succeed/fail's labels (#776)
Motivation:

EventLoopPromise.succeed/fail has extraneous labels that don't add
anything but noise.

Modifications:

remove extraneous labels

Result:

less noise in the code
2019-01-24 16:42:53 +00:00
Jari (LotU) 313ddabb48 Allow setting of RemoveAfterUpgradeStrategy (#766)
Allow to set RemoveAfterUpgradeStrategy on HTTPResoonseSecoder
2019-01-21 22:12:24 +00:00
Johannes Weiss 3e7d6a7bfd rename ELF.then to ELF.flatMap (#760)
Motivation:

ELF's API should be as close as possible to the new Result's API.
Therefore, we should rename `then` to `flatMap`

Modifications:

- renamed `then` to `flatMap`
- renamed `thenIfError` to `flatMapError`
- renamed ELF's generic parameter from `T` to `Value`

Result:

- more like Result
- fixes #688
2019-01-21 16:41:04 +00:00
Cory Benfield ea888e6405
Fix broken test for byte delivery. (#745)
Motivation:

When we write unit tests, we generally like them to actually test the
thing they claim to. This test never ran, and the assertions in place
to verify that it ran also never ran, so we didn't notice the test
not running.

Modifications:

- Moved the assertion that validates the test ran to a place where
  it will definitely execute.
- Ensured the EmbeddedChannel gets marked as active, so that we
  actually deliver the bytes from the HTTPDecoder.

Result:

This test will run, and actually pass.
2019-01-19 20:17:38 +00:00
Johannes Weiss f38984d80e
remove bogus 'is active' assertion in channelRead0 (#739)
Motivation:

BaseSocketChannel used to assert that `channelRead0` is only called when
the channel is active. That's bogus and it's trivial to hit this issue
when calling `fireChannelRead` in the last `ChannelHandler` when the
channel has gone inactive.

Modifications:

remove assertion, add comment

Result:

fewer crashes
2019-01-07 14:18:48 +00:00
Johannes Weiss fa2ebe4a56 remove backports of newer Swift functionality (#738)
Motivation:

We now depend on Swift 5.0, so we can remove all the backporting of
functionality.

Modifications:

deleted all backported Swift functionality

Result:

less code
2019-01-07 12:32:58 +00:00
Johannes Weiss 95b290a51f use automatic Equatable conformances (#737)
Motivation:

No code is the best code, let's have the compiler generate more
Equatable instances for us.

Modifications:

remove some hand-written Equatable conformances

Result:

less code, possibly fewer bugs
2019-01-07 11:52:22 +00:00
Johannes Weiss 684cad331c EventLoopFuture: use Result type (#734)
Motivation:

Now that the stdlib has introduced the Result type, we can use it in the
implementation (and the whenComplete) function of EventLoopFuture

Modifications:

- replace EventLoopValue with Result
- make whenComplete provide the Result

Result:

use the new shiny stuff
2019-01-05 08:08:47 +00:00
Johannes Weiss 08eb3259ce better DispatchData support (#732)
Motivation:

DispatchData's APIs are less than optimal and the current one we used
did allocate at least on Linux to copy bytes out.

Modifications:

introduce ByteBuffer.write/read/set/getDispatchData

Result:

when Dispatch gets fixed, lower allocations
2019-01-03 17:45:45 +00:00
Johannes Weiss 695b1ebe13
prefer non-deprecated API for Data/Range (#733)
Motivation:

Deprecated API sucks.

Modifications:

Use non-deprecated API for Data/Range stuff

Result:

better code
2019-01-03 16:00:16 +00:00
Cory Benfield 0db974bdbe
Fix: BlockingIOThreadPool not releasing the latest WorkItem (#716) (#730)
BUGFIX: BlockingIOThreadPool not releasing the latest WorkItem

Fix is to clear the latest work item just before waiting for
the next one to be submitted.

Added two tests to validate the fix: submitting only one work item
to an IO thread pool, and submitting two consecutive work items.

Thanks to Gwynne Raskind for help troubleshooting & fix

(cherry picked from commit 8df414b716)
2019-01-03 10:58:15 +00:00
Ilya Puchka b878f06b20 override content encoding header value in compressor (#728)
override content encoding header value in compressor
2019-01-03 09:57:57 +00:00
Sergej Jaskiewicz 161eaa760e [Gardening] Use multiline string literals instead of concatenation (#719)
Motivation:

The rest of the code in NIO uses multiline literals.

Modifications:

Converted string concatenations to multiline literals.

Result:

NFC, prettier code.
2019-01-02 10:36:04 +00:00
Johannes Weiss 531745d71a
remove ContiguousCollection (#709)
Motivation:

ContiguousCollection is no longer necessary because Sequence gained
withContiguousStorageIfAvailable.

Modifications:

Removed ContiguousCollection and switch to withContiguousStorageIfAvailable.

Result:

less code
2018-12-18 09:20:37 +00:00
Johannes Weiss 2262b656ac
fix CircularBuffer.replaceSubrange expands (#683)
Motivation:

CircularBuffer.replaceSubrange was crazy eager to double the capacity
which is bad.

Modifications:

Made CircularBuffer.replaceSubrange only double if necessary.

Result:

less memory usage
2018-12-14 18:49:34 +00:00
Johannes Weiss 1a69a97b5e
use String.UTF8View.withContiguousStorageIfAvailable (#707)
Motivation:

The new shiny Swift 5 gives us fast access to the UTF8 bytes (if
available, which mostly means not bridged from Cocoa), we should use
that.

Modifications:

use UTF8View.withContiguousStorageIfAvailable

Result:

faster String access
2018-12-14 18:19:55 +00:00
Cory Benfield 15be5243ef Improve ByteBuffer String APIs (#696)
Motivation:

ByteBuffer has pretty good string writing APIs, but they're imperfect.
In particular, the methods in ByteBuffer-aux both return optional Int,
which is strange as they cannot fail. We also only have support for writing
strings in UTF-8.

Modifications:

- ByteBuffer.set(string:at:) and ByteBuffer.write(string:) now both
     return `Int`, and their return value has been made discardable.
- NIOFoundationCompat has been expanded with two new methods for writing
     strings to ByteBuffers in various encodings using Foundation's
     encoding support: ByteBuffer.set(string:encoding:at:) and
     ByteBuffer.write(string:encoding:).
- NIOFoundationCompat has also been expanded with a companion to the
     already existing ByteBuffer.getString(at:length:encoding), namely
     ByteBuffer.readString(length:encoding:).
- New error enum for reporting failures to encode.

Result:

Easier to work with strings in a wider variety of cases with
ByteBuffer

Resolves #253.
2018-12-14 17:25:13 +00:00
Johannes Weiss ee6534f627
update tools-version to 5.0 & fix latest warnings (#704)
Motivation:

The latest Swift 5.0s bring us new goodies (hence tools version) and
also more warnings, hence the fixes for them.

Modifications:

- set tools-version to 5.0
- fix warnings
- workaround https://bugs.swift.org/browse/SR-9514

Result:

happier developers
2018-12-14 12:34:08 +00:00
Bas Broek 6772f13c29 Change unnecessary functions to variables (#695)
* Change unnecessary functions to variables

Motivation:

The changed functions do not have any side effects and therefore better convey intent when being a simple computed variable.

Modifications:

Changes:

- `func markedElementIndex() -> Int?` to `var markedElementIndex: Int?`
- `func markedElement() -> E?` to `var markedElement: E?`
- `func hasMark() -> Bool` to `var hasMark: Bool`

Result:

- improved code quality
2018-12-11 17:50:58 +00:00
Cory Benfield 55e4bc805e
Reunify errors into a single enum. (#690)
Motivation:

If we're going to have errors in enumerations, we should aim to have as
few as possible. We wanted to throw away these two, so let's do it.

Modifications:

- Removed `ChannelLifecycleError`, moved case to `ChannelError`.
- Removed `MulticastError`, moved cases to `ChannelError`.
- Removed manual `Equatable` conformance, used synthesised one.
- Pulled `connectFailed` out of `ChannelError`, as it made it impossible to
    write a correct implementation of `Equatable`.
- Conformed `NIOConnectionError` to `Error` instead.

Result:

Better error handling.

Resolves #620
2018-12-11 08:44:45 +00:00
Johannes Weiss ce39ec20c0 all caps for SNI (#693)
Motivation:

In Swift, abbreviations use the same case for all letters, therefore it
should be `SNI` and not `Sni`.

Modifications:

changes `Sni` to `SNI`

Result:

more consistent with naming guidelines
2018-12-10 20:28:10 +00:00
Johannes Weiss f6b4acc133 changed port/HTTP version parts to Ints (#691)
Motivation:

- `Int` is the currency type for integral things and we already sort of
  changed the the type for ports but not everywhere.
- generic parameters that aren't just 'any type' shouldn't be just `T`
  or `S` or something

Modifications:

- make more use of `Int`
- rename generic parameters to something more descriptive like `Bytes`

Result:

easier to read/write NIO code
2018-12-10 20:18:13 +00:00
Chris Eidhof 285a1c1897 Replace reduce(true) and reduce(false) with allSatisfy (#546) 2018-12-10 18:30:01 +00:00
Johannes Weiss 305ee9818b make factory method names start with make (#692)
Motivation:

Swift naming guidelines mandate that factory methods start with `make`,
like `makeSomething`. We had a few that were `newSomething`.

Modifications:

make all factories start with make

Result:

more compliant to Swift naming rules
2018-12-10 17:59:24 +00:00
Johannes Weiss cbc214938a
first cut at B2MD v2 (#675)
Motivation:

Explain here the context, and why you're making that change.
What is the problem you're trying to solve.

Modifications:

Describe the modifications you've done.

Result:

After your change, what will change.
2018-12-10 16:23:12 +00:00
Johannes Weiss 9b78557aff kick off NIO2 (#678)
Motivation:

NIO2 development starts now.

Modifications:

Made NIO Swift 5-only for everything else see docs/public-api-changes-NIO1-to-NIO2.md

Result:

NIO2 development can start.
2018-12-07 21:15:34 +00:00
Johannes Weiss a20e129c22 change newPromise(for: T.Type) to newPromise(of: T.Type) (#672)
Motivation:

making a promise of a type is more grammatical than making a promise for
a type.

Modifications:

s/newPromise(for/newPromise(of/g

Result:

more grammar
2018-11-28 17:32:07 +00:00
Johannes Weiss c1a84a0085 optional type parameter for newPromise() (#671)
Motivation:

When creating new promises I always find it very frustrating to type the
`: EventLoopPromise<Type>` type annotation but it's necessary for the
compiler to know type the promise will be fulfilled with.

Modifications:

allow an optional `for: SomeType.self` parameter for `newPromise` as

    let p = eventLoop.newPromise(for: Int.self)

is much easier to type than

    let p: EventLoopPromise<Int> = eventLoop.newPromise()

Result:

easier to write code
2018-11-28 12:18:03 +00:00
Johannes Weiss 6f3671de4e
fix some test warnings (#659)
Motivation:

I recently removed a bogus assertion but forgot to remove some now
useless variables.

Modifications:

Remove those useless variables.

Result:

Only deprecation warnings left.
2018-11-21 18:50:50 +00:00
Johannes Weiss 6cf207bdc7
ByteBuffer test: remove bogus test assertion (#655)
Motivation:

One ByteBuffer test was (for whatever reason) asserting that realloc
never succeeds in realloc'ing from 16 to 32 bytes. That just failed on
macOS, presumably an allocator change.

Modifications:

remove bogus assertion about reallocs ability to grow allocations.

Result:

tests more stable
2018-11-15 12:09:12 +00:00
Johannes Weiss 7445783b96
connect timeout tests: work around ECONNREFUSED (#653)
Motivation:

Some network configurations might disallow connecting to unknown IP
addresses. The effect of that is that we might see `ECONNREFUSED` when
trying to connect to 198.51.100.254 which nominally is reserved for
documentation only (ie. we shouldn't get any RSTs).

Modifications:

ignore `ECONNREFUSED` in the timeout tests too

Result:

tests stable in less permissive network environments
2018-11-13 16:34:44 +00:00
Cory Benfield a0b3b19cf4
Provide ChannelPipeline.remove methods with promises. (#651)
Motivation:

ChannelPipeline.remove0 contains a comment that indicates that users
were expected to be able to use the ChannelHandlerContext when both
handlerRemoved and the promise for channel removal call out.

This works when invoking remove() from outside the event loop, but if
a handler invokes remove on itself then it will only be able to attach
a callback to the future *after* the callout occurs. This means that a
ChannelHandler removing itself from the pipeline cannot rely on there
being a moment when it can still invoke the ChannelHandlerContext, but
when it is no longer a formal part of the pipeline.

This kind of behaviour is useful in some unusual cases, and it would
be nice to support it.

Modifications:

- Added remove() methods that accept promises as input.
- Rewrote the current remove() methods in terms of the new ones.
- Added tests.

Result:

ChannelHandlers can perform cleanup with a valid ChannelHandlerContext
but outside the Channel.
2018-11-07 11:50:51 +00:00
Johannes Weiss 26bee21674 fix Swift 5 warnings (mostly redundant modifiers (#642)
Motivation:

Swift 5 complains on redundant modifiers. For example declaring a
`public func` inside of a `public extension` is now a warning. I don't
agree with this but I dislike warnings even more, so...

Modifications:

remove all redundant modifiers that the compiler now warns about such as

    swift-nio/Sources/NIOPriorityQueue/PriorityQueue.swift:90:5: warning: 'public' modifier is redundant for property declared in a public extension

Result:

no warnings in Swift 5
2018-11-01 09:50:55 +00:00
Norio Nomura 287d50c373 CONNECT method should not have request body (#637)
* CONNECT method has no request body

### Motivation:

[rfc7231](https://tools.ietf.org/html/rfc7231#section-4.3.6) said:
> A payload within a `CONNECT` request message has no defined semantics;
   sending a payload body on a `CONNECT` request might cause some existing
   implementations to reject the request.

### Modifications:

Change `HTTPMethod.CONNECT.hasRequestBody` to returns `.no`.

### Result:

`HTTPRequestEncoder` does not generate chunked body for `CONNECT` method.

* Change `HTTPMethod.CONNECT.hasRequestBody` to returns `.unlikely`
2018-10-29 22:54:52 -07:00
Johannes Weiss 176dd6e856
fix potential deadlock in BlockingIOThreadPool (#634)
Motivation:

BlockingIOThreadPool used to call out with a lock held and on top of
that on the wrong thread...

Modifications:

Make BlockingIOThreadPool call out on the supplied `queue`

Result:

fewer deadlock and surprises
2018-10-19 16:52:51 +01:00
Johannes Weiss ed28803a78 update http_parser.c (#627)
Motivation:

There was an outstanding change in http_parser.c that we did not yet
have in our copy.

Modifications:

run the update http parser script and add changes as well as a test case
designed to hit the change.

Result:

ship the latest and greatest
2018-10-16 10:27:44 +01:00
Cory Benfield 19b07156e5 Rest between runs of tests that join multicast groups. (#625)
Motivation:

On some machines we've seen tests that rapidly join and leave multicast groups
hitting spurious test failures. These test failures manifest as hitting ENOMEM on
setsockopt(IP_ADD_MEMBERSHIP). The reason appears to be that the IGMP join/leave
messages that the kernel needs to emit for these joins can be queued up waiting for
a timer to fire, and if we move sufficiently quickly we can push too many
messages into that queue.

This can be avoided by avoiding the need to emit the IGMP join/leave messages
at all. We can do that by forcing the multicast joins onto the loopback interface,
as there's no value in the kernel emitting join/leaves on the loopback. Given that
for these tests the join is necessary only to get the kernel to have IGMP state,
there's no reason not to do this.

Modifications:

Forced all multicast joins onto the loopback address.

Result:

No weird ENOMEM crashes in test runs.
2018-09-28 15:28:27 +02:00
Albert Aleksieiev a59293cbcd add Android support (#609)
### Motivation:

make swift-nio compatible with Android, and pass all test in Android.

### Modifications:

* add missed `ifaddrs` implementation
* add missed thread related functions - `CNIOLinux_pthread_getname_np`, `CNIOLinux_pthread_setaffinity_np` and `CNIOLinux_pthread_getaffinity_np`
* fix types incositency between Linux and Android, e.g. `Epoll.swift` class
* make bytes counter explicitely 64bits to avoid overflow on 32bit, in `PendingWritesManager.swift` and `PendingDatagramWritesState.swift`
* fix issue with Unix domain socket, first byte need to be zero in Android
* several incosistency fixes between Linux and Android api.

### Result:

now swift-nio works on Android. All tests passed!
2018-09-27 11:32:43 +01:00
Cory Benfield 81e97329f3
Work around SE-0213 (#623)
Motivation:

In Swift 5, types that conform to ExpressibleByIntegerLiteral will now
have their init(integerLiteral:) initializer invoked whenever the
compiler sees code of the form `Type(integerLiteral)`, rather than
before where the integer literal would be created as `Int` and then
an alternative initializer would be called. This broke our tests, so
we should fix it now that we're aware of it.

Modifications:

Force the type of the argument for the one broken test line, add new
test lines that execute this code path.

Result:

Better testing, fewer compile errors.
2018-09-25 12:21:56 +01:00
Cory Benfield c73eb57694
Support UDP multicast. (#618)
Motivation:

A large number of very useful protocols are implemented using multicast
with UDP. As a result, it would be helpful to add support for joining and
leaving IP multicast groups using SwiftNIO.

Modifications:

- Defines a MulticastChannel protocol for channels that support joining and
  leaving multicast groups.
- Adds an implementation of MulticastChannel to DatagramChannel.
- Adds a interfaceIndex property to NIONetworkInterface.
- Adds if_nametoindex to the Posix enum.
- Adds a isMulticast computed property to SocketAddress
- Adds a demo multicast chat application.
- Add a number of multicast-related socket options to SocketOptionProvider.

Result:

NIO users will be able to write channels that handle multicast UDP.
2018-09-24 10:24:09 +01:00
Cory Benfield be4ea8ac74 Add SocketOptionChannel for wider socket options. (#589)
Motivation:

A small number of socket options have values that do not fit into a C
int type. Our current ChannelOption based approach for setting these
simply does not work, and cannot be extended to support the truly arbitrary
types that the setsockopt/getsockopt functions allow here.

This makes it impossible to use some socket options, which is hardly a
good place to be.

There were a number of ways we could have addressed this: we could have
special-cased all socket options with non-integer types in ChannelOption,
but I believe that would be too manual, and risk limiting users that need
to set other socket options. We could also have added a ChannelOption
that simply allows users to pass a buffer to write into or read from,
but that is a very un-Swift-like API that feels pretty gross to hold.

Ultimately, the nicest seemed to be a new protocol users could check
for, and that would provide APIs that let users hold the correct concrete
type. As with setsockopt/getsockopt, while this API is typed it is
not type-safe: ultimately, the struct we have here is treated just as a
buffer by setsockopt/getsockopt. We do not attempt to prevent users from
shooting themselves in the foot here.

This PR does not include an example use case in any server, as I will
provide such an example in a subsequent multicast PR.

Modifications:

- Added a SocketOptionChannel protocol.
- Conformed BaseSocketChannel to SocketOptionChannel.
- Wrote some tests for this.

Result:

Users can set and get sockopts with data that is larger than a C int.
2018-09-18 13:40:38 +02:00