/*
 * Copyright 2014 Open Networking Laboratory
 *
 * 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.onlab.onos.sdnip.bgp;

import java.util.concurrent.CountDownLatch;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.onlab.packet.Ip4Address;

/**
 * Class for handling the decoding of the BGP messages at the remote
 * BGP peer session.
 */
class TestBgpPeerFrameDecoder extends FrameDecoder {
    int remoteBgpVersion;               // 1 octet
    long remoteAs;                      // 2 octets
    long remoteHoldtime;                // 2 octets
    Ip4Address remoteBgpIdentifier;     // 4 octets -> IPv4 address

    final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
    final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);

    @Override
    protected Object decode(ChannelHandlerContext ctx,
                            Channel channel,
                            ChannelBuffer buf) throws Exception {
        // Test for minimum length of the BGP message
        if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
            // No enough data received
            return null;
        }

        //
        // Mark the current buffer position in case we haven't received
        // the whole message.
        //
        buf.markReaderIndex();

        //
        // Read and check the BGP message Marker field: it must be all ones
        //
        byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
        buf.readBytes(marker);
        for (int i = 0; i < marker.length; i++) {
            if (marker[i] != (byte) 0xff) {
                // ERROR: Connection Not Synchronized. Close the channel.
                ctx.getChannel().close();
                return null;
            }
        }

        //
        // Read and check the BGP message Length field
        //
        int length = buf.readUnsignedShort();
        if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
            (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
            // ERROR: Bad Message Length. Close the channel.
            ctx.getChannel().close();
            return null;
        }

        //
        // Test whether the rest of the message is received:
        // So far we have read the Marker (16 octets) and the
        // Length (2 octets) fields.
        //
        int remainingMessageLen =
            length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
        if (buf.readableBytes() < remainingMessageLen) {
            // No enough data received
            buf.resetReaderIndex();
            return null;
        }

        //
        // Read the BGP message Type field, and process based on that type
        //
        int type = buf.readUnsignedByte();
        remainingMessageLen--;      // Adjust after reading the type
        ChannelBuffer message = buf.readBytes(remainingMessageLen);

        //
        // Process the remaining of the message based on the message type
        //
        switch (type) {
        case BgpConstants.BGP_TYPE_OPEN:
            processBgpOpen(ctx, message);
            break;
        case BgpConstants.BGP_TYPE_UPDATE:
            // NOTE: Not used as part of the test, because ONOS does not
            // originate UPDATE messages.
            break;
        case BgpConstants.BGP_TYPE_NOTIFICATION:
            // NOTE: Not used as part of the testing (yet)
            break;
        case BgpConstants.BGP_TYPE_KEEPALIVE:
            processBgpKeepalive(ctx, message);
            break;
        default:
            // ERROR: Bad Message Type. Close the channel.
            ctx.getChannel().close();
            return null;
        }

        return null;
    }

    /**
     * Processes BGP OPEN message.
     *
     * @param ctx the Channel Handler Context.
     * @param message the message to process.
     */
    private void processBgpOpen(ChannelHandlerContext ctx,
                                ChannelBuffer message) {
        int minLength =
            BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
        if (message.readableBytes() < minLength) {
            // ERROR: Bad Message Length. Close the channel.
            ctx.getChannel().close();
            return;
        }

        //
        // Parse the OPEN message
        //
        remoteBgpVersion = message.readUnsignedByte();
        remoteAs = message.readUnsignedShort();
        remoteHoldtime = message.readUnsignedShort();
        remoteBgpIdentifier =
            Ip4Address.valueOf((int) message.readUnsignedInt());
        // Optional Parameters
        int optParamLen = message.readUnsignedByte();
        if (message.readableBytes() < optParamLen) {
            // ERROR: Bad Message Length. Close the channel.
            ctx.getChannel().close();
            return;
        }
        message.readBytes(optParamLen);             // NOTE: data ignored

        // BGP OPEN message successfully received
        receivedOpenMessageLatch.countDown();
    }

    /**
     * Processes BGP KEEPALIVE message.
     *
     * @param ctx the Channel Handler Context.
     * @param message the message to process.
     */
    private void processBgpKeepalive(ChannelHandlerContext ctx,
                                     ChannelBuffer message) {
        if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH !=
            BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) {
            // ERROR: Bad Message Length. Close the channel.
            ctx.getChannel().close();
            return;
        }
        // BGP KEEPALIVE message successfully received
        receivedKeepaliveMessageLatch.countDown();
    }
}
