View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the 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  public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
    39
    40      private static final Logger logger = Logger.getLogger(
    41              SecureChatServerHandler.class.getName());
    42
    43      static final ChannelGroup channels = new DefaultChannelGroup();
    44
    45      @Override
    46      public void handleUpstream(
    47              ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
    48          if (e instanceof ChannelStateEvent) {
    49              logger.info(e.toString());
    50          }
    51          super.handleUpstream(ctx, e);
    52      }
    53
    54      @Override
    55      public void channelConnected(
    56              ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    57
    58          // Get the SslHandler in the current pipeline.
    59          // We added it in SecureChatPipelineFactory.
    60          final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
    61
    62          // Get notified when SSL handshake is done.
    63          ChannelFuture handshakeFuture = sslHandler.handshake();
    64          handshakeFuture.addListener(new Greeter(sslHandler));
    65      }
    66
    67      @Override
    68      public void channelDisconnected(
    69              ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    70          // Unregister the channel from the global channel list
    71          // so the channel does not receive messages anymore.
    72          channels.remove(e.getChannel());
    73      }
    74
    75      @Override
    76      public void messageReceived(
    77              ChannelHandlerContext ctx, MessageEvent e) {
    78
    79          // Convert to a String first.
    80          String request = (String) e.getMessage();
    81
    82          // Send the received message to all channels but the current one.
    83          for (Channel c: channels) {
    84              if (c != e.getChannel()) {
    85                  c.write("[" + e.getChannel().getRemoteAddress() + "] " +
    86                          request + '\n');
    87              } else {
    88                  c.write("[you] " + request + '\n');
    89              }
    90          }
    91
    92          // Close the connection if the client has sent 'bye'.
    93          if (request.toLowerCase().equals("bye")) {
    94              e.getChannel().close();
    95          }
    96      }
    97
    98      @Override
    99      public void exceptionCaught(
    100             ChannelHandlerContext ctx, ExceptionEvent e) {
    101         logger.log(
    102                 Level.WARNING,
    103                 "Unexpected exception from downstream.",
    104                 e.getCause());
    105         e.getChannel().close();
    106     }
    107
    108     private static final class Greeter implements ChannelFutureListener {
    109
    110         private final SslHandler sslHandler;
    111
    112         Greeter(SslHandler sslHandler) {
    113             this.sslHandler = sslHandler;
    114         }
    115
    116         public void operationComplete(ChannelFuture future) throws Exception {
    117             if (future.isSuccess()) {
    118                 // Once session is secured, send a greeting.
    119                 future.getChannel().write(
    120                         "Welcome to " + InetAddress.getLocalHost().getHostName() +
    121                         " secure chat service!\n");
    122                 future.getChannel().write(
    123                         "Your session is protected by " +
    124                         sslHandler.getEngine().getSession().getCipherSuite() +
    125                         " cipher suite.\n");
    126
    127                 // Register the channel to the global channel list
    128                 // so the channel received the messages from others.
    129                 channels.add(future.getChannel());
    130             } else {
    131                 future.getChannel().close();
    132             }
    133         }
    134     }
    135 }