Commit Graph

1385 Commits

Author SHA1 Message Date
tomer doron ed50f8a41e
replace redundant commands in docker-compose files with generic one (#1010)
Motivation: keep it DRY

Modifications: move redundant commands from 18-04-5.0 and 16.04-5.1 to the generic task definitions
2019-05-21 09:12:05 -07:00
Cory Benfield 925ab655be Fix misleading comment on ELF.map (#1012)
Motivation:

We left a doc comment on EventLoopFuture.map that caused confusion by
misleadingly claiming that it could handle throwing functions. The
operation that handles throwing functions is flatMapThrowing.

Modifications:

- Removed the misleading comment and pointed users to flatMapThrowing
    instead.

Result:

Less user confusion.
2019-05-21 09:45:46 +01:00
Johannes Weiss a836b78c7a prune docker compose files (#1007)
Motivation:

We still had a bunch of docker files for NIO on Swift versions that NIO2
doesn't actually work on. Also we had allocation counter limits in
places where they don't mean anything.

Modifications:

Prune all the useless information.

Result:

Less configuration.
2019-05-18 07:10:26 +01:00
Johannes Weiss 7623b5e4f1
undo tiny public API breakage (#1008)
Motivation:

In #957 we accidentally broke the API just a little bit. We turned the
`ByteToMessageHandler.init` from

    public init(_ decoder: Decoder)

into

    public init(_ decoder: Decoder, maximumBufferSize: Int? = nil)

This looks totally benign and in almost all cases because of the default
argument, you wouldn't notice the API breakage. However, it's possible
to write code that works in NIO 2.0.0 but breaks in NIO 2.1.0. For
example

    let g: (Dummy) -> ByteToMessageHandler<Dummy> = ByteToMessageHandler<Dummy>.init
    let h: (Dummy) -> ByteToMessageHandler<Dummy> = ByteToMessageHandler<Dummy>.init(_:)

Modifications:

According to SemVer, this releases a patch that unbreaks the public API.

Result:

No API breakages (checked with `swift-api-digester` which also found the
breakage in the first place).
2019-05-17 17:20:43 +01:00
Johannes Weiss ccc459a86e TestUtils: EventCounterHandler (#1005)
Motivation:

In many unit tests, it's important to count the events. So far we have
many many ad-hoc handlers to do so but having one that counts all events
would be handy.

Modifications:

Add `EventCounterHandler` to count all events travelling the
`ChannelPipeline`.

Result:

Easier unit testing
2019-05-17 14:09:03 +01:00
George Barnett 6023c65341 Allow adding a sequence of headers to HTTPHeaders (#1004)
* Allow adding a sequence of headers to HTTPHeaders

Motivation:

When combining two collections of headers, adding each pair one-by-one
using add(name:value:) can cause multiple unnecessary reallocations of
the underlying array.

Modifications:

Provide two additional add methods to HTTPHeaders: one to add a sequence
of name/value pairs and another to add the headers from another
HTTPHeaders, both of which use `append(contentsOf:)` on the underlying
array to avoid additional reallocations.

Result:

Fewer reallocations when adding multiple headers.

* Fix incorrect documentation, make add<S: Sequence>(contentsOf:) @inlineable

* Reserve capacity and add sequentially instead of using append(contentsOf:)

* Add tests and missing @usableFromInline
2019-05-16 17:21:21 +01:00
Romain Pouclet c59c193ea7 Add an `always` method on EventLoopFuture (#981)
Add an `always` method on EventLoopFuture

Motivation:

https://github.com/apple/swift-nio/issues/665

Modifications:

* Add `always` in EventLoopFuture.swift
* Add tests

Result:

NIO Users will be able to use `.always` to, well, always run an action
wether the future succeed or not.
2019-05-15 12:02:23 +01:00
Johannes Weiss 5513bb202a
Create NIOTestUtils & add B2MD verifier (#939)
Motivation:

When writing B2MDs, there are a couple of scenarios that always need to
be tested: firehose feeding, drip feeding, many messages, ...

It's tedious writing those tests over and over again for every B2MD.

Modifications:

- Add a simple B2MD verifier that users can use in unit tests.
- Add a new, public `NIOTestUtils` module which contains utilities
  mostly useful for testing. Crucially however, it does not depend on
  `XCTest` so it can be used it all targets.

Result:

Hopefully fewer bugs in B2MDs.
2019-05-10 17:29:13 +01:00
Johannes Weiss d1c7cd0bac alloc counters: propagate tmp dir (#1000)
Motivation:

The allocation counter tests should default to using the integration
tests' tmp dir.

Modifications:

Propagate the right tmp dir.

Result:

fewer orphaned tmp dirs lying around in case of error.
2019-05-10 17:04:53 +01:00
Johannes Weiss a2ecd50863
don't hardcode NIO modules (#999)
Motivation:

The new allocation counter suite hardcoded a few things:
- the NIO and NIOHTTP1 modules
- no extra dependencies apart from the repo you're in

Modifications:

remove these hardcoded things.

Result:

allocation counter script works for nio-http2
2019-05-10 15:12:21 +01:00
Johannes Weiss 0e37ada7cc B2MDError: nest PayloadTooLargeError (#998)
Motivation:

New public NIO types must be nested in existing ones or `NIO` prefixed.
This wasn't the case for ByteToMessageDecoderPayloadTooLargeError

Modifications:

nest PayloadTooLargeError into ByteToMessageDecoderError

Result:

we stick to our rules.
2019-05-09 15:29:52 +01:00
Johannes Weiss 5d1d59868d new alloc counter tests (#996) 2019-05-09 14:27:29 +01:00
Johannes Weiss e0679121a6
HTTPDecoder: don't crash if response has no headers (#997)
Motivation:

With HTTP/1.0 and EOF framing it's possible to have a HTTP response that
doesn't have any headers. HTTPDecoder unfortunately fell flat on its
face and crashed the program if that happened.

Modifications:

- don't expect headers on responses
- add tests for that
- rename the state machine cases to reflect a request and response
  parsing

Result:

fewer crashes.
2019-05-07 15:38:58 +01:00
Cory Benfield 768c3ab328
Avoid unnecessary allocation by way of tuple conversion. (#994)
Motivation:

Due to https://bugs.swift.org/browse/SR-10614, assigning an array containing a tuple type
to a variable that expects an array containing a different-but-compatible tuple type will cause
an allocation and copy of that array storage.

In some cases this is necessary, but we were doing it in the HTTPHeaders constructors, which meant
that the swift-nio-http2 code was hitting a hilariously over the top number of allocations.

Modifications:

- Change the internal storage type of HTTPHeaders to match the public constructor.

Result:

Fewer allocations when constructing HTTPHeaders
2019-05-03 21:12:19 +01:00
Johannes Weiss 9e451149ca lower allocation limits for Swift 5.1 (#995)
Motivation:

Swift 5.1 shows much fewer allocations, let's tighten the limits.

Modifications:

Tighten the allocation limits on 5.1.

Result:

We'll catch allocation regressions much more easily.
2019-05-03 19:10:25 +01:00
Cory Benfield ae5564e4de Improve MarkedCircularBuffer performance. (#993)
Motivation:

While CircularBuffer has an inlinable implementation to improve performance, MarkedCircularBuffer
never got enhanced to have it. This harms performance in many core NIO libraries which heavily use
MCB, forcing heap allocations on almost all MCB operations.

Modifications:

- Make basically everything on MarkedCircularBuffer inlinable.

Result:

Faster code.
2019-05-03 11:00:45 +01:00
Johannes Weiss ba3733aa3a add Swift 5.1 docker file (#991)
Motivation:

We should test all available Swift versions, including snapshots.

Modifications:

Add docker compose file for Swift 5.1.

Result:

More testing.
2019-05-02 14:21:06 +01:00
Johannes Weiss 07293f2625 add tests for opening files RW (#990)
Motivation:

The new file RW opening facilities didn't have any tests and it didn't
let you specify arbitrary POSIX flags.

Modifications:

- Add tests.
- Let users specify both POSIX flags & mode.

Result:

Better code quality.
2019-05-02 12:42:35 +01:00
Liam Flynn 993a3b7521 Update naming to allow for the easy addition of a HTTP client upgrader. (#983)
Motivation:

To make the web socket upgrader naming clearer, particularly once we add a client version.

Modifications:

Rename WebSocketUpgrader too WebSocketServerUpgrader.

Result:

Improved clarity of naming on the web socket upgrader.
2019-05-02 11:02:48 +01:00
Johannes Weiss 846bc4f2f1 update contributors list (#989) 2019-05-01 15:56:12 +01:00
Cory Benfield 8e32c53e4d Make ChannelOptions.Storage initializer public. (#988)
Motivation:

Structures that users can't create don't give them much value.

Modifications:

- Make the initializer public.
- Remove that godforsaken @testable import.

Result:

ChannelOptions.Storage sparks joy.
2019-05-01 14:09:35 +01:00
Romain Pouclet 81538eca27 Add a way to get a handler from a pipeline (#974)
Motivation:

https://github.com/apple/swift-nio/issues/966

Modifications:

- Add a `handler(type:)` method on ChannelPipeline
- Add a test in ChannelPipelineTest

Result:

Provides a nicer way to get a typed handler directly from the pipeline

Closes #966
2019-04-30 15:12:22 +01:00
Romain Pouclet 4991d0930f Add a way to convert HTTP methods from/to String (#976)
Motivation:

https://github.com/apple/swift-nio/issues/701

Modifications:

* Add `init(rawValue:)`
* Add `rawValue`
* Add tests in HTTPTypesTest.swift

Result:

Users no longer have to write their own conversion methods.
2019-04-30 13:17:54 +01:00
Romain Pouclet d093ae0659 Add a Channel Handler that closes the channel (#967)
Motivation:
Because of #600, many users will start leaking Channels because they
don't close on error.

Modifications:

* Add ChannelHandlerError
* Add ChannelHandlerErrorTest

Result:

User will have access to an handler to use to automatically close
the channel in case of unhandled errors
2019-04-30 12:06:24 +01:00
Cory Benfield ae3d2988f8
Avoid keeping hold of partial bytes forever. (#984)
Motivation:

The HTTPDecoder is a complex object that has very careful state management goals. One source of this
complexity is that it is fed a stream of bytes with arbitrary chunk sizes, but needs to produce a
collection of objects that are contiguous in memory. For example, each header field name and value
must be turned into a String, which requires a contiguous sequence of bytes to do.

As a result, it is quite common to have a situation where the HTTPDecoder has only *part* of an
object that must be emitted atomically. In this situation, the HTTPDecoder would like to instruct
its ByteToMessageHandler to keep hold of the bytes that form the beginning of that object. To avoid
asking http_parser to parse those bytes twice, the HTTPDecoder uses a value called httpParserOffset
to keep track.

As an example, consider what would happen if the "Connection: keep-alive\r\n" header field was delivered
in two chunks: first "Connection: keep-al", and then "ive\r\n". The header field name can be emitted in
its entirety, but the partial field value must be preserved. To achieve this, the HTTPDecoder will store
an offset internally to keep track of which bytes have been parsed. In this case, the offset will be set
to 7: the number of bytes in "keep-al". It will then tell the rest of the code that only 12 bytes of the
original 19 byte message were consumed, causing the ByteToMessageHandler to preserve those 7 bytes.

However, when the next chunk is received, the ByteToMessageHandler will *replay* those bytes to
HTTPDecoder. To avoid parsing them a second time, HTTPDecoder keeps track of how many bytes it is
expecting to see replayed. This is the value in httpParserOffset.

Due to a logic error in the HTTPDecoder, the httpParserOffset field was never returned to zero.
This field would be modified whenever a partial field was received, but would never be returned
to zero when a complete message was parsed. This would cause the HTTPDecoder to unnecessarily keep
hold of extra bytes in the ByteToMessageHandler even when they were no longer needed. In some cases
the number could get smaller, such as when a new partial field was received, but it could never drop
to zero even when a complete HTTP message was receivedincremented.

Happily, due to the rest of the HTTPDecoder logic this never produced an invalid message: while
ByteToMessageHandler was repeatedly producing extra bytes, it never actually passed them to http_parser
again, or caused any other issue. The only situation in which a problem would occur is if the HTTPDecoder
had a RemoveAfterUpgradeStrategy other than .dropBytes. In that circumstance, decodeLast would not
consume any extra bytes, but those bytes would have remained in the buffer passed to decodeLast, which
would then incorrectly *forward them on*. This is the only circumstance in which this error manifested,
and in most applications it led to surprising and irregular crashes on connection teardown. In all
other applications the only effect was unnecessarily preserving a few tens of extra bytes on
some connections, until receiving EOF caused us to drop all that memory anyway.

Modifications:

- Return httpParserOffset to 0 when a full message has been delivered.

Result:

Fewer weird crashes.
2019-04-29 17:59:57 +01:00
Artem Redkin 93b8807c5d Add ability to open a file for writing (#975)
* Add ability to open a file for writing

Motivation:
Users can use NonBlockingFileIO for reading files, but if one wants to
write a file, there is no way to achieve that, apart from opening file
manually. I think having to inits to open files for reading and writing
would be convinient.

Modifications:
Allow to open files for writing.

Result:
Users can now open files for writing and reading in the same way.
2019-04-29 16:17:14 +01:00
Cory Benfield 12654afd21 Remove unnecessary warnings in HeapTests (#982)
Motivation:

There are a pair of vars that should be lets in the heap tests.

Modifications:

- Moved the var to let

Result:

No test warnings
2019-04-29 12:29:17 +01:00
Johannes Weiss 902cf2eb4e
README: fix outdated info (#979)
Motivation:

The link to swift.org linked to the Swift 5 development versions but now
it's released. We also mentioned swift-nio-{http2,ssl,extras,transport-services}
but we already mention them in a more prominent place.

Modifications:

Remove outdated/duped info.

Result:

Better readme
2019-04-23 20:21:16 +01:00
Johannes Weiss 2cfa777013
CircularBuffer.Index: remove bogus assert (#978)
Motivation:

CircularBuffer.Index was asserting that its size is the same as a word.
Whilst that's true on 64-bit architectures, the assert itself is bogus
and a left-over from development.

Modifications:

Remove bogus assert.

Result:

Better 32-bit support.
2019-04-23 18:41:49 +01:00
JP Simard f6692f5c37 Add 'Show on GitHub' link to API docs (#977)
* Add 'Show on GitHub' link to API docs

Addresses #955

* Remove trailing slash
2019-04-23 10:21:41 +01:00
tomer doron e32a436466 optional max payload size for ByteToMessageDecoder (#957)
* optional max payload size for ByteToMessageDecoder

Motivation:

ByteToMessageDecoder aggregate data in memory as part of their normal operation. the ability to limit how much they aggregate is critical in many real-life applications

Modifications:

* add optional maximumBufferSize argument to ByteToMessageDecoder initializer
* test for buffer size when maximumBufferSize is set and throw ByteToMessageDecoderError.payloadTooLarge error

Result:

users can limit how much memory ByteToMessageDecoder takes and handle the exception on their end
2019-04-11 14:12:59 +01:00
Johannes Weiss c90b159b4f HTTP1 example server: don't crash on empty file served (#962)
Motivation:

The file-io implementation in the example HTTP1 server just crashed on
empty file ;).

Modifications:

- fix the crash
- add integration test

Result:

fewer crashes
2019-04-10 19:28:09 +01:00
Cory Benfield 0179535b99
Simplify Heap implementation. (#960)
Motivation:

Our original Heap implementation used a bunch of static functions
in order to make it clear how it related to textbook heap
implementations. This was primarily done to ensure that it was easier
to see the correctness of the code.

However, we've long been satisfied with the correctness of the code,
and the Heap is one of the best tested parts of NIO. For this reason,
we should be free to refactor it.

Given https://bugs.swift.org/browse/SR-10346, we've been given an
incentive to do that refactor right now. This is because the Heap
is causing repeated CoW operations each time we enqueue new work
onto the event loop. That's a substantial performance cost: well
worth fixing with a small rewrite.

Modifications:

- Removed all static funcs from Heap
- Rewrote some into instance funcs
- Merged the implementation of insert into append.
- Added an allocation test to avoid regressing this change.

Result:

Faster Heap, happier users, sadder textbook authors.
2019-04-10 13:53:07 +01:00
Moritz Lang 56a2bee434 Initialize ByteBuffer from ByteBufferView (#958)
Motivation:

As Johannes previously said in (#946), there's no reason not be able to
get a ByteBuffer from a ByteBufferView.

Modifications:

I added a public initializer to ByteBuffer taking a ByteBufferView to
create a slice of the view's buffer from the same range.

Result:

`ByteBuffer` will have a public initializer to create a ByteBuffer from
a ByteBufferView.
2019-04-10 11:53:06 +01:00
Moritz Lang 4795a11e9d Fix documentation block for viewBytes method (#959)
Motivation:

The documentation popup for viewBytes did not correctly
show what the method returns.

Modifications:

I added a colon after the return doc-block keyword.

Result:

The documentation popup for viewBytes will now correctly show
what the method returns.
2019-04-09 21:08:58 +01:00
Johannes Weiss 6907e8aac4 B2MD: tests we're okay with data after EOF (#956)
Motivation:

B2MDs must be robust regarding data after EOF, just in case. Let's add
test cases for that.

Modifications:

add two tests that send a B2MD data after EOF.

Result:

we're sure we're okay with that.
2019-04-09 08:35:08 +01:00
Liam Flynn 3395d39731 Reorder ‘channel active’ calls to the same order as `_ChannelInboundHandler` and their likely chronological order. (#953)
Motivation:
When first viewing the example classes, coming to the ‘read’ method first, leaves the subject unclear as to what the method is ‘reading’.
It is preferable to view something being sent first, and then to view the reading of the response.
It also matches the call order against the protocol making it a little easier for those unfamiliar with the protocol to see which methods have been implemented.

Modifications:
Moved channel active calls to be top of the class.
Despite the diff there are no actual code modifications.
UDP Client changed to indent using spaces to match rest of project. Incidental change.

Result:
The examples are slighter clearer to read, particularly for newcomers to swift-no as the calls are in a logical chronological order.
2019-04-08 22:56:52 +01:00
Liam Flynn 06649bb8c7 Add a HTTP1 client example. It is only a simple echo which closely resembles the TCP and UDP echo examples. (#941)
Motivation:
To provide a simple example of the HTTP1 client pipeline.
To create a comparable example to the TCP and UDP demos to show what extra steps are needed for a HTTP layer.

Modifications:
Adds a NIOHTTP1Client example in a main file.
Adds a readme to the NIOHTTP1Client example.

Result:
There is now a simple example of how to send a HTTP1 client request to the server.
2019-04-05 17:38:34 +01:00
Johannes Weiss 39c6b87ff8
migration guide: Info about B2MD (#949)
Motivation:

@tomerd learned the hard way that there were some subtle changes in
B2MDs around intercepting arbitrary channel events. Previously,
intercepting those was illegal but possible. In NIO 2, it's impossible.

Modifications:

add a description for what changed

Result:

easier migrations
2019-04-05 17:22:44 +01:00
Johannes Weiss fef050a83c B2MD: don't go to final state twice (#948)
Motivation:

B2MD (in debug mode) has some checking that we never move out of a final
state in the state machine. Both .done and .error are final states.
Previously however, the code set .done in a defer block which meant that
even if the decodeLoop throws (which should bring it to .error), it goes
via .done first. That's an error because .done is already a final state
so we shouldn't move to .error after that.

Modifications:

Only move to .done if there was no error. If there was an error, we
should go straight to .error, not via .done.

Result:

- more correct B2MD
- fewer crashes (in debug mode)
2019-04-05 14:44:40 +02:00
Daniel Alm 77d90255eb Significantly improve the performance of `EventLoopFuture.{and,when}AllSucceed`. (#943)
* Significantly improve the performance of `EventLoopFuture.{and,when}AllSucceed`.

* PR improvements.

* Add the fast track for `AllComplete` as well.

* Use `future.inEventLoop` instead of pointer comparison.
2019-04-05 10:56:36 +02:00
Johannes Weiss d1c9ed1d3f add some documentation around EventLoops (#944)
Motivation:

There were a bunch of docs missing around EventLoops.

Modifications:

Add some more docs.

Result:

Happier users, CC @ianpartridge :)
2019-04-03 19:30:06 +02:00
Liam Flynn df4e078c74 Add 2 missing server readme docs. (#940)
Add missing server readme docs for WebSocket server and UDP echo server.

Motivation:
With the exception of these two samples, all client and server examples have helpful readme docs.
Provides brief description of purpose of the sample code and how to run it.

Modifications:
Adds a readme to NIOUDPEchoServer.
Adds a readme to NIOWebSocketServer.

Result:
The samples for NIOUDPEchoServer and NIOWebSocketServer have a little explanation.
2019-04-02 11:28:31 +01:00
Johannes Weiss 3336cfaca3 README: Update prerequisites (#938) 2019-04-01 10:21:08 +01:00
Liam Flynn 0c74dfbbfb Update style in TCP Client and HTTP1Server examples. (#937)
Motivation:
There is a UDP echo client which is very similar to the NIOEchoClient.
The styles of these two examples should match closely so ‘diff’ comparing will show the pertinent API differences.

Modifications:
Add self tags to member variables in the TCP echo client.
Add a self tag to a member variable in the HTTP1 server.
Remove an assert from the echo client.

Result:
The code in the TCP and UDP examples now matches and fits the SwiftNIO style.
2019-03-31 19:56:42 +01:00
Johannes Weiss 8e59048aaf API docs: repo switcher
Motivation:

API docs should be cross-linked.

Modifications:

Cross-link them.

Result:

better API docs
2019-03-31 16:18:35 +01:00
Liam Flynn 65d6f63a39 UDP Echo Client Example. (#933)
* UDP echo client example.

Motivation:

There is a UDP echo server example but it does not currently have a machine client example.
The TCP echo server has both sample client and server examples and it would be preferable to match.
The UDP client connection also differs from both the UDP server and the TCP client, so it is good to provide and example of this difference.

Modifications:

Added a UDP client example and a matching readme file.
The main swift file is a similar to the TCP echo example as possible.

Result:

There is now a clear example of how to create a simple UDP client side connection.
2019-03-31 16:18:11 +01:00
Johannes Weiss bba988ece0
README: recommend 2.0.0, not 1.0.0 2019-03-29 15:43:37 +00:00
Johannes Weiss 2b0d2e4b30 minor docs additions & fixes (#930)
Motivation:

Just spotted a few small issues in the docs.

Modifications:

fix 'em

Result:

better docs.
2019-03-27 11:53:17 +00:00
Johannes Weiss 8d5994be5f
update the podspec generator to require Swift 5.0 (#929)
Motivation:

Our podspecs should also correctly require Swift 5.

Modifications:

require Swift 5 in the podspec generator.

Result:

better podspecs for NIO2.
2019-03-26 15:50:55 +00:00