Commit Graph

197 Commits

Author SHA1 Message Date
Louis Ryan
0b12592acb Use CoalescingBufferQueue to merge data writes on a stream in HTTP2 instead of CompositeByteBuf
Motivation:

Slicing a mutable CompositeByteBuf is not the appropriate mechanism to use to track and release buffers that have been written to a channel.
In particular buffers passed over an Embedded or LocalChannel are retained after the ChannelPromise is completed and listening to the
promise to consolidate a CompositeBuffer breaks slices taken from the composite as the offset indices have changed.

In addition CoalescingBufferQueue handles taking arbitrarily sized slices of a sequence of buffers more efficiently.

Modifications:

Convert FlowControlledData to use a CoalescingBufferQueue to handle merging data writes.

Result:

HTTP2 works over LocalChannel and code is considerably simpler.
2015-07-09 10:46:53 -07:00
zhangduo
508d6e3b31 Allow numBytes == 0 when calling Http2LocalFlowController.consumeBytes.
Motivation:

Sometimes people use a data frame with length 0 to end a stream(such as jetty http2-server). So it is possible that data.readableBytes and padding are all 0 for a data frame, and cause an IllegalArgumentException when calling flowController.consumeBytes.

Modifications:

Return false when numBytes == 0 instead of throwing IllegalArgumentException.

Result:

Fix IllegalArgumentException.
2015-07-09 08:42:41 -07:00
nmittler
8a16081a93 Proper shutdown of HTTP2 encoder when channelInactive
Motivation:

The problem is described in https://github.com/grpc/grpc-java/issues/605. Basically, when using `StreamBufferingEncoder` there is a chance of creating zombie streams that never get closed.

Modifications:

Change `Http2ConnectionHandler`'s `channelInactive` handling logic to shutdown the encoder/decoder before shutting down the active streams.

Result:

