Motivation:
We did recently change the Channel / ChannelHandler API to always act on the Future only. We should do the same for our handlers.
Modifications:
- Adjust http2 API
- Adjust other handlers API
Result:
Easier to use API and more consistent
Motivation:
Our current ChannelFutureListeners are too restrictive in terms of the type of the context. We should lift this a bit
Modifications:
Refactor ChannelFutureListeners to not be an enum and so allow most of its instances to be used with any ChannelOutboundInvoker.
Result:
More flexible usage
Motivation:
The need of cascade from a Future to a Promise exists. We should add some default implementation for it.
Modifications:
- Merge PromiseNotifier into Futures
- Add default cascadeTo(...) methods to Future
- Add tests to FuturesTest
- Replace usage of PromiseNotifier with Future.cascadeTo
- Use combination of map(...) and cascadeTo(...) in *Bootstrap to reduce code duplication
Result:
Provide default implementation of cascadeTo.
Motivation:
In this issue(#11578 ) discussed that tilde should not be encoded in QueryStringEncoder, this pr is to fix this problem
Modification:
Modified QueryStringEncoder so that it does not encode tilde, and added a test case
Result:
Fixes#11578
Motivation:
Making futures easier to compose, combine, and extend is useful to have as part of the API, since implementing this correctly and efficiently can be tricky.
Modification:
Add `Future.map(Function<V,R>) -> Future<R>` and `Future.flatMap(Function<V,Future<R>>) -> Future<R>` default methods to the `Future` interface.
These methods return new Future instance, that will be completed when the original future completes, and the result will be processed through the given mapping function.
These two methods take care to propagate cancellation and exceptions correctly:
Cancellation propagates both ways between the new and original future.
Failures only propagate from the original future to the returned new Future instance.
Result:
A few convenient methods for modifying and composing futures.
This PR fixes#8523, and perhaps also #2105
Motiviation:
The workflow from the default branch is the one that gets to run for all PRs, regardless of what branch they are targeting.
This means the 4.1 PR Reports workflow needs to tollerate master branch PRs, where there is no Java 8 builds.
Modification:
Make the PR Reports tolerate that the Java 8 matrix fails if they are missing.
Result:
Hopefully we'll get working PR Reports for master branch PRs now.
Motivation:
The expression "not is success" can mean that either the future failed, or it has not yet completed.
However, many places where such an expression is used is expecting the future to have completed.
Specifically, they are expecting to be able to call `cause()` on the future.
It is both more correct, and semantically clearer, to call `isFailed()` instead of `!isSuccess()`.
Modification:
Change all places that used `!isSuccess()` to mean that the future had failed, to use `isFailed()`.
A few places are relying on `isSuccess()` returning `false` for _incomplete_ futures, and these places have been left unchanged.
Result:
Clearer code, with potentially fewer latent bugs.
Motivation:
We did miss to update some code that setup the EventLoop mock and so did see test-failures due NPE's
Modifications:
Correctly mock the newPromise() method.
Result:
No more test-failures
Motivation:
232c669fa4 did add some overflow protection but did not handle null elements in the array the same as before.
Modifications:
- Break the loop if a null element was found
- Add unit test
Result:
Fixes https://github.com/netty/netty/issues/11612
Motivation:
232c669fa4 did add overflow protection but did miss to take the array offset into account and so could report false-positives
Modifications:
- Correctly take offset into account when check for overflow.
- Add unit tests
Result:
Correctly take offset into account when overflow check is performed
* Remove deprecated Channel*Handler* classes
Motivation:
There is no need to keep the older adapter and duplex classes around.
Modifications:
- Remove old adapter and duplex classes
- Adjust javadocs
Result:
Cleanup
* Address nit
Motivation:
We should just add `executor()` to the `ChannelOutboundInvoker` interface and override this method in `Channel` to return `EventLoop`.
Modifications:
- Add `executor()` method to `ChannelOutboundInvoker`
- Let `Channel` override this method and return `EventLoop`.
- Adjust all usages of `eventLoop()`
- Add some default implementations
Result:
API cleanup
Motivation:
This workflow has been broken for a couple of months now.
It would be nice if we could get junit test reports back in out PR checks.
Modificatoin:
Fix a test matrix typo.
Update workflow action versions.
Result:
Hopefully the PR Reports workflow starts working again.
Draft until it actually does work. There are probably several things wrong that will take time to work through.
Motivation:
At the moment the outbound operations of ChannelHandler take a Promise as argument. This Promise needs to be carried forward to the next handler in the pipeline until it hits the transport. This is API choice has a few quirks which we should aim to remove:
- There is a difference between if you add a FutureListener to the Promise or the Future that is returned by the outbound method in terms of the ordering of execution of the listeners. Sometimes we add the listener to the promise while in reality we usually always want to add it to the future to ensure the listerns are executed in the "correct order".
- It is quite easy to "loose" a promise by forgetting to use the right method which also takes a promise
- We have no idea what EventExecutor is used for the passed in Promise which may invalid our assumption of threading.
While changing the method signature of the outbound operations of the ChannelHandler is a good step forward we should also take care of just remove all the methods from ChannelOutboundInvoker (and its sub-types) that take a Promise and just always use the methods that return a Future only.
Modifications:
- Change the signature of the methods that took a Promise to not take one anymore and just return a Future
- Remove all operations for ChannelOutboundInvoker that take a Promise.
- Adjust all code to cope with the API changes
Result:
Cleaner API which is easier to reason about and easier to use.
Motivation:
Keeping the version of netty-tcnative correct can sometimes be hard.
Modifications:
Add entries for netty-tcnative* to the bom
Result:
Fixes https://github.com/netty/netty/issues/11567
Motivation:
Since most futures in Netty are of the `Void` type, methods like `getNow()` and `cause()` cannot distinguish if the future has finished or not.
This can cause data race bugs which, in the case of `Void` futures, can be silent.
Modification:
The methods `getNow()` and `cause()` now throw an `IllegalStateException` if the future has not yet completed.
Most use of these methods are inside listeners, and so are not impacted.
One place in `AbstractBootstrap` was doing a racy read and has been adjusted.
Result:
Data race bugs around `getNow()` and `cause()` are no longer silent.
Motivation:
We can make things easier for implementations by providing some default methods
Modifications:
- Add default methods to Channel
- Remove code from AbstractChannel
Result:
Easier to implement custom Channel
Motivation:
We should allow server initiated renegotiation when OpenSSL / BoringSSL bases SSLEngine is used as it might be used for client auth.
Modifications:
- Upgrade netty-tcnative version to be able to allow renegotiate once
- Adjust code
Result
Fixes https://github.com/netty/netty/issues/11529
Motivation:
Make SslHandler's handlerRemoved0 method release the sslEngine
even if it fails in the middle.
See details in https://github.com/netty/netty/issues/11595.
Modifications:
Wrap the release of sslEngine into a finally block.
Result:
The sslEngine would be released eventually.
Co-authored-by: Chen Liu <cliu@splunk.com>
Motivation:
We tightly integrate the TrustManger and KeyManager into our native SSL implementation which means that both of them need to support TLSv1.3 as protocol. This is not always the case and so can produce runtime exceptions.
As TLSv1.3 support was backported to Java8 quite some time now we should be a bit more conservative and only enable TLSv1.3 for our native implementation if the JDK implementation supports it as well. This also allows us to remove some hacks we had in place to be able to support it before in Java8.
Modifications:
- Only enable TLSv1.3 support for our native SSL implementation when the JDK supports it as well
- Remove OpenSslTlsv13X509ExtendedTrustManager as its not needed anymore
Result:
Fixes https://github.com/netty/netty/issues/11589
Motivation:
The generics for the existing futures, promises, and listeners are too complicated.
This complication comes from the existence of `ChannelPromise` and `ChannelFuture`, which forces listeners to care about the particular _type_ of future being listened on.
Modification:
* Add a `FutureContextListener` which can take a context object as an additional argument. This allows our listeners to have the channel piped through to them, so they don't need to rely on the `ChannelFuture.channel()` method.
* Make the `FutureListener`, along with the `FutureContextListener` sibling, the default listener API, retiring the `GenericFutureListener` since we no longer need to abstract over the type of the future.
* Change all uses of `ChannelPromise` to `Promise<Void>`.
* Change all uses of `ChannelFuture` to `Future<Void>`.
* Change all uses of `GenericFutureListener` to either `FutureListener` or `FutureContextListener` as needed.
* Remove `ChannelFutureListener` and `GenericFutureListener`.
* Introduce a `ChannelFutureListeners` enum to house the constants that previously lived in `ChannelFutureListener`. These constants now implement `FutureContextListener` and take the `Channel` as a context.
* Remove `ChannelPromise` and `ChannelFuture` — all usages now rely on the plain `Future` and `Promise` APIs.
* Add static factory methods to `DefaultPromise` that allow us to create promises that are initialised as successful or failed.
* Remove `CompleteFuture`, `SucceededFuture`, `FailedFuture`, `CompleteChannelFuture`, `SucceededChannelFuture`, and `FailedChannelFuture`.
* Remove `ChannelPromiseNotifier`.
Result:
Cleaner generics and more straight forward code.
Motivation:
At the moment why you try to build a SslContext via SslProvider.OPENSSL* and netty-tcnative* is not on the classpath it will fail with:
```
Exception in thread "main" java.lang.NoClassDefFoundError: io/netty/internal/tcnative/SSLPrivateKeyMethod
at io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:830)
at io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:611)
at io.netty.handler.codec.http.Main.main(Main.java:34)
Caused by: java.lang.ClassNotFoundException: io.netty.internal.tcnative.SSLPrivateKeyMethod
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 3 more
```
We should do better here.
Modifications:
Call `OpenSsl.ensureAvailability()` before trying to construct OpenSsl*Context instances
Result:
More clear error message like:
```
java.lang.UnsatisfiedLinkError: failed to load the required native library
at io.netty.handler.ssl.OpenSsl.ensureAvailability(OpenSsl.java:540)
at io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:830)
at io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:611)
...
Caused by: java.lang.ClassNotFoundException: io.netty.internal.tcnative.SSLContext
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at io.netty.handler.ssl.OpenSsl.<clinit>(OpenSsl.java:126)
... 68 more
```
Motivation:
These cleanups were done in another PR but were not directly related to that PR.
This extracts those changes and backports them to 4.1.
Modification:
* Remove the use of mocking in DefaultPromiseTest.
* Fix a few warnings.
* Make `testStackOverFlowChainedFuturesB` test with the right listener chain.
Result:
Cleaner code.
Motivation:
At present, the verification methods of `ZstdOptions` and `BrotliOptions` are not consistent, and the processing methods of `ZstdOptions` and `BrotliOptions` in `HttpContentCompressor` are also inconsistent.
The http2 module does not add zstd-jni dependency, so `ClassNotFoundException` may be thrown
Modification:
Added `Zstd.isAvailable()` check in `ZstdOptions` to be consistent, and added zstd-jni dependency in http2 module
Result:
The verification methods of `ZstdOptions` and `BrotliOptions` are consistent, and `ClassNotFoundException` will not be thrown
Signed-off-by: xingrufei <xingrufei@sogou-inc.com>
Motivation:
- Fix `HttpContentCompressor` errors due to missing optional compressor libraries such as Brotli and Zstd at runtime.
- Improve support for optional encoders by only considering the `CompressionOptions` provided to the constructor and ignoring those for which the encoder is unavailable.
Modification:
The `HttpContentCompressor` constructor now only creates encoder factories for the CompressionOptions passed to the constructor when the encoder is available which must be checked for Brotli and Zstd. In case of Brotli, it is not possible to create BrotliOptions if brotly4j is not available so there's actually nothing to check. In case of Zstd, I had to create class `io.netty.handler.codec.compression.Zstd` similar to `io.netty.handler.codec.compression.Brotli` which is used to check that zstd-jni is availabie at runtime.
The `determineEncoding()` method had to change as well in order to ignore encodings for which there's no `CompressionEncoderFactory` instance.
When the HttpContentCompressor is created using deprecated constructor (ie. with no CompressionOptions), we consider all available encoders.
Result:
Fixes#11581.
Motivation:
The `HttpContentCompressor.beginEncode()` method has too many if else, so consider refactoring
Modification:
Create the corresponding `CompressionEncoderFactory` according to the compression algorithm, remove the if else
Result:
The code of `HttpContentCompressor` is cleaner than the previous implementation
Signed-off-by: xingrufei <xingrufei@sogou-inc.com>
Co-authored-by: Norman Maurer <norman_maurer@apple.com>
Motivation:
Opportunities for clean up found while working on a different PR.
Modification:
* Dead code has been removed.
* Unnecessary parenthesis, qualifiers, etc. removed.
* Unused imports removed.
* Override annotations added where missing.
Result:
Cleaner code
Motivation:
This fixes a bug that would result in an `io.netty.channel.unix.Errors$NativeIoException: connectx(..) failed: Address family not supported by protocol family` error.
This happens when the connecting socket is configured to use IPv6 but the address being connected to is IPv4.
This can occur because, for instance, Netty and `InetAddress.getLoopbackAddress()` have different preferences for IPv6 vs. IPv4.
Modification:
Pass the correct ipv6 or ipv4 flags to connectx, depending on whether the socket was created for AF_INET or AF_INET6, rather than relying on the IP version of the destination address.
Result:
No more issue with TCP FastOpen on MacOS when using addresses of the "wrong" IP version.
Motivation:
89866da252 did introduce a JDK17 profile but did not adjust it for the master branch which needs java11 at least
Modifications:
Fix config
Result:
Be able to compile with JDK17
Motivation:
We should use StandardSocketOptions#IP_MULTICAST_IF as default source when joing multicast groups and only try to use the localAddress if this returns null.
Modifications:
First check if StandardSocketOptions#IP_MULTICAST_IF was set and if so use the network interface when joining mulicast groups
Result:
Fixes https://github.com/netty/netty/issues/11541
Motivation:
ccef8feedd introduced some changes to share code but did introduce a regression when decoding queries.
Modifications:
- Correctly only decode one time.
- Adjust unit test
Result:
Fixes https://github.com/netty/netty/issues/11591
Motivation:
As JDK17 is really close to be released we should add a CI job for it to ensure netty works correctly when using it.
Modifications:
Add docker config and workflow config to run CI job for JDK17
Result:
Ensure netty works on JDK17 as well
Motivation:
Sometimes intellij fails to build because the compiler cant really figure out what to do. We can workaround this by adding some explicit casts.
Modifications:
Add explicits casts
Result:
No more problems with intellij
Motivation:
We should add some docs / comment to explain what io.netty.leakDetection.acquireAndReleaseOnly is all about.
Modifications:
Add some comments
Result:
Fixes https://github.com/netty/netty/issues/11576.
Motivation:
0c9a86db81 added a change to log a message if someone tried to change the TLSv1.3 ciphers when using BoringSSL. Unfortunally the code had some error and so even if the user did not change these we logged something.
Modifications:
- Ensure there are no duplicates in the ciphers
- Correctly take TLSv1.3 extra ciphers into account when using BoringSSL
Result:
Correctly log or not log
Motivation:
The deprecated ThreadDeathWatcher produces more garbage and can delay resource release, when compared to manual resource management.
Modification:
Remove the ThreadDeathWatcher and other deprecated APIs that rely on it.
Result:
Less deprecated code.
__Motivation__
Since request.headers().getAll() will never return null. And the check null condition will not work as expected.
__Modification__
Add isEmpty() checking as well.
__Result__
Fixes#11568
Motivation:
The MacOS-specific `connectx(2)` system call make it possible to establish client-side connections with TCP FastOpen.
Modification:
Add support for TCP FastOpen to the KQueue transport, and add the `connectx(2)` system call to `BsdSocket`.
Result:
It's now possible to use TCP FastOpen when initiating connections on MacOS.
Motivation:
This test is inherently flaky due to file descriptor reuse.
Even though we have taken steps to make it less flaky, it still fails sometimes.
When it does, the error message is not very helpful.
Modification:
Make use of assertThrows and assertThat to get more descriptive error messages when the tests fail.
Result:
More meaningful messages on test failures, which may help us make the tests more resilient in the future
Motivation:
A number of classes and APIs around the ResourceLeakDetector have been deprecated for removal in Netty 5.x, because better alternatives exist.
Modification:
Remove everything in and around ResourceLeakDetector that is deprecated, and fix the few usages that were found.
Result:
Less deprecated code.
Motivation:
This class was deprecated, since a better alternative exists in `PromiseCombiner`.
Modification:
Remove `PromiseAggregator`, its Channel companion, and its test.
Result:
Less deprecated code.
Motivation:
There are lots of redundant variable declarations which should be inlined to make good look better.
Modification:
Made variables inlined.
Result:
Less redundant variable and more readable code.
Motivation:
TCP FastOpen is a pure optimisation, that is opportunistically applied.
There is no reason to make it specific to the epoll transport, and in the future we could add support to other transports.
Besides, the client-side equivalent, TCP_FASTOPEN_CONNECT, is already transport agnostic.
Modification:
Move the TCP_FASTOPEN channel option from EpollChannelOption to ChannelOption.
Mark the field in EpollChannelOption as deprecated.
Result:
All channel options related to TCP FastOpen are now transport agnostic.
However, we still only actually support TFO on the epoll transport.