Commit Graph

5850 Commits

Author SHA1 Message Date
Norman Maurer
1f68479e3c Minimize memory footprint of HashedWheelTimer and context-switching
Motivation:
At the moment there are two issues with HashedWheelTimer:
* the memory footprint of it is pretty heavy (250kb fon an empty instance)
* the way how added Timeouts are handled is inefficient in terms of how locks etc are used and so a lot of context-switching / condition can happen.

Modification:
Rewrite HashedWheelTimer to use an optimized bucket implementation to store the submitted Timeouts and a MPSC queue to handover the timeouts.  So volatile writes are reduced to a minimum and also the memory foot-print of the buckets itself is reduced a lot as the bucket uses a double-linked-list. Beside this we use Atomic*FieldUpdater where-ever possible to improve the memory foot-print and performance.

Result:
Lower memory-footprint and better performance
2014-05-11 15:15:46 +02:00
Trustin Lee
10ab0db8f5 More robust native library discovery in Mac OS X
Motivation:

Some JDK versions of Mac OS X generates a JNI dynamic library with '.jnilib' extension rather than with '.dynlib' extension.  However, System.mapLibraryName() always returns 'lib<name>.dynlib'. As a result, NativeLibraryLoader fails to load the native library whose extension is .jnilib.

Modification:

Try to find both '.jnilib' and '.dynlib' resources on OS X.

Result:

Dynamic libraries are loaded correctly in Mac OS X, and thus we can continue the OpenSslEngine work.
2014-05-11 18:53:15 +09:00
nmittler
35ab47a5d5 Merging HTTP/2 preface logic into connection handler
Motivation:

The HTTP/2 connection preface logic is currently handled in two places.
Reading/writing the client preface string is handled by
Http2PrefaceHandler while the reading/writing of the initial settings
frame is handled by AbstractHttp2ConnectionHandler. Given that their
isn't much code in Http2PrefaceHandler, it makes sense to just merge it
into the preface handling logic of AbstractHttp2ConnectionHandler. This
will also make configuring the pipeline simpler for HTTP/2.

Modifications:

Removed Http2PrefaceHandler and added it's logic to
AbstractHttp2ConnectionHandler. Updated other classes depending on
Http2PrefaceHandler.

Result:

All of the HTTP/2 connection preface processing logic is now in one
place.
2014-05-10 18:48:35 +02:00
Norman Maurer
496bd70e0a Use ByteBuf.readSlice(...).retain() to minimize memory copies.
Motivation:
At the moment we call ByteBuf.readBytes(...) in these handlers but with optimizations done as part of 25e0d9d we can just use readSlice(...).retain() and eliminate the memory copy.

Modifications:
Replace ByteBuf.readBytes(...) usage with readSlice(...).retain().

