users@grizzly.java.net

Re: Implementing a NIO tunnel with Grizzly

From: Sam Crawford <samcrawford_at_gmail.com>
Date: Tue, 1 Sep 2009 17:27:08 +0100

Thanks v much Alexey. I'll proceed along my current course, but will
push new connections into a DelayedQueue, and then have a single
separate ScheduledExecutor dequeuing items after 5 seconds and
checking the handshake status.

Rest assured I'll be back with more questions on other matters soon!

All the best,

Sam


2009/9/1 Oleksiy Stashok <Oleksiy.Stashok_at_sun.com>:
> 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
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>
>