New full duplex HTTP tunnel without need for servlet container

Iain McGinniss iainmcgin at gmail.com
Tue Sep 29 06:57:58 EDT 2009


Hello all,

Firstly, a quick introduction: my name is Iain McGinniss, and I am  
presently employed by OneDrum (www.onedrum.com) to contribute to open  
source projects which they use at the core of their product. This  
started as performance and stability fixes for the JXTA peer to peer  
library. JXTA presently uses a hand-crafted NIO TCP stack as it's  
primary means of communication, with a Jetty based HTTP fallback.  
Neither are particularly stable, so once I dealt with some other  
serious issues in their architecture I turned my attention to  
replacing these transports. This brought me to the Netty project,  
after a brief foray with Grizzly. The TCP stack in JXTA has been  
reimplemented to use Netty already, and I have written a new HTTP  
tunnel to replace the HTTP stack.

This brings me to the purpose of this email. I had previously  
contacted Trustin regarding this HTTP tunnel, which I am in the  
process of polishing off just now. The guiding principles of it's  
design were:

1. Utilise HTTP in a way that will allow it to work through most  
firewalls and proxy servers. This rules out HTTP pipelining as a way  
of getting full duplex behaviour on a single connection. Instead, two  
connections must be used, one to send data from client to server and  
the other to long-poll data back from server to client. This is  
essentially the Comet technique.
2. Use only Netty to implement the server and client. Specifically,  
the tunnel should not require a servlet container or any other  
infrastructure, just Netty's TCP stack and HTTP codec.
3. Make the tunnel appear like a normal channel to both client and  
server. Emulate the behaviour of a normal TCP connection for the  
tunnel as far as possible, abstracting away the details of how the  
data is actually transmitted.

The above resulted in the creation of:

HttpTunnelClientChannelFactory - takes a ClientSocketChannelFactory  
for the creation of the real TCP connections used to service the tunnel.
HttpTunnelClientChannel - a virtual channel, wrapping the send and  
poll TCP channels.
HttpTunnelServerChannelFactory - takes a ServerSocketChannelFactory to  
create the underlying TCP server socket used to accept tunnel  
connections.
HttpTunnelServerChannel - a virtual server channel
HttpTunnelAcceptedChannel - a virtual accepted channel, representing  
the server end of a tunnel.
... and various other supporting types (Sinks, ChannelHandlers,  
reasonably comprehensive unit tests of each).

No assumptions are made about how long any particular incoming  
connection will last on the server end, so a small component (the  
ServerMessageSwitch) sits in-between the physical channels and the  
virtual ones, routing messages in and out. This provides resilience to  
proxies that reuse HTTP connections or close them periodically in  
response to inactivity.

Design principle 3 above is the one which causes me the most  
difficulty - as I am still relatively new to Netty, I am not sure what  
semantics of channels are regarded as essential and which can be  
treated as optional. For instance, my client channels are not yet  
configurable - they have a SocketChannelConfig based configuration  
object, but it is not used and it's properties are not honoured in any  
way. I also don't do anything with interest ops, and my handling of  
events (exceptions, timeouts, state transitions) is likely to be  
sloppy in places. There are also likely some channel semantics which I  
am completely unaware of.

So, to summarise: I have this new tunnel, which once polished I  
believe will be a good compliment or replacement to the existing HTTP  
tunnel in Netty. It could do with some detailed code review and  
contributions to make it production ready and as high quality as the  
other components in Netty. Also, I am unaware how the contribution  
process works in this community - how should I submit patches, what  
quality gates are there before a contribution is fully accepted and  
committed to trunk? Some pointers around these aspects would be  
greatly appreciated.

Iain


More information about the netty-dev mailing list