Fixes https://github.com/grpc/grpc-java/issues/605
2015-07-09 07:35:55 -07:00
Norman Maurer
e43fede591 [#3945] Http2ConnectionHandler breaks channelReadComplete pipeline notification
Motivation:

Http2ConnectionHandler missed to forward channelReadComplete(...) events.

Modifications:

Ensure we notify the next handler in the pipeline via ctx.fireChannelReadComplete().

Result:

Correctly forwarding of event.
2015-07-08 07:49:17 +02:00
Scott Mitchell
a9e57f1b20 HTTP/2 limit header accumulated size
Motivation:
The Http2FrameListener requires that the Http2FrameReader accumulate ByteBuf objects. There is currently no way to limit the amount of bytes that is accumulated.

Motiviation:
- DefaultHttp2FrameReader supports maxHeaderSize which will fail fast as soon as the maximum size is exceeded.
- DefaultHttp2HeadersDecoder will respect the return value of endHeaderBlock() and fail if the max size is exceeded.

Result:
Frames which carry header data now respect a maximum number of bytes that can be accumulated.
2015-07-07 13:28:44 -07:00
Ryo Okubo
f3c3f3e60c Allow servers to specify ENABLE_PUSH to 0 explicitly
Motivation:

If server sends SETTINGS with ENABLE_PUSH, its handled as
PROTOCOL_ERROR in spite of the value. But the value specified to
0 may be allowed in RFC7540.

Modifications:

Check whether ENABLE_PUSH sent from a server is 0 or not.

Result:

When server specifies ENABLE_PUSH to 0 explicitly, client doesn't
handle it as PROTOCOL_ERROR.
2015-07-07 10:00:30 -07:00
nmittler
b5337abe2a Fixing exception in StreamBufferingEncoderTest.
Motivation:

NPE doesn't cause the tests to fail but should get fixed.

Modifications:

Modified the StreamBufferingEncoderTest to mock the ctx to return a promise.

Result:

Fixes #3905
2015-06-24 12:09:39 -07:00
Louis Ryan
bbf1829f2f Make the flow-controllers write fewer, fatter frames to improve throughput.
Motivation:

Coalescing many small writes into a larger DATA frame reduces framing overheads on the wire and reduces the number of calls to Http2FrameListeners on the remote side.
Delaying the write of WINDOW_UPDATE until flush allows for more consumed bytes to be returned as the aggregate of consumed bytes is returned and not the amount consumed when the threshold was crossed.

Modifications:
- Remote flow controller no longer immediately writes bytes when a flow-controlled payload is enqueued. Sequential data payloads are now merged into a single CompositeByteBuf which are written when 'writePendingBytes' is called.
- Listener added to remote flow-controller which observes written bytes per stream.
- Local flow-controller no longer immediately writes WINDOW_UPDATE when the ratio threshold is crossed. Now an explicit call to 'writeWindowUpdates' triggers the WINDOW_UPDATE for all streams who's ratio is exceeded at that time. This results in
  fewer window updates being sent and more bytes being returned.
- Http2ConnectionHandler.flush triggers 'writeWindowUpdates' on the local flow-controller followed by 'writePendingBytes' on the remote flow-controller so WINDOW_UPDATES preceed DATA frames on the wire.

Result:
- Better throughput for writing many small DATA chunks followed by a flush, saving 9-bytes per coalesced frame.
- Fewer WINDOW_UPDATES being written and more flow-control bytes returned to remote side more quickly, thereby improving throughput.
2015-06-19 15:19:53 -07:00
nmittler
045602bd76 Better error when first HTTP/2 frame is not SETTINGS
Motivation:

Bootstrap of the HTTP/2 can take a lot of paths and a lot of things can go wrong in the initial handshakes leading up to establishment of HTTP/2 between client and server. There have been many times where handshakes have failed silently, leading to very cryptic errors that are hard to debug.

Modifications:

Changed the HTTP/2 handler and decoder to ensure that the very first data on the wire (WRT HTTP/2) is SETTINGS/preface+SETTINGS. When this is not the case, a connection error is thrown with the bytes that were found instead.

Result:

Fixes #3880
2015-06-18 15:58:15 -07:00
Trustin Lee
88cf2ee212 Lazily instantiate HttpServerUpgradeHandler.UpgradeCodec
Related: #3814

Motivation:

To implement the support for an upgrade from cleartext HTTP/1.1
connection to cleartext HTTP/2 (h2c) connection, a user usually uses
HttpServerUpgradeHandler.

It does its job, but it requires a user to instantiate the UpgradeCodecs
for all supported protocols upfront. It means redundancy for the
connections that are not upgraded.

Modifications:

- Change the constructor of HttpServerUpgradeHandler
  - Accept UpgraceCodecFactory instead of UpgradeCodecs
- The default constructor of HttpServerUpgradeHandler sets the
  maxContentLength to 0 now, which shouldn't be a problem because a
  usual upgrade request is a GET.
- Update the examples accordingly

Result:

A user can instantiate Http2ServerUpgradeCodec and its related objects
(Http2Connection, Http2FrameReader/Writer, Http2FrameListener, etc) only
when necessary.
2015-06-10 12:08:00 +09:00
Trustin Lee
4c63d9261a Do not use hard-coded handler names in HTTP/2
Motivation:

Our HTTP/2 implementation sometimes uses hard-coded handler names when
adding/removing a handler to/from a pipeline. It's not really a good
idea because it can easily result in name clashes. Unless there is a
good reason, we need to use the reference to the handlers

Modifications:

- Allow null as a handler name for Http2Client/ServerUpgradeCodec
  - Use null as the default upgrade handler name
- Do not use handler name strings in some test cases and examples

Result:

Fixes #3815
2015-06-10 11:49:27 +09:00
Trustin Lee
8f29925e4b Fix a buffer leak in StreamBufferingEncoderTest
Related: #3871

Motivation:

StreamBufferingEncoderTest does not release when writeGoAway() is
called.

Modifications:

Release the buffer in mock object arguments

Result:

No buffer leak
2015-06-09 14:24:32 +09:00
Scott Mitchell
e58e338ffd HTTP/2 shutdown cleanup miss
Motiviation:
https://github.com/netty/netty/pull/3865 was merged from a machine with old code. A test case that was updates was not merged.

Modifications:
- Merge the missing test case updates

Result:
Test case no longer fails.
2015-06-08 07:59:53 -07:00
Scott Mitchell
2449760ea3 HTTP/2 ConnectionHandler close cleanup
Motiviation:
The connection handler stream close operation is unconditionally adding a listener object to a future. We may not have to add a listener at all because the future has already been completed.

Modifications:
- If the future is done, directly invoke the logic without creating/adding a new listener.

Result:
No need to create/add listener if the future is already done in close logic.
2015-06-08 07:47:50 -07:00
nmittler
455682cae0 Porting BufferingHttp2ConnectionEncoder from gRPC
Motivation:

gRPC's BufferingHttp2ConnectionEncoder is a generic utility that simplifies client-side applications that want to allow stream creation without worrying about violating the SETTINGS_MAX_CONCURRENT_STREAMS limit.  Since it's not gRPC-specific it makes sense to move it into Netty proper.

Modifications:

Adding the BufferingHttp2ConnectionEncoder and it's unit test.

Result:

Netty now supports buffering stream creation.
2015-06-05 05:50:44 -07:00
Trustin Lee
7b177cea5b Replace SpdyOrHttpChooser and Http2OrHttpChooser with ApplicationProtocolNegotiationHandler
Motivation:

SpdyOrHttpChooser and Http2OrHttpChooser duplicate fair amount code with each other.

Modification:

- Replace SpdyOrHttpChooser and Http2OrHttpChooser with ApplicationProtocolNegotiationHandler
- Add ApplicationProtocolNames to define the known application-level protocol names

Result:

- Less code duplication
- A user can perform dynamic pipeline configuration that follows ALPN/NPN for any protocols.
2015-06-05 12:01:18 +09:00
Trustin Lee
2e231283cf Improve the API design of Http2OrHttpChooser and SpdyOrHttpChooser
Related: #3641 and #3813

Motivation:

When setting up an HTTP/1 or HTTP/2 (or SPDY) pipeline, a user usually
ends up with adding arbitrary set of handlers.

Http2OrHttpChooser and SpdyOrHttpChooser have two abstract methods
(create*Handler()) that expect a user to return a single handler, and
also have add*Handlers() methods that add the handler returned by
create*Handler() to the pipeline as well as the pre-defined set of
handlers.

The problem is, some users (read: I) don't need all of them or the
user wants to add more than one handler. For example, take a look at
io.netty.example.http2.tiles.Http2OrHttpHandler, which works around
this issue by overriding addHttp2Handlers() and making
createHttp2RequestHandler() a no-op.

Modifications:

- Replace add*Handlers() and create*Handler() with configure*()
- Rename getProtocol() to selectProtocol() to make what it does clear
- Provide the default implementation of selectProtocol()
- Remove SelectedProtocol.UNKNOWN and use null instead, because
  'UNKNOWN' is not a protocol
- Proper exception handling in the *OrHttpChooser so that the
  exception is logged and the connection is closed when failed to
  select a protocol
- Make SpdyClient example always use SSL. It was always using SSL
  anyway.
- Implement SslHandshakeCompletionEvent.toString() for debuggability
- Remove an orphaned class: JettyNpnSslSession
- Add SslHandler.applicationProtocol() to get the name of the
  application protocol
  - SSLSession.getProtocol() now returns transport-layer protocol name
    only, so that it conforms to its contract.

Result:

- *OrHttpChooser have better API.
- *OrHttpChooser handle protocol selection failure properly.
- SSLSession.getProtocol() now conforms to its contract.
- SpdyClient example works with SpdyServer example out of the box
2015-06-05 12:00:44 +09:00
Scott Mitchell
4cac79594c Update HTTP/2 to RFCs
Motivation:
HTTP/2 RFC 7540 has been released.

Modifications:
- Make changes RFC 7540 introduced since draft 17.

Result:
HTTP/2 RFC 7540 compliant code
2015-05-26 16:08:26 -07:00
nmittler
210baee6bb Allow manual configuration of initial HTTP/2 SETTINGS frame.
Motivation:

There is currently no good way to configure the initial SETTINGS frame. The individual settings can be configured on the various components, but doing this bypasses the proper setting update logic in the encoder.

Modifications:

Updated Http2ConnectionHandler to optionally take initial settings in the constructor. If not provided, it will default to current behavior.

Result:

Easy manual configuration of initial settings.
2015-05-21 13:18:16 -07:00
nmittler
203ec13dd4 Fixing logging of ping acks in Http2OutboundFrameLogger
Motivation:

The Http2OutboundFrameLogger logs all PING frames as not acks.

Modifications:

Changed the logger to correctly log PING acks.

Result:

PING acks are logged correctly.
2015-05-20 08:58:48 -07:00
Scott Mitchell
2419f0c417 HTTP/2 GOAWAY Reference Count Issue
Motiviation:
The Http2ConnectionHandler is incrementing the reference count in the goAway method for the debugData buffer after it has already been sent and maybe consumed. This may result in an IllegalRefCountException to be thrown. The unit tests also encounter buffer leaks because they have not been updated to invoke the listener which releases the buffer in the goAway method.

Modifications:
- The retain() call should be before the frameWriter().writeGoAway(...) call
- The unit tests which call goAway must also invoke the operationComplete(..) method for the listener.

Result:
No IllegalRefCountException. Less buffer leaks in tests.
2015-05-15 10:49:02 -07:00
Scott Mitchell
c61e50bf4f [#3724] HTTP/2 Headers END_STREAM results in RST_STREAM
Motivation:
If headers are sent on a stream that does not yet exist and the END_STREAM flag is set we will send a RST_STREAM frame. We should send the HEADERS frame and no RST_STREAM.

Modifications:
DefaultHttp2RemoteFlowController should allow frames to be sent if stream is created in the 'half closed (local)' state.

Result:
We can send HEADERS frame with the END_STREAM flag sent without sending a RST_STREAM frame.
2015-05-07 08:31:38 -07:00
nmittler
94f068c1c9 Addressing a few more comments from #3749.
Motivation:

There were a few outstanding comments that were left unaddressed after committing the changes for #3749.

Modifications:

Changes to Http2ConnectionHandler.goAway():

- Retaining the debugData buffer, rather than always converting it to a string immediately.
- Changing log level for sending a GOAWAY with error to debug.

Result:

Remaining comments from #3749 are addressed.
2015-05-07 07:57:04 -07:00
nmittler
36061c50b1 Allow override of HTTP/2 graceful connection shutdown.
Motivation:

Currently the graceful shutdown of the HTTP/2 connection waits until there are no active streams. There may be use cases that buffer stream creation (due to limits imposed by MAX_CONCURRENT_STREAMS), in which case they may still want those streams to complete before closing.

Modifications:

Added a isGracefulShutdownComplete method to Http2ConnectionHandler, which can be overridden by a subclass.

Result:

Graceful shutdown logic can be overridden.
2015-05-06 14:41:16 -07:00
nmittler
1a2fc90f0f Allowing inbound HTTP/2 frames after sending GOAWAY
Motivation:

If the client closes, a GOWAY is sent with a lastKnownStream of zero (since the remote side never created a stream). If there is still an exchange in progress, inbound frames for streams created by the client will be ignored because our ignore logic doesn't check to see if the stream was created by the remote endpoint. Frames for streams created by the local endpoint should continue to come through after sending GOAWAY.

Modifications:

Changed the decoder's streamCreatedAfterGoAwaySent logic to properly ensure that the stream was created remotely.

Result:

We now propertly process frames received after sending GOAWAY.
2015-05-05 15:03:28 -07:00
nmittler
76afa0c921 Fixing isDone in SimpleChannelPromiseAggregator
Motivation:

The isDone method is currently broken in the aggregator because the doneAllocatingPromises accidentally calls the overridden version of setSuccess, rather than calling the base class version. This causes the base class's version to never be called since allowNotificationEvent will evaluate to false. This means that setSuccess0 will never be set, resulting in isDone always returning false.

Modifications:

Changed setSuccess() to call the base class when appropriate, regardless of the result of allowNotificationEvent.

Result:

isDone now behaves properly for the promise aggregator.
2015-05-05 12:45:57 -07:00
Louis Ryan
f6e1f4947d Have Http2LocalFlowController.consumeBytes indicate whether a WINDOW_UPDATE was written 2015-05-04 13:21:53 -07:00
Louis Ryan
b122faea68 Remove explicit flushes from HTTP2 encoders, decoders & flow-controllers
Motivation:

Allow users of HTTP2 to control when flushes occur so they can optimize network writes.

Modifications:

Removed explicit calls to flush in encoder, decoder & flow-controller
Connection handler now calls flush on read-complete to enable batching writes in response to reads

Result:

Much less flushing occurs for normal HTTP2 request and response patterns.
2015-04-30 17:44:53 -07:00
Scott Mitchell
694eab76eb HTTP/2 Warnings Cleanup
Motiviation:
There are a few spots in the HTTP/2 codec where warnings were generated and can be avoided.

Modifications:
Clean up the cause of the warnings.

Result:
Less warnings.
2015-04-29 11:45:52 -07:00
Scott Mitchell
ba0f920fee HTTP/2 Sending a GO_AWAY with an error code should close conneciton
Motivation:
The specification requires that sending a GO_AWAY frame with an error code results in closing the TCP connection https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-5.4.1.

Modifications:
- Close the connection after succesfully sending a GO_AWAY.

Result:
Fixes https://github.com/netty/netty/issues/3653
2015-04-29 11:16:51 -07:00
Jakob Buchgraber
e3980a6487 Http2ConnectionHandler should propagate channelActive and channelInactive events.
Motivation:

The Http2ConnectionHandler incorrectly doesn't propagate channelActive and channelInactive events and thus breaks the pipeline
for other ChannelHandler.

Modification:

- Add calls to super.channelActive() and super.channelInactive().
- Remove unused methods.

Result:

- Http2ConnectionHandler can be used with other ChannelHandlers.
2015-04-28 20:11:12 -07:00
Scott Mitchell
f1e122a0c1 ByteString arrayOffset method
Motivation:
The ByteString class currently assumes the underlying array will be a complete representation of data. This is limiting as it does not allow a subsection of another array to be used. The forces copy operations to take place to compensate for the lack of API support.

Modifications:
- add arrayOffset method to ByteString
- modify all ByteString and AsciiString methods that loop over or index into the underlying array to use this offset
- update all code that uses ByteString.array to ensure it accounts for the offset
- add unit tests to test the implementation respects the offset

Result:
ByteString and AsciiString can represent a sub region of a byte[].
2015-04-24 18:54:19 -07:00
nmittler
c98195714d Optimizing user-defined stream properties.
Motivation:

Streams currently maintain a hash map of user-defined properties, which has been shown to add significant memory overhead as well as being a performance bottleneck for lookup of frequently used properties.

Modifications:

Modifying the connection/stream to use an array as the storage of user-defined properties, indexed by the class that identifies the index into the array where the property is stored.

Result:

Stream processing performance should be improved.
2015-04-23 12:40:51 -07:00
Scott Mitchell
9d66180290 HTTP/2 Flow Controller required memory reduction
Motivation:
Currently we allocate the full amount of state for each stream as soon as the stream is created, and keep that state until the stream is GC. The full set of state is only needed when the stream can support flow controlled frames. There is an opportunity to reduce the required amount of memory, and make memory eligible for GC sooner by only allocating what is necessary for flow control stream state.

Modifications:

Introduce objects which require 'less' state for local/remote flow control stream state.
Use these new objects when streams have been created but will not transition out of idle AND when streams are no longer eligible for flow controlled frame transfer but still must persist in the priority tree.
Result:
Memory allocations are reduced to what is actually needed, and memory is made eligible for GC potentially sooner.
2015-04-22 14:40:45 -07:00
nmittler
ec6cd54f85 Ignore frames for streams that may have previously existed.
Motivation:

The recent PR that discarded the Http2StreamRemovalPolicy causes connection errors when receiving a frame for a stream that no longer exists. We should ignore these frames if we think there's a chance that the stream has existed previously

Modifications:

Modified the Http2Connection interface to provide a `streamMayHaveExisted` method. Also removed the requireStream() method to identify all of the places in the code that need to be updated.

Modified the encoder and decoder to properly handle cases where a stream may have existed but no longer does.

Result:

Fixes #3643
2015-04-21 20:46:31 -07:00
nmittler
ed99766c26 Always consume bytes for closed HTTP/2 streams.
Motivation:

The current local flow controller does not guarantee that unconsumed bytes for a closed stream will be restored to the connection window.  This may lead to degradation of the connection window over time.

Modifications:

Modified DefaultHttp2LocalFlowController to guarantee that any unconsumed bytes are returned to the connection window as soon as the stream is closed. We also immediately consume any bytes when receiving DATA for a closed stream.

Result:

Fixes #3668
2015-04-21 12:33:24 -07:00
Scott Mitchell
477571f7e5 HTTP/2 Flow Controller interface updates
Motivation:
Flow control is a required part of the HTTP/2 specification but it is currently structured more like an optional item. It must be accessed through the property map which is time consuming and does not represent its required nature. This access pattern does not give any insight into flow control outside of the codec (or flow controller implementation).

Modifications:
1. Create a read only public interface for LocalFlowState and RemoteFlowState.
2. Add a LocalFlowState localFlowState(); and RemoteFlowState remoteFlowState(); to Http2Stream.

Result:
Flow control is not part of the Http2Stream interface. This clarifies its responsibility and logical relationship to other interfaces. The flow controller no longer must be acquired though a map lookup.
2015-04-20 20:02:39 -07:00
Scott Mitchell
d17fcd7805 HTTP/2 Priority tree circular link
Motivation:
If an exclusive dependency change stream B should be an exclusive dependency of stream A is requested and stream B is already a child of stream A...then we will add B to B's own children map and create a circular link in the priority tree. This leads to an infinite recursive loop and a stack overflow exception.

Modifications:
-when removeAllChildren is called it should not remove the exclusive dependency.
-unit test to ensure this case is covered.

Result:
No more circular link in the priority tree.
2015-04-15 14:26:29 -07:00
Scott Mitchell
b823bfa950 ByteString introduced as AsciiString super class
Motivation:
The usage and code within AsciiString has exceeded the original design scope for this class. Its usage as a binary string is confusing and on the verge of violating interface assumptions in some spots.

Modifications:
- ByteString will be created as a base class to AsciiString. All of the generic byte handling processing will live in ByteString and all the special character encoding will live in AsciiString.

Results:
The AsciiString interface will be clarified. Users of AsciiString can now be clear of the limitations the class imposes while users of the ByteString class don't have to live with those limitations.
2015-04-15 10:45:18 -07:00
nmittler
c6cfb683f5 Removing Http2StreamRemovalPolicy
Motivation:

Due to a recent flurry of cleanup and fixes, we no longer need the stream removal policy to protect against recently removed streams. We should get rid of it.

Modifications:

Removed Http2StreamRemovalPolicy and everywhere it's used.

Result:

Fixes #3448
2015-04-13 12:18:29 -07:00
Scott Mitchell
9c4af6af7e HTTP/2 Connection Listener Unchecked Exceptions
Motivation:
The DefaultHttp2Connection is not checking for RuntimeExceptions when invoking Http2Connection.Listener methods. This is a problem for a few reasons: 1. The state of DefaultHttp2Connection will be corrupted if a listener throws a RuntimeException. 2. If the first listener throws then no other listeners will be notified, which may further corrupt state that is updated as a result of listeners being notified.

Modifications:
- Document that RuntimeExceptions are not supported for Http2Connection.Listener methods, and will be logged as an error.
- Update DefaultHttp2Connection to handle and exception for each listener that is notified, and be sure that 1 listener throwing an exception does not prevent others from being notified.

Result:
More robust DefaultHttp2Connection.
2015-04-13 08:57:08 -07:00
nmittler
044e1eca69 Change Http2Settings to use char keys.
Motivation:

Now that we have a CharObjectHashMap, we should change Http2Settings to use it.

Modifications:

Changed Http2Settings to extend CharObjectHashMap rather than IntObjectHashMap.

Result:

Http2Settings uses less memory to store keys.
2015-04-10 11:49:46 -07:00
nmittler
da01902ea2 Removing direct access to HTTP/2 child streams.
Motivation:

We've removed access to the activeStreams collection, we should do the same for the children of a stream to provide a consistent interface.

Modifications:

Moved Http2StreamVisitor to a top-level interface. Removed unnecessary child operations from the Http2Stream interface so that we no longer require a map structure.

Result:

Cleaner and more consistent interface for iterating over child streams.
2015-04-10 08:51:58 -07:00
Scott Mitchell
28bd5a55c8 HTTP/2 Prevent modification of activeStreams while iterating
Motivation:
The Http2Connection interface exposes an activeStreams() method which allows direct iteration over the underlying collection. There are a few places that make copies of this collection to avoid modification while iterating, and a few places that do not make copies. The copy operation can be expensive on hot code paths and also we are not consistently iterating over the activeStreams collection.

Modifications:
- The Http2Connection interface should reduce the exposure of the underlying collection and just expose what is necessary for the interface to function.  This is just a means to iterate over the collection.
- The DefaultHttp2Connection should use this new interface and protect it's internal state while iteration is occurring.

Result:
Reduction in surface area of the Http2Connection interface.  Consistent iteration of the set of active streams.  Concurrent modification exceptions are handled in 1 encapsulated spot.
2015-04-07 21:00:24 -07:00
Jakob Buchgraber
19c864505d Fix GOAWAY logic in Http2Encoder and Http2Decoder.
Motivation:

1) The current implementation doesn't allow for HEADERS, DATA, PING, PRIORITY and SETTINGS
   frames to be sent after GOAWAY.

2) When receiving or sending a GOAWAY frame, all streams with ids greater than the lastStreamId
   of the GOAWAY frame should be closed. That's not happening.

