users@grizzly.java.net

Re: Implementing a NIO tunnel with Grizzly

From: Oleksiy Stashok <Oleksiy.Stashok_at_Sun.COM>
Date: Tue, 01 Sep 2009 15:09:51 +0200

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
>