BMP Initiation message decoder

bmp collector receives initiation message from bmp agent

Change-Id: I41bbeb66108adf3137c56bc864f32491d5aab150
diff --git a/apps/bgpmonitoring/app/src/main/java/org/onosproject/bgpmonitoring/type/BmpInitiationMessage.java b/apps/bgpmonitoring/app/src/main/java/org/onosproject/bgpmonitoring/type/BmpInitiationMessage.java
new file mode 100644
index 0000000..9c67a2b
--- /dev/null
+++ b/apps/bgpmonitoring/app/src/main/java/org/onosproject/bgpmonitoring/type/BmpInitiationMessage.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * 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.bgpmonitoring.type;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.bgpmonitoring.InitiationMessage;
+import org.onosproject.bgpmonitoring.BmpParseException;
+import org.onosproject.bgpmonitoring.BmpMsg;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.BiPredicate;
+import java.nio.ByteBuffer;
+
+import org.onlab.packet.Deserializer;
+
+/**
+ * A means for the monitored router to inform the
+ * monitoring station of its vendor, software version, and so on.
+ * <p>
+ * The initiation message provides a means for the monitored router to.
+ * inform the monitoring station of its vendor, software version, and so
+ * on.  An initiation message MUST be sent as the first message after
+ * the TCP session comes up.  An initiation message MAY be sent at any
+ * point thereafter, if warranted by a change on the monitored router.
+ * <p>
+ * The initiation message consists of the common BMP header followed by
+ * two or more Information TLVs containing information
+ * about the monitored router.  The sysDescr and sysName Information
+ * TLVs MUST be sent, any others are optional.  The string TLV MAY be
+ * included multiple times.
+ */
+public final class BmpInitiationMessage extends InitiationMessage {
+
+    /*
+
+      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
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |          Information Type     |       Information Length      |
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |                 Information (variable)                        |
+     ~                                                               ~
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+     */
+
+
+    private List<BmpMsg> initiationMeassages;
+
+
+    private BmpInitiationMessage(Builder builder) {
+        this.initiationMeassages = builder.initiationMeassages;
+    }
+
+    /**
+     * Returns BMP initiation message.
+     *
+     * @return BMP initiation message
+     */
+    public List<BmpMsg> getInitiationMeassages() {
+        return initiationMeassages;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        BmpInitiationMessage that = (BmpInitiationMessage) o;
+        return Objects.equals(initiationMeassages, that.initiationMeassages);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(initiationMeassages);
+    }
+
+
+    /**
+     * Data deserializer function for BMP initiation message.
+     *
+     * @return data deserializer function
+     */
+    public static Deserializer<BmpInitiationMessage> deserializer() {
+        return (data, offset, length) -> {
+            BiPredicate<ByteBuffer, Integer> isValidBuffer = (b, l)
+                    -> b.hasRemaining() && b.remaining() >= l;
+
+            ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            if (!isValidBuffer.test(bb, INIT_MSG_NOTIFICATION_HEADER_MIN_LENGTH)) {
+                throw new BmpParseException("Invalid bmp initiation message buffer size.");
+            }
+            Builder builder = new Builder();
+            while (bb.hasRemaining() && bb.remaining() > INIT_MSG_NOTIFICATION_HEADER_MIN_LENGTH) {
+                int msgtype = bb.getShort();
+                int msgLength = bb.getShort();
+                bb.position(bb.position() - INIT_MSG_NOTIFICATION_HEADER_MIN_LENGTH);
+                if (bb.remaining() < msgLength) {
+                    break;
+                }
+                byte[] msgBytes = new byte[msgLength];
+                bb.get(msgBytes);
+
+                builder.initiationMeassages(BmpInitMsg.deserializer()
+                        .deserialize(msgBytes, 0, msgLength));
+            }
+
+            return builder.build();
+        };
+    }
+
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("initiationMeassages", initiationMeassages)
+                .toString();
+    }
+
+    /**
+     * Builder for BMP initiation message.
+     */
+    private static class Builder {
+
+        private List<BmpMsg> initiationMeassages;
+
+        /**
+         * Setter bmp initiation message.
+         *
+         * @param msg bmp initiation message.
+         * @return this class builder.
+         */
+        public Builder initiationMeassages(BmpMsg msg) {
+            this.initiationMeassages.add(msg);
+            return this;
+        }
+
+        /**
+         * Builds bmp initiation message.
+         *
+         * @return bmp initiation message.
+         */
+        public BmpInitiationMessage build() {
+            return new BmpInitiationMessage(this);
+        }
+    }
+}