Modifications:

1) Allow sending of HEADERS and DATA frames after GOAWAY for streams with ids < lastStreamId.
2) Always allow sending PING, PRIORITY AND SETTINGS frames.
3) Allow sending multiple GOAWAY frames with decreasing lastStreamIds.
4) After receiving or sending a GOAWAY frame, close all streams with ids > lastStreamId.

Result:

The GOAWAY handling is more correct.
2015-04-07 20:34:07 -07:00
Scott Mitchell
ac8b05e0fb HTTP/2 DefaultHttp2Connection recursive call fix
Motivation:
There are methods to manipulate the prioritzable count for streams which have the '0' postfix which are designed to be used during recursion.  However these methods are calling out to an external method without the '0' during the recursive process.  This is doing uneccessary conditional checks during recursion.

Modifications:
Change the decrementPrioritizableForTree to decrementPrioritizableForTree0 while in recursive method.
Change the incrementPrioritizableForTree to incrementPrioritizableForTree0 while in recursive method.

Result:
Less overhead during recursive calls.
2015-04-06 17:13:03 -07:00
Scott Mitchell
cee3cc25fc HTTP/2 LifecycleManager and Http2ConnectionHandler interface clarifications
Motiviation:
The interface provided by Http2LifecycleManager is not clear as to how the writeXXX methods should behave.  The implementation of this interface from the Http2ConnectionHandler's perspecitve is unclear what writeXXX means in this context.

