Motivation:
if connect returns EINPROGRESS we send POLL OUT and check
via socket.finishConnect if the connection is successful
Modifications:
-added new io_uring connect op
-use a directbuffer for the socket address
Result:
you are able to connect to a peer
Motivation:
when you submit a poll, io_uring still hold reference to it even if close is called
source io_uring mailing list(https://lore.kernel.org/io-uring/27657840-4E8E-422D-93BB-7F485F21341A@kernel.dk/T/#t)
Modification:
-To delete fd reference in io_uring, we use POLL_REMOVE to avoid a server socket address error
-Added a POLL_REMOVE test
Result:
server can be closed and restarted
Motivation:
We did create a lot of objects related to the completion queue and submission queue which produced a lot of GC. Beside this we also did maintain an extra map which is not really needed as we can encode everything that we need in the user_data field.
Modification:
- Reduce complexity and GC pressure by store needed informations in the user_data field
- Small refactoring of the code to move channel related logic to the channel
- Remove unused classes
- Use callback to process stuff in the completion queue and so remove all GC created by it
- Simplify by not storing channel and buffer in the event
Result:
Less GC pressure and no extra lookups for events needed
Motivation:
We use eventfd in our io_uring based transport to wakeup the eventloop. When doing so we need to be careful that we read any data previous written to it.
Modification:
- Correctly read data that was written to eventfd before submit another event related to it to the submission queue as otherwise we will see another completion event related to it asap
- Ensure we not remove the wrong event from the storted event ids (we did remove the wrong before because we reused the Event object)
- ensure we only use the submission queue from the EventLoop thread in all cases
- add another unit test
Result:
Wakeups via eventfd work as expected
Motivation:
We need to use deadlineToDelayNanos(...) to calculate the timeout for io_uring as otherwise the timeout will be scheduled at the wrong time in the future
Modifications:
Make use of deadlineToDelayNanos(...)
Result:
Correctly schedule timeou
Motivation:
There was a bug in the implemention so we missed to submit what was in the submission queue. This could lead to a deadlock. Beside this we should also process all events that we can poll without blocking and only after that process tasks. This will ensure we drain the ringbuffers in a timely manner
Modifications:
- Add missing submit() call
- Rename peek() to poll() as we consume the data so peek() is missleading
- Process all events that can be processed without blocking
Result:
Fix a bug, clarify and better performance
Motiviation:
after each pass all channel sockets are closed, after the allocator is changed(4. iteration) the server socket BeginRead wont be called after server socket creation, however, both allocators work in netty example
Modification:
increased the timeout, other tests were commented out
Result:
testsuite changes will be undone later
Motivation:
-at the moment we dont shutdown when we get a read error message
-missing autoread support
Modifications:
-even if autoread is disable, should do check if the read event is already submitted
-added new Handle exception method to shutdown the channels
Result:
EL read event can handle read errors
Motivation:
no checks for non writeable sockets
Modifications:
-Added a linked write poll to make sure that the socket does not write if it is not writeable
-Added a new boolean to avoid to submit a second write operation
Result:
writeable socket check
Motivation:
when the channel connection is lost, we dont get any notification(unless the customer has not submitted a writer or read event)
Modifications:
add rhup polling to be notified when the connection is lost
Result:
the eventloop is notified on connection losts
Motivation:
to shutdown child channels we should create new abstact client class instead of using AbstractIOUringChannel
Modifications:
-Added new child channel abstract class
-Add shutdown methods to close a channel when the connection is lost
Result:
the channels can be closed when the connection is lost
Motivation:
some tcp options (like TcpFastopen or TcpFastopenConnect etc.) are required for testsuite tests
Modification:
-copied the class LinuxSocket from epoll and JNI to load this module in io_uring jni
-some configurations have been adjusted
Result:
more tcp options are available
Motivation:
availability io_uring check for each test case
Modification:
added ioUringExit method to munmap the shared memory and close ring file descriptor which is required for the availability check
Result:
it's able to integrate testsuite tests
Motivation:
no need to poll in front of the read operation since IORING_FEAT_FAST_POLL polls anyway
Modification:
removed poll before the read event
Result:
netty echo prototype works on a custom kernel https://github.com/1Jo1/linux/tree/io_uring_off7(merge linux-block/io_uring-5.9 branch into 5.8.0) and Linux 5.9-rc1 should work as well(not tested yet)
Motivation:
The problem is that if io_uring accept/read non blocking doesnt return -EAGAIN for non-blocking sockets
in general, then it removes a way for the application to tell if
there's ever any data there.
There is a fix in Kernel 5.8 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.8&id=e697deed834de15d2322d0619d51893022c90ea2 which means we need to add poll before the accept/read event(poll<link>read/accept) to fix in netty as well
Modification:
-add poll before the accept/read event with this flag IOSQE_IO_LINK
Result:
netty prototype works on Kernel 5.8
Motivation:
wake up the blocking call io_uring which is called when a new task is added(not from the eventloop thread)
Modification:
-Added timeout operation for scheduled task(not tested yet)
-Added Poll operation
-Added two tests to reproduce the polling signal issue
Result:
io_uring_enter doesnt get any polling signal from eventFdWrite if both functions are executed in different threads
Motivation:
unnecessary use of LinuxSocket class, missing CRLF etc.
Modification:
-Add CRLF
-remove IOUringChannelConfig and LinuxSocket class
Result:
less code and cleanup
Motivation:
if you run a io_uring example two times in a row, you gonna get bind address exception
Modification:
-set SO_REUSEADDR as default
Result:
fixed bug
Motivation:
fix checkstyle errors and many classes are unnecessarily public
Modification:
-fixed maven checkstyle errors
-using package-private and final classes
Result:
better code quality
Motivation:
missing eventLoop completionQueue logic
Modification:
-mapping between channel and eventloop
-added new prototype blocking example
Result:
First running prototype
Motivation:
unix common tools native C modules were not loaded in netty_io_uring_native.c
```
Caused by: java.lang.UnsatisfiedLinkError: io.netty.channel.unix.LimitsStaticallyReferencedJniMethods.udsSunPathSize()I
at io.netty.channel.unix.LimitsStaticallyReferencedJniMethods.udsSunPathSize(Native Method)
at io.netty.channel.unix.Socket.<clinit>(Socket.java:49)
at io.netty.channel.uring.IOUringServerSocketChannel.<init>(IOUringServerSocketChannel.java:29)
... 11 more
```
Modification:
Added unix common tools native in netty_io_uring_native.c and small cleanup
Result:
fix UnsatisfiedLinkError exception
Motivation:
-missing channel configs
-we dont store byteBuf and channel for the read operation to execute channel.fireChannelReadComplete
Modifications:
-add channels configs
-new Event properties for the processing completionQueue
Result:
with these changes it will be much easier to implement the eventloop
Motivation:
JNI ring buffer implementation is inflexible and not really efficient
Modifications:
-RingBuffer instance is created in JNI which contains io_uring ring buffer information
-move the JNI ring buffer logic to Java
-added Todos
-using unsafe memory barriers loadFence and storeFence
-revert epoll file
Result:
this java ring buffer implementation is more flexible and efficient
Motivation:
prototype is not buildable and JNI io_uring implementation is missing
Modifications:
-added io_uring implementation(source from https://github.com/axboe/liburing)
-eventloop stores netty io_uring pointer which is used for two ring buffers to execute events like read and write operations in JNI
-memory barriers already included in JNI(will be changed in the future)
-pom file adopted from native epoll
Result:
prototype can finally be built
Motivation
HttpObjectDecoder and its associated classes make frequent use of
default values for maxInitialLineLength, maxHeaderSize, maxChunkSize,
etc. Today, these defaults are defined in-line in constructors and
duplicated across many classes. This repetition is more prone to error
and inconsistencies.
Furthermore, due to the current lack of builder support, if a user wants
to change just one of these values (e.g., maxHeaderSize), they are also
required to know and repeat the other default values (e.g.,
maxInitialLineLength and maxChunkSize).
The primary motivation for this change is as we are considering adding
another constructor parameter (for multiple content length behavior),
appending this parameter may require some users to have prior knowledge
of the default initialBufferSize, and it would be cleaner to allow them
to reference the default constant.
Modifications
* Consolidate the HttpObjectDecoder default values into public constants
* Reference these constants where possible
Result
No functional change. Additional telescoping constructors will be easier
and safer to write. Users may have an easier experience changing single
parameters.
The current FLowControlHandler keeps a flag to track whether a read() call is pending.
This could lead to a scenario where you call read multiple times when the queue is empty,
and when the FlowControlHandler Queue starts getting messages, channelRead will be fired only once,
when we should've fired x many times, once for each time the handlers downstream called read().
Modifications:
Minor change to replace the boolean flag with a counter and adding a unit test for this scenario.
Result:
I used TDD, so I wrote the test, made sure it's failing, then updated the code and re-ran the test
to make sure it's successful after the changes.
Co-authored-by: Kareem Ali <kali@localhost.localdomain>
Motivation:
Current implementation `StompSubframeEncoder` can encode `StompFrame` into several separate chunks or encode separately `StompHeadersSubframe` and `StompContentSubframe`. But some client libraries (e.g. stomp.js) do not support aggregation.
Modification:
Add StompWebSocketFrameEncoder for integration between origin stomp suframe encoder and `ContinuationWebSocketFrame` to support chunks on transport level.
Result:
Fixes#10261
Motivation:
9b7e091 added a special SSLHandshakeException sub-class to signal handshake timeouts but we missed to update a testcase to directly assert the type of the exception.
Modifications:
Assert directly that SslHandshakeTimeoutException is used
Result:
Test cleanup
Motivation:
There is a possibility to end up with a StackOverflowError when trying to resolve authorative nameservers because of incorrect wrapping the AuthoritativeDnsServerCache.
Modifications:
Ensure we don't end up with an overflow due wrapping
Result:
Fixes https://github.com/netty/netty/issues/10246
Motivation:
It seems that `testSwallowedReadComplete(...)` may fail with an AssertionError sometimes after my tests. The relevant stack trace is as follows:
```
java.lang.AssertionError: expected:<IdleStateEvent(READER_IDLE, first)> but was:<null>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
at io.netty.handler.flow.FlowControlHandlerTest.testSwallowedReadComplete(FlowControlHandlerTest.java:478)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
```
Obviously the `readerIdleTime` of `IdleStateHandler` and the thread sleep time before `EmbeddedChannel.runPendingTasks` are both 100ms. And if `userEvents.poll()` happened before `userEvents.add(...)` or no `IdleStateEvent` fired at all, this test case would fail.
Modification:
Sleep for a little more time before running all pending tasks in the `EmbeddedChannel`.
Result:
Fix the problem of small probability of failure.
Motivation:
`containsValue()` will check if there are multiple values defined in the specific header name, we need to use this method instead of `contains()` for the `Transfer-Encoding` header to cover the case that multiple values defined, like: `Transfer-Encoding: gzip, chunked`
Modification:
Change from `contains()` to `containsValue()` in `HttpUtil.isTransferEncodingChunked()` method.
Result:
Fixes#10320
Motivation:
Currently we passing custom websocket handshaker response headers to a `WebSocketServerHandshaker` but they can contain a reserved headers (e.g. Connection, Upgrade, Sec-Websocket-Accept) what lead to duplication because we use response.headers().add(..) instead of response.headers().set(..).
Modification:
In each `WebSocketServerHandshaker00`, ... `WebSocketServerHandshaker13` implementation replace the method add(..) to set(..) for reserved response headers.
Result:
Less error-prone
Motivation:
A new GraalVM with JDK 11 was released and GraalVM adds Java 11 support
Modification:
- Update GraalVM JDK 8 version
- Add GraalVM JDK 11 support
Result:
Build with GraalVM JDK 11 and use latest GraalVM JDK 8 version
Motivation:
We should include as much details as possible when throwing an IllegalArgumentException because of overflow in CompositeByteBuf
Modifications:
Add more details and factor out check into a static method to share code
Result:
Make it more clear why an operations failed