org.evilco.network.rcon.common.codec.FrameCodec.java Source code

Java tutorial

Introduction

Here is the source code for org.evilco.network.rcon.common.codec.FrameCodec.java

Source

/*
 * Copyright 2014 Johannes Donath <johannesd@evil-co.com>
 * 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 org.evilco.network.rcon.common.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import lombok.AccessLevel;
import lombok.Getter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.nio.ByteOrder;
import java.util.List;

/**
 * @author Johannes Donath <johannesd@evil-co.com>
 * @copyright Copyright (C) 2014 Evil-Co <http://www.evil-co.com>
 */
@ChannelHandler.Sharable
public class FrameCodec extends ByteToMessageCodec<ByteBuf> {

    /**
     * Stores an internal logger instance.
     */
    @Getter(AccessLevel.PROTECTED)
    private static final Logger logger = LogManager.getLogger(FrameCodec.class);

    /**
     * Stores the internal singleton instance.
     */
    private static FrameCodec INSTANCE = null;

    /**
     * Internal Constructor
     */
    protected FrameCodec() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2)
            throws Exception {
        // set order
        byteBuf2 = byteBuf2.order(ByteOrder.LITTLE_ENDIAN);

        // log
        getLogger().debug("Encoding frame for " + byteBuf.readableBytes() + " bytes of data.");

        // ensure output buffer is writable
        byteBuf2.ensureWritable((4 + byteBuf.readableBytes()));

        // write packet length
        byteBuf2.writeInt(byteBuf.readableBytes());

        // write packet
        byteBuf2.writeBytes(byteBuf);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> objects)
            throws Exception {
        // set order
        byteBuf = byteBuf.order(ByteOrder.LITTLE_ENDIAN);

        // read all available packets
        while (byteBuf.readableBytes() >= 4) {
            // log
            getLogger().trace("Decoding frame with maximal size of " + byteBuf.readableBytes() + " bytes.");

            // mark reader index
            byteBuf.markReaderIndex();

            // read length
            int length = byteBuf.readInt();

            // log
            getLogger().trace("Detected frame length of " + length + " bytes.");

            // check whether enough data is available
            if (length > byteBuf.readableBytes()) {
                // log
                getLogger().debug("There are only " + byteBuf.readableBytes() + " out of " + length
                        + " bytes available. Skipping frame until more data is available.");

                // reset buffer
                byteBuf.resetReaderIndex();

                // exit loop
                break;
            }

            // log
            getLogger().trace("Frame seems to be complete reading data.");

            // construct buffer
            ByteBuf packetBuffer = channelHandlerContext.alloc().buffer(length);

            // read data
            byteBuf.readBytes(packetBuffer, length);

            // add to list
            objects.add(packetBuffer);

            // log
            getLogger().trace("Frame decoded. " + byteBuf.readableBytes() + " bytes left in buffer.");
        }
    }

    /**
     * Returns an instance of FrameCodec.
     * @return The instance.
     */
    public static FrameCodec getInstance() {
        if (INSTANCE == null)
            INSTANCE = new FrameCodec();
        return INSTANCE;
    }
}