users@grizzly.java.net

Re: Implementing a NIO tunnel with Grizzly

From: Sam Crawford <samcrawford_at_gmail.com>
Date: Tue, 1 Sep 2009 15:37:00 +0100

Hi Alexey,

Thanks, but I recognise already that we don't need to block for
operations. I've had great success with getting the non-blocking
aspect working well!

My question was around creating time limits for logical steps of
execution (not physical timeouts when reading from a blocking
socket!). So my handshaking process completes in a non-blocking
manner, but I want to enforce an absolute time limit of 5 seconds that
the handshake can take.

To be specific:

1. If the client connects but does not transfer any bytes then the
connection should be dropped after 5 seconds
2. If the client connects and starts the handshake, but does not
complete it within 5 seconds, then the connection should be dropped
3. If the client connects, completes the handshake within 5 seconds,
and establishes the tunnel then there should not be an enforced
timeout

Thanks,

Sam


2009/9/1 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
> Hi Sam,
>
>> Apologies for the slow reply. There was no issues with the tunneling
>> when the exception was thrown, so I'm not concerned about it.
>>
>> I'm now actively working on porting our project to use Grizzly (and I
>> will certainly write an article afterwards to cover my experiences!),
>> and have another query...
>>
>> Our tunneling mechanism uses a handshaking mechanism (not unlike a
>> SOCKS proxy with the CONNECT header). We don't want to wait
>> indefinitely for the handshake to complete (e.g. 5 seconds is probably
>> a sensible maximum). That said, once the tunnel is running, we would
>> not want to have any timeouts (i.e. the tunnel should be able to sit
>> idle for hours if need be).
>>
>> In the old Java sockets API I'd set a read timeout on the socket
>> before doing the handshaking, and remove it afterwards.
>>
>> I can't see how to achieve the same (or similar) in Grizzly 2.0. Is
>> there a recommended way of doing this?
>
> By default all the I/O operations on Grizzly 2.0 TCP NIO connections are
> non-blocking.
> You have Grizzly Connection object, which represents your network connection
> [1]. You can get StreamReader, StreamWriter out of this Connection.
>
> Using StreamReader [2] you can check number of bytes available for reading:
> StreamReader.availableDataSize() or retrieve/register some notifier, which
> will notify you, when StreamReader state will be changed: new bytes become
> available, connection was closed etc:
> Future f = StreamReader.notifyAvailable(numberOfBytes, [completionHandler]);
>
> Using StreamWriter [3] you can perform write operations in non-blocking
> mode, using StreamWriter.writeXXX(...). By calling
> Future f = StreamReader.flush([completionHandler]);
> you can register/retrieve notifier, using which you can asynchronously check
> write operation completion state.
>
> So, really, you don't to block for anything :)
>
> Please let me know, if you'll have any questions.
>
> WBR,
> Alexey.
>
>
> [1]
> https://grizzly.dev.java.net/source/browse/grizzly/branches/2dot0/code/modules/grizzly/src/main/java/com/sun/grizzly/Connection.java?rev=3266&view=markup
> [2]
> https://grizzly.dev.java.net/source/browse/grizzly/branches/2dot0/code/modules/grizzly/src/main/java/com/sun/grizzly/streams/StreamReader.java?rev=3292&view=markup
> [3]
> https://grizzly.dev.java.net/source/browse/grizzly/branches/2dot0/code/modules/grizzly/src/main/java/com/sun/grizzly/streams/StreamWriter.java?rev=3496&view=markup
>
>>
>> Thanks again,
>>
>> Sam
>>
>>
>>
>> 2009/8/18 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>>
>>> Hi Sam,
>>>
>>>> I've fired up the example you provided and it seems pretty
>>>> straightforward and works well.
>>>>
>>>> However, when doing some quick tests via it I noted the following
>>>> exception was printed every so often... Is this something to be
>>>> concerned about? I was running this with the latest 2.0 SNAPSHOT.
>>>
>>> Hmm, I think you can say me, if it's something you have concerns about
>>> :))))
>>> For me it looks like issue occurs, when Filter decides to close one
>>> connection, it also closes a peer connection. And closing of peer
>>> connection
>>> may cause this exception.
>>>
>>> Do you see any problem with tunneling functionality, when the exception
>>> occurs?
>>>
>>> I will probably reduce the logging level for the exception.
>>>
>>> Thank you.
>>>
>>> WBR,
>>> Alexey.
>>>
>>>>
>>>> Thanks
>>>>
>>>> Sam
>>>>
>>>> # java -cp "grizzly-framework-2.0.0-SNAPSHOT.jar:."
>>>> com.sun.grizzly.samples.tunnel.TunnelServer
>>>> Aug 16, 2009 9:33:31 PM com.sun.grizzly.samples.tunnel.TunnelServer main
>>>> INFO: Press any key to stop the server...
>>>> Aug 16, 2009 9:33:36 PM com.sun.grizzly.nio.transport.TCPNIOTransport
>>>> fireIOEvent
>>>> WARNING: Unexpected exception occurred
>>>>
>>>>
>>>> fireIOEvent().connection=com.sun.grizzly.nio.transport.TCPNIOConnection_at_785f8172
>>>> event=READ
>>>> java.nio.channels.CancelledKeyException
>>>>      at
>>>> sun.nio.ch.SelectionKeyImpl.ensureValid(SelectionKeyImpl.java:55)
>>>>      at
>>>> sun.nio.ch.SelectionKeyImpl.interestOps(SelectionKeyImpl.java:64)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.DefaultSelectorHandler.unregisterKey0(DefaultSelectorHandler.java:216)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.DefaultSelectorHandler.unregisterKey(DefaultSelectorHandler.java:104)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.AbstractNIOConnection.disableIOEvent(AbstractNIOConnection.java:271)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.transport.TCPNIOTransport.executeDefaultProcessor(TCPNIOTransport.java:730)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.transport.TCPNIOTransport.processReadIoEvent(TCPNIOTransport.java:703)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:648)
>>>>      at com.sun.grizzly.nio.SelectorRunner.fire(SelectorRunner.java:385)
>>>>      at
>>>>
>>>> com.sun.grizzly.nio.SelectorRunner.iterateKeyEvents(SelectorRunner.java:317)
>>>>      at
>>>> com.sun.grizzly.nio.SelectorRunner.iterateKeys(SelectorRunner.java:287)
>>>>      at
>>>> com.sun.grizzly.nio.SelectorRunner.doSelect(SelectorRunner.java:259)
>>>>      at com.sun.grizzly.nio.SelectorRunner.run(SelectorRunner.java:190)
>>>>      at
>>>>
>>>> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>>>>      at
>>>>
>>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>>>>      at java.lang.Thread.run(Thread.java:619)
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> 2009/8/12 Sam Crawford <samcrawford_at_gmail.com>:
>>>>>
>>>>> Brilliant, thank you very much! Hopefully I'll get started on this
>>>>> next month and you'll no doubt see me posting lots of questions here.
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Sam
>>>>>
>>>>>
>>>>> 2009/8/11 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
>>>>>>
>>>>>> Hi Sam,
>>>>>>
>>>>>>> I'm currently looking to rewrite our (blocking) tunneling software
>>>>>>> using NIO (in an effort to increase scalability), and Grizzly seems
>>>>>>> like it could save me a considerable amount of time. To be clear,
>>>>>>> this
>>>>>>> is for tunneling arbitrary TCP traffic (not just HTTP!), over both
>>>>>>> SSL
>>>>>>> and non-SSL.
>>>>>>>
>>>>>>> Having searched the archives, I see that someone else two years was
>>>>>>> interested in something similar
>>>>>>>
>>>>>>>
>>>>>>> (https://grizzly.dev.java.net/servlets/ReadMsg?listName=users&msgNo=52).
>>>>>>> Are the concepts largely the same nowadays? I know the Grizzly
>>>>>>> libraries have progressed a great deal since then, so I didn't want
>>>>>>> to
>>>>>>> dive too deeply into that if there were more appropriate ways of
>>>>>>> achieving this these days.
>>>>>>>
>>>>>>> Any other pointers would be most welcome!
>>>>>>
>>>>>> IMHO it should be pretty easy to write simple tunneling application.
>>>>>> All you'll need on server side - is to build filter chain and keep
>>>>>> client<->server connection map to redirect data among them.
>>>>>>
>>>>>> I've just created simple tunnel example for Grizzly 2.0, hope it will
>>>>>> help.
>>>>>> To build them - please use the latest Grizzly 2.0 snapshot [2]
>>>>>>
>>>>>> WBR,
>>>>>> Alexey.
>>>>>>
>>>>>> [1]
>>>>>>
>>>>>>
>>>>>> https://grizzly.dev.java.net/source/browse/grizzly/branches/2dot0/code/samples/framework-samples/src/main/java/com/sun/grizzly/samples/tunnel/
>>>>>> [2]
>>>>>>  <groupId>com.sun.grizzly</groupId>
>>>>>>  <artifactId>grizzly-framework</artifactId>
>>>>>>  <version>2.0.0-SNAPSHOT</version>
>>>>>>
>>>>>>>
>>>>>>> Many thanks,
>>>>>>>
>>>>>>> Sam
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>>
>>>>>>
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>
>