Implementation of PcInitate and PcUpdate messages

Change-Id: I746a5860a8b4a8022d747a02075ed3237741c53a
diff --git a/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepCloseMsgVer1.java b/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepCloseMsgVer1.java
new file mode 100644
index 0000000..54ed78f
--- /dev/null
+++ b/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepCloseMsgVer1.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2015 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.onosproject.pcepio.protocol.ver1;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepCloseMsg;
+import org.onosproject.pcepio.protocol.PcepMessageReader;
+import org.onosproject.pcepio.protocol.PcepMessageWriter;
+import org.onosproject.pcepio.protocol.PcepType;
+import org.onosproject.pcepio.protocol.PcepVersion;
+import org.onosproject.pcepio.types.PcepObjectHeader;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/*
+ * RFC : 5440 , section : 6.8
+ * <Close Message>           ::= <Common Header> <CLOSE>
+ *
+     0                   1                   2                   3
+     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    | Ver |  Flags  |  Message-Type |       Message-Length          |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |          Reserved             |      Flags    |    Reason     |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                                                               |
+    //                         Optional TLVs                       //
+    |                                                               |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+class PcepCloseMsgVer1 implements PcepCloseMsg {
+
+    protected static final Logger log = LoggerFactory.getLogger(PcepCloseMsgVer1.class);
+
+    // Pcep version: 1
+    public static final byte PACKET_VERSION = 1;
+    public static final int PACKET_MINIMUM_LENGTH = 12;
+    public static final PcepType MSG_TYPE = PcepType.CLOSE;
+    public static final byte CLOSE_OBJ_TYPE = 1;
+    public static final byte CLOSE_OBJ_CLASS = 15;
+    public static final byte CLOSE_OBJECT_VERSION = 1;
+    public static final byte DEFAULT_REASON = 1; // Default reason to close
+    public static final short CLOSE_OBJ_MINIMUM_LENGTH = 8;
+    public static final int SHIFT_FLAG = 5;
+    static final PcepObjectHeader DEFAULT_CLOSE_HEADER = new PcepObjectHeader(CLOSE_OBJ_CLASS, CLOSE_OBJ_TYPE,
+            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, CLOSE_OBJ_MINIMUM_LENGTH);
+
+    private final PcepObjectHeader closeObjHeader;
+    private byte yReason;
+    private LinkedList<PcepValueType> llOptionalTlv;
+
+    public static final PcepCloseMsgVer1.Reader READER = new Reader();
+
+    static class Reader implements PcepMessageReader<PcepCloseMsg> {
+        PcepObjectHeader closeObjHeader;
+        byte yReason;
+        // Optional TLV
+        private LinkedList<PcepValueType> llOptionalTlv;
+
+        @Override
+        public PcepCloseMsg readFrom(ChannelBuffer cb) throws PcepParseException {
+
+            if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
+                throw new PcepParseException("Packet size is less than the minimum length.");
+            }
+            // fixed value property version == 1
+            byte version = cb.readByte();
+            version = (byte) (version >> SHIFT_FLAG);
+            if (version != PACKET_VERSION) {
+                throw new PcepParseException("Wrong version. Expected=PcepVersion.PCEP_1(1), got=" + version);
+            }
+            // fixed value property type == 7
+            byte type = cb.readByte();
+            if (type != MSG_TYPE.getType()) {
+                throw new PcepParseException("Wrong type. Expected=PcepType.CLOSE(7), got=" + type);
+            }
+            short length = cb.readShort();
+            if (length < PACKET_MINIMUM_LENGTH) {
+                throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
+                        + length);
+            }
+            closeObjHeader = PcepObjectHeader.read(cb);
+            // Reserved
+            cb.readShort();
+            // Flags
+            cb.readByte();
+            // Reason
+            yReason = cb.readByte();
+            // parse optional TLV
+            llOptionalTlv = parseOptionalTlv(cb);
+            return new PcepCloseMsgVer1(closeObjHeader, yReason, llOptionalTlv);
+        }
+    }
+
+    /**
+     * Parse the list of Optional Tlvs.
+     *
+     * @param cb channel buffer
+     * @return list of Optional Tlvs
+     * @throws PcepParseException when fails to parse optional tlvs
+     */
+    public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
+
+        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+        /*
+         rfc 5440:
+         Optional TLVs may be included within the CLOSE object body. The
+         specification of such TLVs is outside the scope of this document.
+         */
+        return llOptionalTlv;
+    }
+
+    /**
+     * constructor to initialize PCEP close Message with all the parameters.
+     *
+     * @param closeObjHeader object header for close message
+     * @param yReason reason for closing the channel
+     * @param llOptionalTlv list of optional tlvs
+     */
+    PcepCloseMsgVer1(PcepObjectHeader closeObjHeader, byte yReason, LinkedList<PcepValueType> llOptionalTlv) {
+
+        this.closeObjHeader = closeObjHeader;
+        this.yReason = yReason;
+        this.llOptionalTlv = llOptionalTlv;
+    }
+
+    /**
+     * Builder class for PCEP close message.
+     */
+    static class Builder implements PcepCloseMsg.Builder {
+
+        // PCEP Close message fields
+        private boolean bIsHeaderSet = false;
+        private PcepObjectHeader closeObjHeader;
+        private boolean bIsReasonSet = false;
+        private byte yReason;
+        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+
+        private boolean bIsPFlagSet = false;
+        private boolean bPFlag;
+
+        private boolean bIsIFlagSet = false;
+        private boolean bIFlag;
+
+        @Override
+        public PcepVersion getVersion() {
+            return PcepVersion.PCEP_1;
+        }
+
+        @Override
+        public PcepType getType() {
+            return PcepType.CLOSE;
+        }
+
+        @Override
+        public PcepCloseMsg build() {
+
+            PcepObjectHeader closeObjHeader = this.bIsHeaderSet ? this.closeObjHeader : DEFAULT_CLOSE_HEADER;
+            byte yReason = this.bIsReasonSet ? this.yReason : DEFAULT_REASON;
+
+            if (bIsPFlagSet) {
+                closeObjHeader.setPFlag(bPFlag);
+            }
+
+            if (bIsIFlagSet) {
+                closeObjHeader.setIFlag(bIFlag);
+            }
+            return new PcepCloseMsgVer1(closeObjHeader, yReason, this.llOptionalTlv);
+        }
+
+        @Override
+        public PcepObjectHeader getCloseObjHeader() {
+            return this.closeObjHeader;
+        }
+
+        @Override
+        public Builder setCloseObjHeader(PcepObjectHeader obj) {
+            this.closeObjHeader = obj;
+            this.bIsHeaderSet = true;
+            return this;
+        }
+
+        @Override
+        public byte getReason() {
+            return this.yReason;
+        }
+
+        @Override
+        public Builder setReason(byte value) {
+            this.yReason = value;
+            this.bIsReasonSet = true;
+            return this;
+        }
+
+        @Override
+        public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
+            this.llOptionalTlv = llOptionalTlv;
+            return this;
+        }
+
+        @Override
+        public LinkedList<PcepValueType> getOptionalTlv() {
+            return this.llOptionalTlv;
+        }
+
+        @Override
+        public Builder setPFlag(boolean value) {
+            this.bPFlag = value;
+            this.bIsPFlagSet = true;
+            return this;
+        }
+
+        @Override
+        public Builder setIFlag(boolean value) {
+            this.bIFlag = value;
+            this.bIsIFlagSet = true;
+            return this;
+        }
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer cb) throws PcepParseException {
+        WRITER.write(cb, this);
+    }
+
+    static final Writer WRITER = new Writer();
+
+    static class Writer implements PcepMessageWriter<PcepCloseMsgVer1> {
+
+        @Override
+        public void write(ChannelBuffer cb, PcepCloseMsgVer1 message) throws PcepParseException {
+            int startIndex = cb.writerIndex();
+            // first 3 bits set to version
+            cb.writeByte((byte) (PACKET_VERSION << SHIFT_FLAG));
+            // message type
+            cb.writeByte(MSG_TYPE.getType());
+            // length is length of variable message, will be updated at the end
+            // Store the position of message
+            // length in buffer
+            int msgLenIndex = cb.writerIndex();
+            cb.writeShort((short) 0);
+            int objStartIndex = cb.writerIndex();
+            int objLenIndex = message.closeObjHeader.write(cb);
+            if (objLenIndex <= 0) {
+                throw new PcepParseException("Failed to write Close object header.");
+            }
+            // first 3 bits set to version
+            cb.writeShort(0); // Reserved
+            cb.writeByte(0); // Flags
+            cb.writeByte(message.yReason);
+            // Pack optional TLV
+            packOptionalTlv(cb, message);
+            int length = cb.writerIndex() - objStartIndex;
+            cb.setShort(objLenIndex, (short) length);
+            // will be helpful during print().
+            message.closeObjHeader.setObjLen((short) length);
+            // As per RFC the length of object should be
+            // multiples of 4
+            int pad = length % 4;
+            if (pad != 0) {
+                pad = 4 - pad;
+                for (int i = 0; i < pad; i++) {
+                    cb.writeByte((byte) 0);
+                }
+                length = length + pad;
+            }
+            // update message length field
+            length = cb.writerIndex() - startIndex;
+            cb.setShort(msgLenIndex, (short) length);
+        }
+
+        public void packOptionalTlv(ChannelBuffer cb, PcepCloseMsgVer1 message) {
+
+            LinkedList<PcepValueType> llOptionalTlv = message.llOptionalTlv;
+            ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
+            while (listIterator.hasNext()) {
+                listIterator.next().write(cb);
+            }
+        }
+    }
+
+    @Override
+    public PcepVersion getVersion() {
+        return PcepVersion.PCEP_1;
+    }
+
+    @Override
+    public PcepType getType() {
+        return MSG_TYPE;
+    }
+
+    @Override
+    public byte getReason() {
+        return this.yReason;
+    }
+
+    @Override
+    public void setReason(byte value) {
+        this.yReason = value;
+    }
+
+    @Override
+    public LinkedList<PcepValueType> getOptionalTlv() {
+        return this.llOptionalTlv;
+    }
+
+    @Override
+    public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
+        this.llOptionalTlv = llOptionalTlv;
+    }
+
+    @Override
+    public void print() {
+        log.debug("CLOSE MESSAGE");
+        closeObjHeader.print();
+        int x = yReason & 0xFF;
+        log.debug("Reason: " + x);
+        log.debug("OPTINAL TLV:");
+        ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
+        while (listIterator.hasNext()) {
+            listIterator.next().print();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("close Object Header", closeObjHeader)
+                .add("Reason", yReason)
+                .add("Optional Tlv list", llOptionalTlv)
+                .toString();
+    }
+}