Result:
Less memory copies.
2014-05-10 17:21:06 +02:00
Norman Maurer
706db46b7e [#2485] Use RecvByteBufAllocator for all allocations related to read from Channel
Motivation:
At the moment we sometimes use only RecvByteBufAllocator.guess() to guess the next size and the use the ByteBufAllocator.* directly to allocate the buffer. We should always use RecvByteBufAllocator.allocate(...) all the time as this makes the behavior easier to adjust.

Modifications:
Change the read() implementations to make use of RecvByteBufAllocator.

Result:
Behavior is more consistent.
2014-05-10 15:21:25 +02:00
Tatsuhiro Tsujikawa
f978999d6a Apply HTTP/2 local settings after ACK is received
Motivation:

Previously local settings is applied on its transmission.  But this
makes settings value out-of-sync with remote endpoint.  The
application of local settings must be done after the remote endpoint
sends back its SETTINGS ACK.  This synchronization is vital to the
protocol.  Suppose that server sends SETTINGS_HEADER_TABLE_SIZE 0 on
connection establishment and resizes its header table size down to 0.
Meanwhile, client sends HEADERS which has header block encoded in
default 4096 header table size, because client has not seen the
SETTINGS from server.  Server tries to decode received HEADERS but due
to the difference of header table size, decoding process may fail.

Modifications:

We don't apply settings on transmission.  Instead, we keep track of
outstanding settings in FIFO queue.  When we get ACK, we pop oldest
outstanding settings and apply its values.

Result:

The outstanding settings values are applied when its ACK is received,
which is compliant behavior to the HTTP/2 specification.
2014-05-10 14:55:10 +02:00
nmittler
e22aed284b Various fixes for compliance with HTTP/2 spec
Motivation:

A few items were identified where the http2 codec is out of compliance
with the spec.

Modifications:

- Fixed handling of priority weight on the wire. Now adding 1 after
reading from the wire and subtracing 1 before writing.

- Fixed handling of next stream ID. Client streamIds were starting at 3,
but they need to start at 1 to allow the upgrade from HTTP/1.1. Also
making next stream ID logic more flexible. Allowing the next created
stream to be any number in the sequence following the previously created
stream.

- Disallowing SETTINGS frames with ENABLE_PUSH specified for server
endpoints. This means that attempts to write this frame from a server,
or read it from a client will fail.

Result:

The http2 implementation will be more inline with the spec.
2014-05-09 18:05:26 +02:00
nmittler
c62edc87a5 Fix build for Http2ConnectionRoundtripTest 2014-05-09 15:43:00 +02:00
Norman Maurer
e3f5414d26 Fix a race in Http2ConnectionRoundtripTest that could lead to a NPE. 2014-05-09 08:30:06 +02:00
nmittler
d5148bfee9 Adding context to Http2FrameObserver
Motivation:

The Http2FrameObserver isn't provided the ChannelHandlerContext when
it's called back. This will force observers to find an alternative means
of obtaining the context if they need to do things like copying buffers.

Modifications:

Changed the Http2FrameReader and Http2FrameObserver to include the
context. Updated all other uses of these interfaces.

Result:

Frame observers will now have the channel context.
2014-05-08 18:55:19 +02:00
nmittler
de0c416de0 Cleaning up HTTP/2 outbound flow control
Motivation:

The outbound flow controller currently has to walk the entire tree each
time to calculate the total available data for each subtree. For better
performance we should maintain a running total for each subtree as we
queue/write frames.

Modifications:

I've modified the DefaultHttp2OutboundFlowController to manage the state
of "priorityData" at each node in the priority tree, which is
essentially the total writable data for all streams in that subtree.
These totals do not take into account the connection window, as that is
applied when splitting the data across the streams at each level in the
tree.

The flow controller now sorts the children of a node by the product of
their data (for the subtree) and its weight. This is used since in
certain cases the algorithm might prefer nodes that appear later in the
list. Sorting helps keep nodes with similar characteristics (e.g. a lot
of data and a high priority) with similar output.

To help clean things up, I'm storing a FlowState for the root node as
well, which maintains the runnning total of the currently writable data
for all stream.

Another item of cleanup is that I created a GarbageCollector innerclass
within the outbound flow controller. This keeps all of the garbage
collection code in one place, away from the flow control code.

Also added some more unit tests for the flow controller.

Result:

The outbound flow controller is a bit cleaner and perhaps a bit more
fair when distributing outbound data across streams.
2014-05-08 06:49:12 +02:00
Trustin Lee
22a21cf54e Update netty-build to version 20
- Preparation for merging OpenSslEngine work
2014-05-08 09:59:18 +09:00
Norman Maurer
68083920a4 [#2469] Correctly update indices after incomplete gathering write
Motivation:
When doing a gathering write we need to update the indices after the write partial completes. In the current code-base we use the wrong value when compare the expected written bytes and the actual written bytes.

Modifications:
Use the correct value when compare.

Result:
Indices are updated correctly and so no corruption can happen when resume writing after data was only partial written before.
2014-05-07 07:08:36 +02:00
Norman Maurer
3080d14f25 Fix buffer leaks in HTTP2 codec
Motivation:
Our ci showed some buffer leaks in the http2 codec. This commit fixes all of these.

Modifications:
* Correctly release buffers in DefaultHttp2FrameWriter
* Fix buffer leaks in tests

Result:
Tests pass without leaks
2014-05-07 06:53:02 +02:00
nmittler
ca7c53d45f Add support for HTTP/2 draft 12.
Motivation:

Draft 12 has just arrived and has quite a few changes. Need to update in
order to keep current with the spec.

Modifications:

This is a rewrite of the original (draft 10) code. There are only 2
handlers now: preface and connection. The connection handler is now
callback based rather than frame based (there are no frame classes
anymore). AbstractHttp2ConnectionHandler is the base class for any
HTTP/2 handlers. All of the stream priority logic now resides in the
outbound flow controller, and its interface exposes methods for
adding/updating priority for streams.

Upgraded to hpack 0.7.0, which is used by draft12. Also removed
draft10 code and moved draft12 code to the ../http2 package
(no draft subpackage).

Result:

Addition of a HTTP/2 draft 12 support.
2014-05-06 20:22:27 +02:00
Daniel Bevenius
b1a51f0669 Adding short-curcuit option for CORS
Motivation:
CORS request are currently processed, and potentially failed, after the
target ChannelHandler(s) have been invoked. This might not be desired, for
example a HTTP PUT or POST might have been performed.

Modifications:
Added a shortCurcuit option to CorsConfig which when set will
cause a validation of the HTTP request's 'Origin' header and verify that
it is valid according to the configuration. If found invalid an 403
"Forbidden" response will be returned and not further processing will
take place.

This is indeed no help for non browser request, like using curl, which
can set the 'Origin' header.

Result:
Users can now configure if the 'Origin' header should be validated
upfront and have the request rejected before any further processing
takes place.
2014-05-06 12:06:34 +02:00
Norman Maurer
e1becd2147 Fix buffer leak introduced by #2462
Motivation:
Because of not correctly release a buffer before null out the reference a memory leak shows up.

Modifications:
Correct call buffer.release() before null out reference.

Result:
No more leak
2014-05-06 10:06:19 +02:00
Jeff Pinner
1aca3863eb SPDY: ensure SpdyHeaderBlockRawDecoder always reads entire input 2014-05-05 07:32:37 +02:00
Jeff Pinner
3f50a9cde3 SPDY: release headerBlock in SpdyFrameCodec 2014-05-05 07:26:39 +02:00
Jeff Pinner
78963635ba SPDY: remove unused code in SpdyHeaderBlockRawEncoder 2014-05-05 07:01:23 +02:00
Sun Ning
31b01c87e4 Made websocket maxFramePayloadSize configurable from WebSocketServerProtocolHandler.
Motivation:

Currently there's no way to configure maxFramePayloadSize from
WebSocketServerProtocolHandler, which is the most used entry point of
WebSocket server.

Modifications:

Added another constructor for maxFramePayloadSize.

Result:

We can configure max frame size for websocket packet in
WebSocketServerProtocolHandler. It will also keep backward compatibility
with default max size: 65536. (65536 is hard-coded max size in previous
version of Netty)
2014-05-05 06:24:40 +02:00
Norman Maurer
aba9c552cd [#2454] Correctly return null when DefaultChannelPipeline.firstContext() is called on empty pipeline
Motivation:
DefaultChannelPipeline.firstContext() should return null when the ipeline is empty. This is not the case atm.

Modification:
Fix incorrect check in DefaultChannelPipeline.firstContext() and add unit tests.

Result:
Correctly return null when DefaultChannelPipeline.firstContext() is called on empty pipeline.
2014-05-04 21:13:56 +02:00
Jeff Pinner
c09d85f699 SPDY: allow subclassing of SpdyFrameCodec 2014-05-03 14:44:08 +02:00
Trustin Lee
724aed4757 Generate the default JAR to make oss.sonatype.org happy
Motivation:

oss.sonatype.org refuses to promote an artifact if it doesn't have the
default JAR (the JAR without classifier.)

Modifications:

- Generate both the default JAR and the native JAR to make
  oss.sonatype.org happy
- Rename the profile 'release' to 'restricted-release' which reflects
  what it really does better
- Remove the redundant <quickbuild>true</quickbuild> in all/pom.xml
  We specify the profile 'full' that triggers that property already
  in maven-release-plugin configuration.

Result:

oss.sonatype.org is happy.  Simpler pom.xml
2014-05-03 17:28:28 +09:00
Trustin Lee
eb46726c52 Enforce the release is performed only from RHEL 6.5 or equivalent
Motivation:

Netty must be released from RHEL 6.5 x86_64 or compatible so that:

1) we ship x86_64 version of epoll transport officially, and
2) we ensure the ABI compatibility with older GLIBC versions.
   The shared library built on a distribution with newer GLIBC will not
   run on older distributions.

Modifications:

- When 'release' profile is active, perform an additional check using
  maven-enforcer-plugin so that 'mvn release:*' fails when running on
  non-RHEL6.5.  This rule is active only when releasing, so a user
  should not be affected.
- Simplify maven-release-plugin configuration by removing redundant
  profiles such as 'linux'.  'linux' is automatically activated when
  releasing because we now enforce the release occurs on linux-x86_64.
- Remove the no-osgi profile, which is unused
- Remove the reference to 'sonatype-oss-release' profile in all/pom.xml,
  because we always specify 'release' profile when releasing
- Rename the profile 'linux-native' to 'linux' for brevity
- Upgrade oss-parent and maven-enforcer-plugin

Result:

No one can make a mistake to release Netty on an environment that can
produce incompatible or missing native library.
2014-05-02 21:17:09 +09:00
Trustin Lee
3f57df1763 Upgrade os-maven-plugin to fix a build issue on windows-x86_32 2014-05-02 21:14:54 +09:00
Trustin Lee
89a98e9ca7 Fix a build failure due to missing classifier 2014-05-02 14:35:30 +09:00
Trustin Lee
68b4c9f2b5 Simplify native library resolution using os-maven-plugin
Motivation:

So far, we used a very simple platform string such as linux64 and
linux32.  However, this is far from perfection because it does not
include anything about the CPU architecture.

Also, the current build tries to put multiple versions of .so files into
a single JAR.  This doesn't work very well when we have to ship for many
different platforms.  Think about shipping .so/.dynlib files for both
Linux and Mac OS X.

Modification:

- Use os-maven-plugin as an extension to determine the current OS and
  CPU architecture reliable at build time
- Use Maven classifier instead of trying to put all shared libraries
  into a single JAR
- NativeLibraryLoader does not guess the OS and bit mode anymore and it
  always looks for the same location regardless of platform, because the
  Maven classifier does the job instead.

Result:

Better scalable native library deployment and retrieval
2014-05-02 04:21:29 +09:00
Norman Maurer
3508960781 Fix compile error 2014-04-30 15:58:33 +02:00
Norman Maurer
8599ab5bdb Remove ContinuationWebSocketFrame.aggregatedText()
Motivation:
Before we aggregated the full text in the WebSocket08FrameDecoder just to fill in the ContinuationWebSocketFrame.aggregatedText(). The problem was that there was no upper-limit and so it would be possible to see an OOME if the remote peer sends a TextWebSocketFrame + a never ending stream of ContinuationWebSocketFrames. Furthermore the aggregation does not really belong in the WebSocket08FrameDecoder, as we provide an extra ChannelHandler for this anyway (WebSocketFrameAggregator).

Modification:
Remove the ContinuationWebSocketFrame.aggregatedText() method and corresponding constructor. Also refactored WebSocket08FrameDecoder a bit to me more efficient which is now possible as we not need to aggregate here.

Result:
No more risk of OOME because of frames.
2014-04-30 14:49:37 +02:00
Norman Maurer
e920dc57db Correctly write pending data after ssl handshake completes. Related to [#2437]
Motivation:
When writing data from a server before the ssl handshake completes may not be written at all to the remote peer
if nothing else is written after the handshake was done.

Modification:
Correctly try to write pending data after the handshake was complete

Result:
Correctly write out all pending data
2014-04-30 14:23:34 +02:00
Norman Maurer
79fc0d2408 Correctly handle SocksCmdResponse. Related to #2428
Motivation:
Ports range check is not correct

Modification:
Allow port between 0 and 65535. 0 is wildcard / unknown port here

Result:
Correct validation
2014-04-30 10:45:14 +02:00
Norman Maurer
9707eba2b3 [#2428] Proper fix of incorrect port range check
Motivation:

In the Internet Protocol, the valid port number range is from 1 to 65535
(inclusive on the both side.)  However, SocksCmdRequest and SocksCmdResponse
refuses to construct itself when the port number 65535 is specified. Beside
this it excepts 0 as port number which should not allowed.

    Modification:

* Not raise an exception when the specified port number is 65535.
* Raise an exception when the specified port number is 0

Result:

Fixes #2428
2014-04-30 08:19:13 +02:00
Trustin Lee
9530f19a58 Fix incorrect port range check
Motivation:

In the Internet Protocol, the valid port number range is from 1 to 65535
(inclusive on the both side.)  However, SocksCmdRequest refuses to
construct itself when the port number 65535 is specified.

Modification:

Do not raise an exception when the specified port number is 65535.

Result:

Fixes #2428
2014-04-29 17:55:13 +09:00
Norman Maurer
9b147c9724 Not cause busy loop when interrupt Thread of NioEventLoop
Motivation:
Because Thread.currentThread().interrupt() will unblock Selector.select() we need to take special care when check if we need to rebuild the Selector. If the unblock was caused by the interrupt() we will clear it and move on as this is most likely a bug in a custom ChannelHandler or a library the user makes use of.

Modification:
Clear the interrupt state of the Thread if the Selector was unblock because of an interrupt and the returned keys was 0.

Result:
No more busy loop caused by Thread.currentThread().interrupt()
2014-04-28 08:19:18 +02:00
Daniel Bevenius
32e0170041 Adding support for echoing the request origin for CORS.
Motivation:
When CORS has been configured to allow "*" origin, and at the same time
is allowing credentials/cookies, this causes an error from the browser
because when the response 'Access-Control-Allow-Credentials' header
is true, the 'Access-Control-Allow-Origin' must be an actual origin.

Modifications:
Changed CorsHandler setOrigin method to check for the combination of "*"
origin and allowCredentials, and if the check matches echo the CORS
request's 'Origin' value.

Result:
This addition enables the echoing of the request 'Origin' value as the
'Access-Control-Allow-Origin' value when the server has been configured
to allow any origin in combination with allowCredentials.

This allows client requests to succeed when expecting the server to
be able to handle "*" origin and at the same time be able to send cookies
by setting 'xhr.withCredentials=true'. A concrete example of this is
the SockJS protocol which expects behaviour.
2014-04-25 18:20:18 +02:00
Norman Maurer
1b8f34f2a6 Eliminate unnecessary extra synchronization in DefaultChannelPipeline
Motivation:
At the moment whenever we add/remove a ChannelHandler with an EventExecutorGroup we have two synchronization points in the execution path. One to find the childInvoker and one for add/remove itself. We can eliminate the former by call findIInvoker in the synchronization block, as we need to synchronize anyway.

Modification:
Remove the usage of AtomicFieldUpdater and the extra synchronization in findInvoker by moving the call of the method in the synchronized(this) block.

Result:
Less synchronization points and volatile reads/writes
2014-04-25 14:14:42 +02:00
Trustin Lee
958a3b70ce Code clean-up
Motivation:

It is less confusing not to spread Thread.interrupt() calls.

Modification:

- Comments
- Move generatorThread.interrupt() to where currentThread.interrupt() is
  triggered

Result:

Code that is easier to read
2014-04-25 17:42:00 +09:00
Trustin Lee
18184c75de Undeprecate deregister() and chanelUnregistered()
Motivation:

As discussed in #2250, it will become much less complicated to implement
deregistration and reregistration of a channel once #2250 is resolved.
Therefore, there's no need to deprecate deregister() and
channelUnregistered().

Modification:

- Undeprecate deregister() and channelUnregistered()
- Remove SuppressWarnings annotations where applicable

Result:

We (including @jakobbuchgraber) are now ready to play with #2250 at
master
2014-04-25 16:50:54 +09:00
Trustin Lee
2d9735817c Synchronized between 4.1 and master (part 3)
Motivation:

4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:

Fix found differences

Result:

4.1 and master got closer.
2014-04-25 16:17:16 +09:00
Trustin Lee
28742b91a5 Fix compilation errors 2014-04-25 15:15:16 +09:00
Trustin Lee
872d4c5bc1 Synchronized between 4.1 and master again (part 2)
Motivation:
4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:
Remove ChannelHandlerInvoker.writeAndFlush(...) and the related
implementations.

Result:
4.1 and master got closer.
2014-04-25 15:07:12 +09:00
Norman Maurer
8a7d8a8ab7 Remove unused method to match up 4.1 branch
Motivation:

4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:

Remove ChannelHandlerInvokerUtil.invokeWriteAndFlush(...) as it is not used anyway and not exists in 4.1

Result:

4.1 and master got closer.
2014-04-24 21:31:13 +02:00
Norman Maurer
7fa861ab70 Synchronized between 4.1 and master
Motivation:

4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:

Fix found differences

Result:

4.1 and master got closer.
2014-04-24 20:47:26 +02:00
Trustin Lee
d2614cfc01 Synchronized between 4.1 and master
Motivation:

4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:

Fix found differences

Result:

4.1 and master got closer.
2014-04-25 00:36:01 +09:00
Norman Maurer
48f2e705d9 Resurrect channel deregistration and constructor changes
Motivation:

Due to the complexity of handling deregistration and re-registration of
a channel, we previously decided to remove the deregister() operation
completely to simplify our code.  However, we realized that it shouldn't
be that complicated to implement it during our discussion about making
I/O scheduling more flexible and more customizable [1], and thus the
removal of deregistration and re-registration is unnecessary now.

Modification:

- Revert commit c149f4bcc0
- Revert commit e743a27e75
- Make some additional adjustments

Result:

- deregister(), fireChannelUnregistered(), and channelRegistered() were
  added back..
- Channel constructors do not require an EventLoop anymore.

[1] https://github.com/netty/netty/issues/2250
2014-04-24 20:54:50 +09:00
Michael Nitschinger
797d6d94a4 [codec-memcache] Avoid NPE on channelInactive.
Motivation:
When no currentMessage has been set and the channel is inactive, a NPE is raised.

Modification:
Make sure that a currentMessage is available before checking the extras.

Result:
No more NPE raised potentially.
2014-04-23 11:41:07 +02:00
Jens Reimann
b88c7d6f9a Mark sun.nio.ch as optional
Motivation:

If sun.nio.ch is not optional this will cause troubles in the
OSGi world. The package is not exposed by default in OSGi, so
actually the whole netty framework cannot be used directly.

There are workarounds, but workarounds are ugly. Especially since
the use of sun.nio.ch is optional. So the requirement on the
package should be optional as well.

Modifications:

Make the import of sun.nio.ch optional.

Result:

If the package cannot be imported it will behave as if the package
sun.nio.ch is not present (like with other JVMs). If the package is
exposed in OSGi (e.g. bootclassloader delegation, extension fragment)
it will be used.
2014-04-23 10:37:39 +02:00
Norman Maurer
1a8a2cac13 Make NioSocketChannelTest more bullet-proof
Motivation:
I had the NioSocketChannelTest.testFlushCloseReentrance() fail sometimes on one of my linux installation. This change let it pass all the time.

Modification:
Set the SO_SNDBUF to a small value to force split writes

Result:
Test is passing all the time where it was sometimes fail before.
2014-04-23 10:05:27 +02:00
Norman Maurer
778ee88ada [#2414] Fix IllegalStateException when try to configure AbstractEpollChannel once it is deregistered
Motivation:
AbstractEpollChannel.clearEpollIn() throws an IllegalStateException if a user tries to change the autoRead configuration for the Channel and the Channel is not registered on an EventLoop yet. This makes it for example impossible to set AUTO_READ to false via the ServerBootstrap as the configuration is modifed before the Channel is registered.

Modification:
Check if the Channel is registered and if not just modify the flags directly so they are respected once the Channel is registered

Result:
It is possible now to configure AUTO_READ via the ServerBootstrap
2014-04-22 10:18:27 +02:00