Modifications:
- Method names in Http2LifecycleManager and Http2ConnectionHandler should be renamed and comments should clarify the interfaces.

Results:
Http2LifecycleManager is more clear and Http2ConnectionHandler's implementation makes sense w.r.t to return values.
2015-04-06 14:34:46 -07:00
Scott Mitchell
30ed2759b5 HTTP/2 Headers Code Using String instead of AsciiString
Motivation:
The HTTP/2 headers code should be using binary string (currently AsciiString) objects instead of String objects. The DefaultHttp2HeadersEncoder was still using String for sensitiveHeaders.

Modifications:
- Remove the usage of String from DefaultHttp2HeadersEncoder.
- Introduce an interface to determine if a header name/value is sensitive or not to 1. prevent necessarily creating/copying sets. 2. Allow the name/value to be considered when checking if sensitive.

Result:
No more String in DefaultHttp2HeadersEncoder and less required set creation/operations.
2015-04-03 15:56:02 -07:00
Scott Mitchell
7b1bc1f118 HTTP/2 RST_STREAM in IDLE
Motivation:
The spec requires that a RST_STREAM received on an IDLE stream results in a connection error. This is not happening.

Modifications:
Check for this condition when a RST_STREAM is received in DefaultHttp2ConnectionDecoder.

Result:
More spec compliant.  Fixes https://github.com/netty/netty/issues/3573.
2015-04-03 15:53:55 -07:00
Scott Mitchell
d22d5bee57 HTTP/2 HEADERS stream dependency fix
Motivation:
The DefaultHttp2ConnectionDecoder has the setPriority call after the Http2FrameListener is notified of the change. The setPriority call has additional verification logic and may even create the dependency stream and so it must be before the Http2FrameListener is notified.

Modifications:
The DefaultHttp2ConnectionDecoder should treat the setPriority call in the same for the HEADERS and PRIORITY frame (call it before notifying the listener).

Result:
Http2FrameListener should see correct state when a HEADERS frame has a stream dependency that has not yet been created yet.  Fixes https://github.com/netty/netty/issues/3572.
2015-04-03 15:50:50 -07:00