users@grizzly.java.net

Re: Implementing a NIO tunnel with Grizzly

From: Oleksiy Stashok <Oleksiy.Stashok_at_Sun.COM>
Date: Tue, 01 Sep 2009 18:20:33 +0200

Hi Sam,

I think you're doing that right way!
Because handshake you're running is a quite complex process (with
several reads/writes as I understand), which is specific to your
protocol, so not sure Grizzly can have some general solution for this.
We have IdleTimeoutFilter implementation, which closes Connection
after detecting that it is idle for some period of time, but it's not
applicable for you, because you want to detect handshake timeouts.

So, IMHO, what you are proposing is right way to implement the logic
you need.

Thanks.

WBR,
Alexey.

> Adding the following to handleAccept in the filter does what I want,
> but it doesn't seem very modern! I'm going to explore using the
> ScheduledExecutorService, but would still be interested to know if
> there's a proper grizzly way of doing this.
>
> Thanks,
>
> Sam
>
>
> Thread r = new Thread() {
> public void run() {
> try {
> Thread.sleep(5000);
> // ctx.getConnection() is still null in handleAccept...
> Connection conn = ctx.getProcessorRunnable().getConnection();
> TunnelHandshake handshake = handshakeAttribute.get(conn);
> if (handshake == null || !handshake.isComplete()) {
> System.out.println("Closing connection");
> conn.close();
> }
> } catch (Exception e) {
> e.printStackTrace();
> }
> }
> };
> r.start();
>
>
>
>
> 2009/9/1 Sam Crawford <samcrawford_at_gmail.com>:
>> 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
>>>
>>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>