users@grizzly.java.net

Re: [Q] How-to client Protocol

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Fri, 29 Feb 2008 16:01:13 -0500

Hi Simon (sound french :-))

Simon Trudeau wrote:
> I’m looking for help building a TCP client with a specific protocol :
>
>
>
> If server is password protected:
>
>
>
> 1. Client connects to server
> 2. Server sends password prompt to client
> 3. Client sends server’s password
> 4. Server sends acknowledgement
> 5. Client sends request
> 6. Server sends reply
> 7. Repeat step 5 and 6
>
>
>
> If server is not password protected:
>
>
>
> 1. Client connects to server
> 2. Client sends request
> 3. Server sends reply
> 4. Repeat step 2 and 3
>
>
>
> How should I go about implementing this protocol? In once case, the
> client, upon establishing a connection, can send a request right away in
> the other case, it must wait for the server to negotiate the password.
>
>
>
> What’s the right way to handle protocol specific data exchange on the
> client side?

With Grizzly, you don't have to implement such mechanism, as it already
support it by default. I will first explain without too much details, so
feel free to ask questions if I'm unclear. But first, are you planning
to use a single port for both TLS (secure) and TCP (unsecure) or will
you have two ports? We have a mechanism that support a single port:

http://weblogs.java.net/blog/jfarcand/archive/2006/11/one_port_to_rul.html

Might want to use that (but for now, let's focus on not using it). For
the server side, you need to add to SelectorHandler:

Controller controller = new Controller();
controller.addSelectorHandler(new SSLSelectorHandler());
controller.addSelectorHandler(new TCPSelectorHandler());

This is just a code snippet. Next the client.


>
>
>
> My first guess would be to create a custom CallbackHandler to trigger
> the password negociation upon connecting to the server like so…

Right,



>
>
>
> connector_handler.connect(new InetSocketAddress(host,port),
>
> new CallbackHandler<Context>()
>
> {
>
> public void onConnect(IOEvent<Context> e)
>
> {
>
> SelectionKey k = e.attachment().getSelectionKey();
>
> System.out.println("Callbackhandler: OnConnect...");
>
> try
>
> {
>
> connector_handler.finishConnect(k);
>
>
>
> //*Negociate password password exchange here*
>
> } catch(Exception ex)
>
> {
>
> System.out.println("exception in CallbackHandler:"+ex.getMessage());
>
> }
>
> e.attachment().getSelectorHandler().register(k,SelectionKey.OP_READ);
>
> }
>
>
>
> public void onRead(IOEvent<Context> e){}
>
> public void onWrite(IOEvent<Context> e){}
>
> });
>
>
>
> It might work… but it definitely doesn’t look very nice. Is there some sort of state machine facility to deal with this kind of situation? I guess there must be since Grizzly is implemented with protocols such as SIP.

But how/where is your password (what kind of form does it take). Usually
  you add a certificate on the client and server side, and Grizzly will
do the negociation for you. Is that what you have in mind?



>
>
>
> There is also something called a ProtocolFilter, I guess it could be better suited than using the CallbackHandler…eventhough I need to define a behaviour OnConnection…

ProtocolFilter are used on the server side usually (but can be used on
the client side as well...SIP does use it). For your SSL stuff, you will
use the SSLReadFilter, and for TCP/UDP, the ReadFilter. What you usually
do is:

91 Controller sel = new Controller();
92 sel.setProtocolChainInstanceHandler(new
DefaultProtocolChainInstanceHandler(){
93 public ProtocolChain poll() {
94 ProtocolChain protocolChain = protocolChains.poll();
95 if (protocolChain == null){
96 protocolChain = new DefaultProtocolChain();
97 protocolChain.addFilter(new ReadFilter());
98 protocolChain.addFilter(*** What you need to do
with the bytes ****);
99 }
100 return protocolChain;
101 }
102 });

This is the server side :-)

>
>
>
> Using a ProtocolFilter, how would I go about making it stateful and maintaining state information between invocation of the ProtocolFilter? I guess it has something to do with the Context object… But how do you store user defined states in this object? Do I have to overload it?

Context.setAttribute() or SelectorHandler.setAttribute or
Controller.setAttribute. You can also makes your ProtocolFilter statefull:

> ProtocolChainInstanceHandler pciHandler =
> new ProtocolChainInstanceHandler() {
>
> final private ProtocolChain protocolChain = new DefaultProtocolChain();
>
> public ProtocolChain poll() {
> return protocolChain;
> }
>
> public boolean offer(ProtocolChain instance) {
> return true;
> }
> };
> controller.setProtocolChainInstanceHandler(pciHandler);

So you can store you state inside any ProtocolFilter. But


>
>
>
>
>
> Well, I guess I have a lot of interrogations! :.)

Keep them coming :-) Our documentation really really sucks :-)


Are there any test cases in the Grizzly code base that could help me?



Are there any tutorials, code samples, on the topic?

There is a couple on grizzly.dev.java.net. A good starter is:

http://weblogs.java.net/blog/jfarcand/archive/2008/02/writing_a_tcpud_1.html

and the SIP example is here:

http://weblogs.java.net/blog/jfarcand/archive/2007/11/supporting_the.html

Erick also proposed a tutorial:

http://www.nabble.com/Grizzly-on-the-client-side%2C-a-modest-tutorial-td15643977.html

But the best source of information is the mailing list. We are all happy
to help so bombard us with questions :-)

Thanks!

-- Jeanfrancois



>
>
>
>
>
> Thanks for your help,
>
>
>
>
>
> Simon
>
>
>