freddo.dtalk2.broker.netty.NettyChannel.java Source code

Java tutorial

Introduction

Here is the source code for freddo.dtalk2.broker.netty.NettyChannel.java

Source

/*
 * Copyright (c) 2013-2015 ArkaSoft LLC.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package freddo.dtalk2.broker.netty;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import freddo.dtalk2.DTalkConnection;

public class NettyChannel implements DTalkConnection {
    private static final Logger LOG = LoggerFactory.getLogger(NettyChannel.class);

    public static final String ATTR_CLIENTID = "ClientID";
    public static final String CLEAN_SESSION = "cleanSession";
    public static final String KEEP_ALIVE = "keepAlive";

    public static final AttributeKey<Object> ATTR_KEY_KEEPALIVE = AttributeKey.valueOf(KEEP_ALIVE);
    public static final AttributeKey<Object> ATTR_KEY_CLEANSESSION = AttributeKey.valueOf(CLEAN_SESSION);
    public static final AttributeKey<Object> ATTR_KEY_CLIENTID = AttributeKey.valueOf(ATTR_CLIENTID);

    private final ChannelHandlerContext mContext;
    private final WebSocketServerHandshaker mHandshaker;

    private String mName;

    NettyChannel(ChannelHandlerContext ctx, WebSocketServerHandshaker handshaker) {
        mContext = ctx;
        mHandshaker = handshaker;
    }

    ChannelHandlerContext getContext() {
        return mContext;
    }

    WebSocketServerHandshaker getHandshaker() {
        return mHandshaker;
    }

    @Override
    public String getName() {
        return mName != null ? mName : (String) getAttribute(ATTR_KEY_CLIENTID);
    }

    @Override
    public void setName(String id) {
        mName = id;
    }

    public Object getAttribute(AttributeKey<Object> key) {
        Attribute<Object> attr = mContext.attr(key);
        return attr.get();
    }

    public void setAttribute(AttributeKey<Object> key, Object value) {
        Attribute<Object> attr = mContext.attr(key);
        attr.set(value);
    }

    public void setIdleTime(int idleTime) {
        if (mContext.pipeline().names().contains("idleStateHandler")) {
            mContext.pipeline().remove("idleStateHandler");
        }
        if (mContext.pipeline().names().contains("idleEventHandler")) {
            mContext.pipeline().remove("idleEventHandler");
        }
        mContext.pipeline().addFirst("idleStateHandler", new IdleStateHandler(idleTime, idleTime / 2, 0));
        mContext.pipeline().addAfter("idleStateHandler", "idleEventHandler", new ChannelDuplexHandler() {
            @Override
            public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                LOG.trace(">>> userEventTriggered: {}", evt);
                if (evt instanceof IdleStateEvent) {
                    IdleStateEvent e = (IdleStateEvent) evt;
                    if (e.state() == IdleState.READER_IDLE) {
                        LOG.debug("read idle");
                        ctx.close();
                    } else if (e.state() == IdleState.WRITER_IDLE) {
                        LOG.debug("write idle");
                        ctx.channel().writeAndFlush(
                                new PingWebSocketFrame(Unpooled.copiedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 })));
                    }
                }
            }
        });
    }

    @Override
    public Future<Void> sendMessage(String message) {
        LOG.trace(">>> sendMessage: {}", message);
        return mContext.channel().writeAndFlush(new TextWebSocketFrame(message));
    }

    @Override
    public void close() {
        mContext.close();
    }

    @Override
    public String toString() {
        String clientID = (String) getAttribute(ATTR_KEY_CLIENTID);
        return "session [clientID: " + clientID + "]" + super.toString();
    }

}