View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.example.securechat;
17  
18  import java.net.InetAddress;
19  import java.util.logging.Level;
20  import java.util.logging.Logger;
21  
22  import org.jboss.netty.channel.Channel;
23  import org.jboss.netty.channel.ChannelEvent;
24  import org.jboss.netty.channel.ChannelFuture;
25  import org.jboss.netty.channel.ChannelFutureListener;
26  import org.jboss.netty.channel.ChannelHandlerContext;
27  import org.jboss.netty.channel.ChannelStateEvent;
28  import org.jboss.netty.channel.ExceptionEvent;
29  import org.jboss.netty.channel.MessageEvent;
30  import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
31  import org.jboss.netty.channel.group.ChannelGroup;
32  import org.jboss.netty.channel.group.DefaultChannelGroup;
33  import org.jboss.netty.handler.ssl.SslHandler;
34  
35  /**
36   * Handles a server-side channel.
37   *
38   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
39   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
40   *
41   * @version $Rev: 2121 $, $Date: 2010-02-02 09:38:07 +0900 (Tue, 02 Feb 2010) $
42   */
43  public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
44  
45      private static final Logger logger = Logger.getLogger(
46              SecureChatServerHandler.class.getName());
47  
48      static final ChannelGroup channels = new DefaultChannelGroup();
49  
50      @Override
51      public void handleUpstream(
52              ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
53          if (e instanceof ChannelStateEvent) {
54              logger.info(e.toString());
55          }
56          super.handleUpstream(ctx, e);
57      }
58  
59      @Override
60      public void channelConnected(
61              ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
62  
63          // Get the SslHandler in the current pipeline.
64          // We added it in SecureChatPipelineFactory.
65          final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
66  
67          // Get notified when SSL handshake is done.
68          ChannelFuture handshakeFuture = sslHandler.handshake();
69          handshakeFuture.addListener(new Greeter(sslHandler));
70      }
71  
72      @Override
73      public void channelDisconnected(
74              ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
75          // Unregister the channel from the global channel list
76          // so the channel does not receive messages anymore.
77          channels.remove(e.getChannel());
78      }
79  
80      @Override
81      public void messageReceived(
82              ChannelHandlerContext ctx, MessageEvent e) {
83  
84          // Convert to a String first.
85          String request = (String) e.getMessage();
86  
87          // Send the received message to all channels but the current one.
88          for (Channel c: channels) {
89              if (c != e.getChannel()) {
90                  c.write("[" + e.getChannel().getRemoteAddress() + "] " +
91                          request + '\n');
92              } else {
93                  c.write("[you] " + request + '\n');
94              }
95          }
96  
97          // Close the connection if the client has sent 'bye'.
98          if (request.toLowerCase().equals("bye")) {
99              e.getChannel().close();
100         }
101     }
102 
103     @Override
104     public void exceptionCaught(
105             ChannelHandlerContext ctx, ExceptionEvent e) {
106         logger.log(
107                 Level.WARNING,
108                 "Unexpected exception from downstream.",
109                 e.getCause());
110         e.getChannel().close();
111     }
112 
113     /**
114      * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
115      * @author <a href="http://gleamynode.net/">Trustin Lee</a>
116      * @version $Rev: 2121 $, $Date: 2010-02-02 09:38:07 +0900 (Tue, 02 Feb 2010) $
117      */
118     private static final class Greeter implements ChannelFutureListener {
119 
120         private final SslHandler sslHandler;
121 
122         Greeter(SslHandler sslHandler) {
123             this.sslHandler = sslHandler;
124         }
125 
126         public void operationComplete(ChannelFuture future) throws Exception {
127             if (future.isSuccess()) {
128                 // Once session is secured, send a greeting.
129                 future.getChannel().write(
130                         "Welcome to " + InetAddress.getLocalHost().getHostName() +
131                         " secure chat service!\n");
132                 future.getChannel().write(
133                         "Your session is protected by " +
134                         sslHandler.getEngine().getSession().getCipherSuite() +
135                         " cipher suite.\n");
136 
137                 // Register the channel to the global channel list
138                 // so the channel received the messages from others.
139                 channels.add(future.getChannel());
140             } else {
141                 future.getChannel().close();
142             }
143         }
144     }
145 }