Add Android support
### Motivation:
Support the Android platform.
### Modifications:
Add Android imports and fix the default temporary directory to be
correct for the OS.
### Result:
The package will build and test on Android.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
Motivation:
The latest NIO release deprecated a number of APIs and added more
Sendable contraints.
Modifications:
- Use sync APIs where possible
- Use `_deprecated` but not `@deprecated` NIOFileHandle API
- Stop using NIOAny
Result:
No warnings
Enable MemberImportVisibility check on all targets. Use a standard
string header and footer to bracket the new block for ease of updating
in the future with scripts.
### Motivation:
To migrate to GitHub actions and centralised infrastructure.
### Modifications:
Changes of note:
* Adopt swift-format using rules from SwiftNIO
* Remove scripts and docker files which are no longer needed
### Result:
Feature parity with old CI.
### Motivation:
`LineBasedFrameDecoder.decodeLast` throws an error if there is more than
one frame’s worth of bytes remaining in the buffer.
This is in violation of the `NIOSingleStepByteToMessageDecoder`protocol
requirement that this method be called in a loop until all bytes are
decoded.
### Modifications:
* The method now only throws if the decode operation could not return a
frame and there are bytes left in the buffer (previously only the latter
criterion applied).
* Method documentation is updated.
* Test added.
### Result:
`LineBasedFrameDecoder.decodeLast` can cope with more edge cases.
Co-authored-by: Rick Newton-Rogers <rnro@apple.com>
Motivation:
The NIOPCAPRingBuffer can limit the number of fragment or the total
number of bytes in its buffer or both. When configuring the buffer to
limit only the maximum number of bytes it sets the maximum number of
fragments allowed to `.max`. On `init` the buffer has enough capacity
reserved to store tha maximum number of fragments.
This would be a large and potentially totally unnecessary allocation.
That is, if it didn't crash at runtime. It crashes at runtime as
`CircularBuffer` converts the requested capacity to a `UInt32` which
traps if you pass it an `Int.max`.
Modifications:
- Don't reserve capacity on init
- Adjust the test which tests the byte limit to not set a capacity as
well
Result:
- `NIOPCAPRingBuffer(maximumBytes:)` doesn't crash
Motivation:
Now that Swift 5.9 is GM we should update the supported versions and
remove 5.6
Modifications:
* Update `Package.swift`
* Remove `#if swift(>=5.7)` guards
* Delete the 5.6 docker compose file and make a 5.10 one
* Update docs
Result:
Remove support for Swift 5.6, add 5.10
Motivation
Per SwiftNIO's formal version policy, we are ready to drop support for
Swift 5.5.
Modifications
This patch removes the support for 5.5 and all supporting
infrastructure. This includes the test generation functionality, which
is no longer required, as well as the files generated by that
functionality. It updates the dockerfile for 5.8, and it removes all
conditional compilation checks that are now definitionally true.
Result
A nice, clean, 5.6+ codebase
Motivation
syncClose will block whatever thread it's on indefinitely. That makes it
unsafe to call in async contexts.
Modifications
Add a new close() method that's async.
Make the existing method unavailable from async.
Add some tests.
Results
Easier to close these from async contexts
# Motivation
Currently the `QuiescingHelper` is crashing on a precondition if you call shutdown when it already was shutdown. However, that can totally happen and we should support it.
# Modification
Refactor the `QuiescingHelper` to exhaustively switch over its state in every method. Furthermore, I added a few more test cases to test realistic scenarios.
# Result
We are now reliable checking our state and making sure to allow most transitions.
* ServerQuiescingHelper no longer leaking promises
Motivation:
ServerQuiescingHelper leaked promises when promise left scope and not succeeded
Modifications:
Failing promise within a deinit
* Minor fixes
* generating linux tests
* mini update
Motivation:
Moving the HTTP1ProxyConnectHandler into swift-nio-extras will make the
code which is generally useful when dealing with HTTP1 proxies available
more easily to a wider audience.
Modifications:
The code and tests are copied over from 0b5bec741b/Sources/AsyncHTTPClient/ConnectionPool/ChannelHandler/HTTP1ProxyConnectHandler.swift.
Result:
HTTP1ProxyConnectHandler will be surfaced via the NIOExtras library
Motivation:
An index page ties all the other documentation together
Modifications:
Add index pages for the library targets.
Correct a few minor errors in the main docs.
Result:
A more joined up documentation experience.
* Improve documentation for NIOExtras
Motivation:
Docs will help users do things correctly.
Modifications:
Add missing comments, improve links.
Result:
Better docc documentation
* Docc in NIOHTTPCompression
* NIOSOCKS docc
* Correct bad symbol
* Minor typo
Co-authored-by: Cory Benfield <lukasa@apple.com>
Motivation:
With NIO 2.32.0 we broke the core NIO module up into modules that split
apart the POSIX layer and the core abstractions. As a result, this
package no longer needs to express a hard dependency on the POSIX layer.
Modifications:
- Rewrote imports of NIO to NIOCore.
- Added NIOEmbedded and NIOPosix imports where necessary in tests.
- Extended soundness script to detect NIO imports.
- Note that the main modules still depend on NIO, which is necessary
for backwards-compatibility reasons. This dependency is unused.
Result:
No need to use NIOPosix.
* fix crash in LengthFieldBasedFrameDecoder for malicious length values
Motivation:
LengthFieldBasedFrameDecoder will cause a fatal error if the length value does not fit into an `Int`.
This can happen if `lengthFieldLength` is set to `.eight` and we are on a 64 bit platform or if `lengthFieldLength` is set to `.four` and we are on a 32-bit platform.
If we then receive a length field value which is greater than `Int.max` the conversion from `UInt` to `Int` will cause a fatal error.
This could be abused to crash a server by only sending 4 or 8 bytes.
Modifications:
safely convert UInt64 & UInt32 to Int and throw an error if they can't be represented as an Int
Result:
- LengthFieldBasedFrameDecoder with lengthFieldLength set to `.eight` can no longer crash the server on a 64-bit platform
- LengthFieldBasedFrameDecoder with lengthFieldLength set to `.four` can no longer crash the server on a 32-bit platform
* use early exit instead of XCTSkipIf
* add support for `.eight` on 32-bit platforms
* limit frame length to `Int32.max`
* change test names
* throw correct error
* fix compilation for Swift 5.0 and add NIO prefix to error enum
* add test for maximum allowed length and one above the maximum allowed length
Signed-off-by: David Nadoba <dnadoba@gmail.com>
* run XCTest script
Signed-off-by: David Nadoba <dnadoba@gmail.com>
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Motivation:
The RSocket protocol uses a 24 bit length field
Modifications:
- add two new methods readInteger and writeInteger on ByteBuffer that support reading and writing integers of any size.
- add a new case (.three) to ByteLength
Result:
LengthFieldBasedFrameDecoder & LengthFieldPrepender do now support a 24 bit length field
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Motivation:
As a rule of thumb we should always forward channel events to the next
handler. #106 added an implementation for `channelInactive` but forgot
to forward it.
Modifications:
- forward `channelInactive` in the `RequestResponseHandler`
Result:
Handlers after the `RequestResponseHandler` will recieve
`channelInactive`.
Motivation:
It's possible for channels to be closed without an error; and the
`RequestResponseHandler` should tolerate that by failing any promises
for which it does not have a response for.
Modifications:
- Add `ClosedBeforeReceivingResponseError`
- Fail outstanding promises with `ClosedBeforeReceivingResponseError` in
`RequestResponseHandler.channelInactive`
- Add a test.
Result:
Outstanding request promises are failed when the channel becomes inactive.
Motivation:
Capturing all packets is expensive. Recording to a ring buffer and
then outputting on a triggering event allows this cost to be reduced.
Modifications:
Add a new handler - NIOPCAPRingCaptureHandler.
This derives from the existing NIOWritePCAPHandler and generates PCAP recordings.
A ring buffer contained in this handler stores the captured packets until RecordPreviousPackets
is received as a user message at which point they are flushed to the sink.
Result:
There is a new handler capable of outputting packet captured data only in the build up to
a known event.
Co-authored-by: Cory Benfield <lukasa@apple.com>
Co-authored-by: George Barnett <gbrntt@gmail.com>
Motivation:
Previously, WritePCAPHandler would crash if more than 4GiB of data were
either received or sent through the same instance of the
WritePCAPHandler because of a UInt32 overflow representing the TCP
sequence/ACK numbers.
Modifications:
Make TCP sequence/ACK numbers wrap around correctly.
Result:
- now you can send/receive up to 16 EiB of data :P.
- fixes rdar://61887658
Motivation:
ServerQuiescingHelper used to swallow close errors and it shoulnd't do
that.
Modifications:
Don't swallow close errors.
Result:
More correctness.
Motivation:
Use B2MDVerifier for the B2MDs in NIOExtras. Already found one bug,
separetely fixed in #51.
Modifications:
Write a basic validation test for all B2MDs.
Result:
Better test coverage.
Motivation:
JSPN-RPC uses various framing methods, one is Content-Length based
framing. NIOExtras should provide encoder/decoders for this.
Modifications:
Add such codecs.
Result:
NIOExtras more useful
Motivation:
LineBasedFrameDecoder previously would only correctly decode \r\n as a
line-ending iff \r\n were not split apart.
Modifications:
Handle \r\n arriving apart.
Result:
more correct line splitting
Motivation:
Especially with TLS but also without, in real production environments it
can be handy to be able to write pcap files from NIO directly.
Modifications:
add a ChannelHandler that can write a PCAP trace from what's going on in
the ChannelPipeline.
Result:
easier debugging in production
Motivation:
LineBasedFrameDecoder discarded everything after EOF and delivered it in
the left-over bytes error. For the real world however that doesn't make
much sense, you'd want all previously received lines and only receive
the partial lines as left-overs.
Modifications:
deliver lines until there are only partial lines left, even in case of
EOF.
Result:
LineBasedFrameDecoder more useful
Motivation:
HTTPResponseCompressor is trivially removable, so mark it.
Modifications:
make HTTPResponseCompressor implement RemovableChannelHandler
Result:
HTTPResponseCompressor can be removed
Motivation:
Currently, we crash if there's any left over bytes available because
LineBasedFrameDecoder modifies cumulationBuffer in a way that is
illegal.
Modifications:
stop modifying cumulationBuffer in an illegal way
Result:
fewer crashes
Motivation:
Frequently, people want to terminate their pipeline with a handler that
takes in requests & a promise and on receipt of the response just
fulfill that promise.
Modifications:
- add `RequestResponseHandler`
- remove outdated of contents from README.md
Result:
more useful handlers
Motivation:
Users may want to log all of inbound and/or outbound events
Modifications:
Add DebugInboundEventsHandler and DebugOutboundEventsHandler
Result:
Users can plug additional handlers into their pipeline for default printing of events or getting a hook with relevant information for their own logging mechanism.
* Adds a LengthFieldPrepender class to prepend the length onto a message.
This class is a type of byte to message encoder.
Motivation:
To encode a prepended length field on data so that messages of arbitrary size can be sent.
Can work as a pair with the ‘LengthFieldBasedFrameDecoder’.
Modifications:
Added ‘LengthFieldPrepender’
Added unit tests for ‘LengthFieldPrepender’ in ‘LengthFieldPrependerTest’
Updated the linux text files by running the script.
Result:
The length can now be easily prepended to any message.
Motivation:
ByteToMessageDecoder is extremely brittle, for example a reentrant call
into decodeLast will present the user with bytes that were previously
seen...
Modification:
Discard bytes in decodeLast
Result:
LengthFieldBasedFrameDecoder will work if close called from channelRead.