Copy latest code to master 50/2150/1
authorss412g <shuky.har-noy@intl.att.com>
Sun, 5 Jan 2020 09:52:19 +0000 (11:52 +0200)
committerss412g <shuky.har-noy@intl.att.com>
Sun, 5 Jan 2020 09:53:04 +0000 (11:53 +0200)
Change-Id: Ia3dc1891e8489b0241a45d54ac13da427337a682
Signed-off-by: ss412g <shuky.har-noy@intl.att.com>
25 files changed:
.gitignore
RIC-E2-TERMINATION/CMakeLists.txt
RIC-E2-TERMINATION/Dockerfile
RIC-E2-TERMINATION/ReadConfigFile.h [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.cpp [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.h [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/ConfigurationFileTest/testConfigFile.cpp [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/T1/E2Builder.h [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/T1/E2Setup.cpp [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/T1/Test1.cpp
RIC-E2-TERMINATION/TEST/base64/testBase64.cpp [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/e2sm.c
RIC-E2-TERMINATION/TEST/e2sm.h
RIC-E2-TERMINATION/TEST/e2test.cpp [new file with mode: 0644]
RIC-E2-TERMINATION/TEST/e2test.h [new file with mode: 0644]
RIC-E2-TERMINATION/base64.cpp
RIC-E2-TERMINATION/base64.h
RIC-E2-TERMINATION/config/config.conf [new file with mode: 0644]
RIC-E2-TERMINATION/container-tag.yaml
RIC-E2-TERMINATION/dockerRouter.txt
RIC-E2-TERMINATION/sctpThread.cpp
RIC-E2-TERMINATION/sctpThread.h
config/config.bad [new file with mode: 0644]
config/config.sec [new file with mode: 0644]
config/config.secbad [new file with mode: 0644]

index 853d153..ad33e82 100644 (file)
@@ -17,6 +17,7 @@ cmake-build-release/
 cmake_install.cmake
 e2.cbp
 e2
+T1
 setUpTest
 subscriptionTest
 CMakeLists.txt
@@ -36,6 +37,16 @@ RIC-E2-TERMINATION/tracelibcpp/CMakeLists.txt
 RIC-E2-TERMINATION/nlohmann/
 RIC-E2-TERMINATION/concurrentqueue/
 /RIC-E2-TERMINATION/base64/
-# documentation
-.tox
-docs/_build/
+/RIC-E2-TERMINATION/3rdparty/cxxopts/
+/RIC-E2-TERMINATION/3rdparty/cgreen_1.2.0_amd64.deb
+/testConfigFile
+/config/config.conf
+/logTest
+/b64Test
+/T1
+/e2Cov
+/RIC-E2-TERMINATION/3rdparty/pistache/
+/CMakeLists.txt.old
+/cmake-modules/
+/e2_coverage.base
+/teste2
index c9d0be3..b941163 100644 (file)
 cmake_minimum_required(VERSION 3.13)
 project(e2)
 
-set(CMAKE_VERBOSE_MAKEFILE on)
+set(CMAKE_VERBOSE_MAKEFILE off)
 
 set(CMAKE_CXX_STANDARD 17)
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEV_PKG=1")
-
-#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -LRIC-E2-TERMINATION/tracelibcpp/build -ggdb3 -Wall -W -Wpedantic")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -LRIC-E2-TERMINATION/base64/lib -O3 -Wall -Wpedantic")
-#only c code with -O3
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -LRIC-E2-TERMINATION/base64/lib -O3 -Wall -W -Wpedantic")
-
-include_directories(RIC-E2-TERMINATION)
-include_directories(RIC-E2-TERMINATION/3rdparty/asn1cFiles)
+set(PROJECT_NAME "e2")
+set(PROJECT_TEST_NAME "e2")
+
+
+if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+    #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -LRIC-E2-TERMINATION/tracelibcpp/build -ggdb3 -Wall -W -Wpedantic")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -O3 -L/usr/lib -Wall -Wpedantic")
+    #only c code with -O3
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -O3 -L/usr/lib -Wall -W -Wpedantic")
+else ()
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -ggdb3 --coverage -L/usr/lib -Wall -Wpedantic")
+    #only c code with -O3
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DASN_DISABLE_OER_SUPPORT -DASN_PDU_COLLECTION -L. -ggdb3 -L/usr/lib -Wall -W -Wpedantic")
+
+endif ()
+include_directories(RIC-E2-TERMINATION
+        RIC-E2-TERMINATION/3rdparty/asn1cFiles
+        RIC-E2-TERMINATION/3rdparty
+        cmake-modules)
 
 file(GLOB ASN_MODULE_SRCS "RIC-E2-TERMINATION/3rdparty/asn1cFiles/*.c")
 file(GLOB ASN_MODULE_HDRS "RIC-E2-TERMINATION/3rdparty/asn1cFiles/*.h")
@@ -54,16 +65,36 @@ include_directories(RIC-E2-TERMINATION/TEST)
 include_directories(RIC-E2-TERMINATION/TEST/e2smTest)
 include_directories(RIC-E2-TERMINATION/TEST/T1)
 include_directories(RIC-E2-TERMINATION/TEST/T2)
-include_directories(RIC-E2-TERMINATION/base64/include)
-include_directories(RIC-E2-TERMINATION/base64/lib)
+
 
 add_library(e2sm
         RIC-E2-TERMINATION/TEST/e2sm.c
         RIC-E2-TERMINATION/TEST/e2sm.h
         ${ASN_MODULE_HDRS})
+
 add_definitions(-DBOOST_LOG_DYN_LINK)
 
-link_libraries(nsl sctp c m dl mdclog rmr_nng nng e2sm asn1codec boost_system boost_log_setup boost_log boost_date_time boost_thread rt boost_filesystem  pthread)
+link_libraries(nsl
+        sctp
+        gcov
+        c
+        m
+        dl
+        mdclog
+        rmr_nng
+        nng
+        e2sm
+        asn1codec
+        boost_system
+        boost_log_setup
+        boost_log
+        boost_date_time
+        boost_thread
+        boost_system
+        rt
+        boost_filesystem
+        cgreen
+        pthread)
 
 add_executable(e2 RIC-E2-TERMINATION/sctpThread.cpp
         RIC-E2-TERMINATION/sctpThread.h
@@ -71,7 +102,66 @@ add_executable(e2 RIC-E2-TERMINATION/sctpThread.cpp
         RIC-E2-TERMINATION/mapWrapper.h
         RIC-E2-TERMINATION/base64.h
         RIC-E2-TERMINATION/base64.cpp
+        RIC-E2-TERMINATION/ReadConfigFile.h
         )
 
 add_executable(e2smtest
         RIC-E2-TERMINATION/TEST/e2smTest/e2smtest.cpp)
+
+add_executable(testConfigFile
+        RIC-E2-TERMINATION/ReadConfigFile.h
+        RIC-E2-TERMINATION/TEST/ConfigurationFileTest/testConfigFile.cpp)
+
+add_executable(b64Test
+        RIC-E2-TERMINATION/base64.cpp
+        RIC-E2-TERMINATION/base64.h
+        RIC-E2-TERMINATION/TEST/base64/testBase64.cpp)
+
+add_executable(T1
+        RIC-E2-TERMINATION/TEST/T1/E2Builder.h
+        RIC-E2-TERMINATION/TEST/T1/E2Setup.cpp
+        #RIC-E2-TERMINATION/TEST/T1/Test1.cpp
+        #RIC-E2-TERMINATION/TEST/T1/
+        )
+
+
+find_package(RapidJSON)
+
+add_executable(logTest
+        RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.h
+        RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.cpp)
+
+add_executable(teste2
+        RIC-E2-TERMINATION/TEST/e2test.h
+        RIC-E2-TERMINATION/TEST/e2test.cpp
+        )
+
+if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+    LIST(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
+    set(CMAKE_BUILD_TYPE "Debug")
+    include(cmake-modules/CodeCoverage.cmake)
+    target_link_libraries(${PROJECT_TEST_NAME} gcov)
+
+    set(LDFLAGS "--coverage -fprofile-arcs")
+
+    #    setup_target_for_coverage_lcov(${PROJECT_NAME}_coverage ${PROJECT_TEST_NAME} coverage)
+    set(COVERAGE_LCOV_EXCLUDES ${PROJECT_SOURCE_DIR}/config'
+            ${PROJECT_SOURCE_DIR}/log'
+            '${PROJECT_SOURCE_DIR}/docs'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/3rdparty'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/asn1cFiles'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/TEST'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/config')
+
+    set(COVERAGE_EXCLUDES '${PROJECT_SOURCE_DIR}/config'
+            ${PROJECT_SOURCE_DIR}/log'
+            '${PROJECT_SOURCE_DIR}/docs'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/3rdparty'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/asn1cFiles'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/TEST'
+            '${PROJECT_SOURCE_DIR}/RIC-E2-TERMINATION/config')
+    append_coverage_compiler_flags()
+    SETUP_TARGET_FOR_COVERAGE_LCOV(NAME e2_coverage
+            EXECUTABLE e2
+            DEPENDENCIES e2)
+endif ()
\ No newline at end of file
index d86523e..5604fcb 100644 (file)
 #   limitations under the License.
 #
 ##############################################################################
+
 #
 #   This source code is part of the near-RT RIC (RAN Intelligent Controller)
 #   platform project (RICP).
 #
 
-FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:2-u16.04-nng as ubuntu
+FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:3-u16.04-nng as ubuntu
 
 WORKDIR /opt/e2/
 
 RUN mkdir -p /opt/e2/RIC-E2-TERMINATION/ \
     && mkdir -p /opt/e2/RIC-E2-TERMINATION/TEST/T1 \
-    && mkdir -p /opt/e2/RIC-E2-TERMINATION/TEST/T2
+    && mkdir -p /opt/e2/RIC-E2-TERMINATION/TEST/T2 \
+    && mkdir -p /opt/e2/RIC-E2-TERMINATION/3rdparty
+
 COPY . /opt/e2/RIC-E2-TERMINATION/
 RUN mv /opt/e2/RIC-E2-TERMINATION/CMakeLists.txt /opt/e2/
 
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.10.0_amd64.deb/download.deb
-RUN dpkg -i rmr_1.10.0_amd64.deb
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.10.0_amd64.deb/download.deb
-RUN dpkg -i rmr-dev_1.10.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.13.0_amd64.deb/download.deb
+RUN dpkg -i rmr_1.13.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.13.0_amd64.deb/download.deb
+RUN dpkg -i rmr-dev_1.13.0_amd64.deb
+
+ARG BUILD_TYPE=Release
 
 RUN apt-get install -y autoconf gawk libtool automake pkg-config autoconf-archive \
     && git clone http://gerrit.o-ran-sc.org/r/com/log \
-    && cd log \
-    && ./autogen.sh && ./configure && make && make install && ldconfig \
-    && cd /opt/e2/ && /usr/local/bin/cmake . && make
+    && cd log && ./autogen.sh && ./configure && make && make install && ldconfig \
+    && cd /opt/e2/RIC-E2-TERMINATION/3rdparty && git clone https://github.com/jarro2783/cxxopts.git \
+    && cd cxxopts && mkdir build && cd build && cmake .. && make install && ldconfig \
+    && cd /opt/e2/RIC-E2-TERMINATION/3rdparty && git clone https://github.com/Tencent/rapidjson.git \
+    && cd rapidjson && mkdir build && cd build && cmake .. && make install && ldconfig \
+    && cd /opt/e2/RIC-E2-TERMINATION/3rdparty && git clone https://github.com/oktal/pistache.git\
+    && cd pistache && mkdir build && cd build && cmake .. && make install && ldconfig\
+    && cd /opt/e2/RIC-E2-TERMINATION/3rdparty \
+    && wget --content-disposition https://github.com/cgreen-devs/cgreen/releases/download/1.2.0/cgreen_1.2.0_amd64.deb \
+    && dpkg -i cgreen_1.2.0_amd64.deb \
+    && cd /opt/e2/ && git clone https://github.com/bilke/cmake-modules.git \
+    && cd /opt/e2/ && /usr/local/bin/cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE . && make
+
+RUN if [$BUILD_TYPE == "Debug"] ; then make e2_coverage ; fi
 
 #    && git clone http://gerrit.o-ran-sc.org/r/ric-plt/tracelibcpp \
 #    && cd tracelibcpp && mkdir build && cd build  \
@@ -52,23 +68,29 @@ RUN apt-get install -y autoconf gawk libtool automake pkg-config autoconf-archiv
 #    && find / -type f -name "libopentracing.a" -exec cp {} libopentracing.a \; && cd /opt/e2/RIC-E2-TERMINATION && ls nlohmann  \
 
 FROM ubuntu:16.04
-RUN apt-get update && apt-get install -y net-tools iputils-ping curl tcpdump
+RUN apt-get update && apt-get install -y net-tools iputils-ping curl tcpdump && mkdir -p /opt/e2/config
 
 COPY --from=ubuntu /opt/e2/e2 /opt/e2/e2
 COPY --from=ubuntu /opt/e2/RIC-E2-TERMINATION/dockerRouter.txt /opt/e2/dockerRouter.txt
+COPY --from=ubuntu /opt/e2/RIC-E2-TERMINATION/config/config.conf /opt/e2/config/config.conf
 #COPY --from=ubuntu /opt/e2/RIC-E2-TERMINATION/tracelibcpp/build/libtracelibcpp.so /usr/local/lib/libtracelibcpp.so
 #COPY --from=ubuntu /opt/e2/RIC-E2-TERMINATION/tracelibcpp/build/libtracelibcpp.so.0 /usr/local/lib/libtracelibcpp.so.0
 #COPY --from=ubuntu /opt/e2/RIC-E2-TERMINATION/tracelibcpp/build/libtracelibcpp.so.0.0.2 /usr/local/lib/libtracelibcpp.so.0.0.2
 #COPY --from=ubuntu /usr/local/lib/librmr_nng.a /usr/local/lib/librmr_nng.a
 COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1 /usr/local/lib/librmr_nng.so.1
 COPY --from=ubuntu /usr/local/lib/librmr_nng.so /usr/local/lib/librmr_nng.so
-COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1.10.0 /usr/local/lib/librmr_nng.so.1.10.0
+COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1.13.0 /usr/local/lib/librmr_nng.so.1.13.0
 COPY --from=ubuntu /usr/local/lib/libnng.so.1 /usr/local/lib/libnng.so.1
 COPY --from=ubuntu /usr/local/lib/libmdclog.so.0 /usr/local/lib/libmdclog.so.0
 
 COPY --from=ubuntu /usr/lib/libboost_log_setup.so /usr/lib/libboost_log_setup.so
 COPY --from=ubuntu /usr/lib/libboost_log_setup.so.1.69.0 /usr/lib/libboost_log_setup.so.1.69.0
 
+COPY --from=ubuntu /usr/local/lib/libpistache.so  /usr/local/lib/libpistache.so
+COPY --from=ubuntu /usr/local/lib/libpistache.so.0  /usr/local/lib/libpistache.so.0
+COPY --from=ubuntu /usr/local/lib/libpistache.so.0.0.001-git20191031  /usr/local/lib/libpistache.so.0.0.001-git20191031
+
+
 COPY --from=ubuntu /usr/lib/libboost_log.so /usr/lib/libboost_log.so
 COPY --from=ubuntu /usr/lib/libboost_log.so.1.69.0 /usr/lib/libboost_log.so.1.69.0
 
@@ -97,8 +119,5 @@ COPY --from=ubuntu /usr/lib/x86_64-linux-gnu/libicudata.so.55.1 /usr/lib/x86_64-
 WORKDIR /opt/e2/
 ENV LD_LIBRARY_PATH=/usr/local/lib
 ENV RMR_SEED_RT=dockerRouter.txt
-ENV nano=38000
-ENV loglevel=info
-ENV volume="."
 EXPOSE 38000
-CMD ["sh", "-c", "./e2 nano $nano loglevel $loglevel volume $volume"]
+CMD ["sh", "-c", "./e2 -p config -f config.conf"]
diff --git a/RIC-E2-TERMINATION/ReadConfigFile.h b/RIC-E2-TERMINATION/ReadConfigFile.h
new file mode 100644 (file)
index 0000000..469d5ef
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 11/19/19.
+//
+
+#ifndef E2_READCONFIGFILE_H
+#define E2_READCONFIGFILE_H
+
+#include <string>
+#include <unordered_map>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cstdlib>
+
+#include <boost/algorithm/string.hpp>
+#include <mdclog/mdclog.h>
+
+using namespace std;
+
+class ReadConfigFile {
+public:
+
+    explicit ReadConfigFile() = default;
+
+    int openConfigFile(std::string const& configFile) {
+        std::ifstream file(configFile.c_str());
+        if (!file) {  // file not found
+            mdclog_write(MDCLOG_ERR, "File: %s, failed to open", configFile.c_str());
+            return -1;
+        }
+        std::string line;
+        std::string section;
+
+        while (std::getline(file,line)) {
+            if (!line.length() || line[0] == '#' || line[0] == ';' || line[0] == '{') {
+                continue;
+            }
+//            else if (line[0] == '#') {
+//                continue;
+//            } else if (line[0] == ';') {
+//                continue;
+//            }
+
+
+            if (line[0] =='[') { //section
+                auto sectionEnd = line.find(']');
+                if (sectionEnd == std::string::npos) {
+                    mdclog_write(MDCLOG_ERR, "Error section definition: %s  ", line.c_str());
+                    section.clear();
+                    return -1;
+//                    continue;
+                }
+                section = line.substr(1, sectionEnd - 1) + ".";
+                continue;
+            }
+
+            auto leftHand = line.find('=');
+            if (leftHand == std::string::npos) {
+                mdclog_write(MDCLOG_ERR, "problematic entry: %s  ", line.c_str());
+                continue;
+            }
+//            auto name = line.substr(0,leftHand);
+//            trim(name);
+            auto name = section + trim(line.substr(0, leftHand));
+
+            auto value = line.substr(leftHand+1);
+            if (value.length() == 0) {
+                mdclog_write(MDCLOG_ERR, "problematic entry: %s no value ", line.c_str());
+                continue;
+
+            }
+            trim(value);
+            //cout << "entry = " << name << " value = " << value  << endl;
+            entries[name] = value;
+        }
+        return 0;
+    }
+
+    /**
+     * @param key the key we are looking
+     * @return string value of the entry and "" if not exists
+     */
+    string getStringValue(std::string const& key) const {
+        auto entry = entries.find(key);
+        if (entry == entries.end()) {
+            return "";
+        }
+        return entry->second;
+    }
+
+    /**
+     * @param key the key we are looking
+     * @return int value of the entry and -1 if not exists
+     */
+    int getIntValue(std::string const& key) const {
+        auto entry = entries.find(key);
+        if (entry == entries.end()) {
+             return -1;
+        }
+        char *dummy;
+        int ret = (int)std::strtol(entry->second.c_str(), &dummy, 10);
+        //cout << "entry = " << key << " value = " << entry->second  << " int value = " << ret << endl;
+        return ret;
+    }
+
+    /**
+    * @param key the key we are looking
+    * @return double value of the entry and -1.0 if not exists
+    */
+    double getDoubleValue(std::string const& key) const {
+        auto entry = entries.find(key);
+        if (entry == entries.end()) {
+            return -1.0;
+        }
+        char *dummy;
+        return std::strtod(entry->second.c_str(), &dummy);
+    }
+
+private:
+    std::unordered_map<string, string> entries;
+
+    inline static std::string& ltrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") {
+        str.erase(0, str.find_first_not_of(chars));
+        return str;
+    }
+
+    inline static std::string& rtrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") {
+        str.erase(str.find_last_not_of(chars) + 1);
+        return str;
+    }
+
+    inline static std::string& trim(basic_string<char> str, const std::string& chars = "\t\n\v\f\r ") {
+        return ltrim(rtrim(str, chars), chars);
+    }
+};
+
+
+#endif //E2_READCONFIGFILE_H
diff --git a/RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.cpp b/RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.cpp
new file mode 100644 (file)
index 0000000..89bc48a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 11/26/19.
+//
+
+#include "LogTest.h"
+
+string LogTest::getLine() {
+    std::string line;
+
+    if (std::getline(file, line)) {
+        return line;
+    }
+    return "";
+}
+
+void LogTest::getJsonDoc(string json) {
+    if (json.length() != 0) {
+        document.Parse(json.c_str());
+    }
+}
+
+string LogTest::getBase64(Document &document) {
+    if (document.HasMember("asnBase64")) {
+        return document["asnBase64"].GetString();
+    }
+    return "";
+}
diff --git a/RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.h b/RIC-E2-TERMINATION/TEST/ASN_LOG/LogTest.h
new file mode 100644 (file)
index 0000000..d264fef
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 11/26/19.
+//
+
+#ifndef E2_LOGTEST_H
+#define E2_LOGTEST_H
+#include <algorithm>
+
+#include <cstdio>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <random>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/sctp.h>
+#include <thread>
+#include <atomic>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <ctime>
+#include <netdb.h>
+#include <sys/epoll.h>
+#include <mutex>
+#include <shared_mutex>
+#include <iterator>
+#include <map>
+#include <fstream>
+
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+#include "rapidjson/stringbuffer.h"
+
+using namespace std;
+using namespace rapidjson;
+
+class LogTest {
+public:
+    LogTest() = default;
+
+    int openFile(string const& configFile) {
+        file.open(configFile.c_str());
+        if (!file) {
+            return -1;
+        }
+        return 0;
+    }
+
+    string getLine();
+    void getJsonDoc(string json);
+
+    string getBase64(Document &document);
+
+private:
+    std::ifstream file;
+    Document document;
+};
+
+
+#endif //E2_LOGTEST_H
diff --git a/RIC-E2-TERMINATION/TEST/ConfigurationFileTest/testConfigFile.cpp b/RIC-E2-TERMINATION/TEST/ConfigurationFileTest/testConfigFile.cpp
new file mode 100644 (file)
index 0000000..33deb2b
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 11/19/19.
+//
+
+#include "ReadConfigFile.h"
+#include <mdclog/mdclog.h>
+#include <cgreen/cgreen.h>
+
+Describe(Cgreen);
+BeforeEach(Cgreen) {}
+AfterEach(Cgreen) {}
+
+using namespace cgreen;
+
+void init_log() {
+    mdclog_attr_t *attr;
+    mdclog_attr_init(&attr);
+    mdclog_attr_set_ident(attr, "TestConfiguration");
+    mdclog_init(attr);
+    mdclog_attr_destroy(attr);
+}
+
+Ensure(Cgreen, fileNotExist) {
+    ReadConfigFile  conf {};
+    assert_that( conf.openConfigFile("kuku") == -1);
+}
+
+Ensure(Cgreen, fileExists) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.conf") == 0);
+}
+
+Ensure(Cgreen, goodparams) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.conf") == 0);
+    assert_that(conf.getIntValue("nano") == 38000);
+    assert_that(conf.getStringValue("loglevel") == "info");
+    assert_that(conf.getStringValue("volume") == "log");
+
+}
+
+Ensure(Cgreen, badParams) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.conf") == 0);
+    assert_that(conf.getIntValue("nano") != 38002);
+    assert_that(conf.getStringValue("loglevel") != "");
+    assert_that(conf.getStringValue("volume") != "bob");
+    assert_that(conf.getStringValue("volum") != "bob");
+}
+
+Ensure(Cgreen, wrongType) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.conf") == 0);
+    assert_that(conf.getStringValue("nano") != "debug");
+    assert_that(conf.getIntValue("loglevel") != 3);
+    assert_that(conf.getDoubleValue("loglevel") != 3.0);
+}
+
+Ensure(Cgreen, badValues) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.bad") == 0);
+}
+
+Ensure(Cgreen, sectionTest) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.sec") == 0);
+    assert_that(conf.getIntValue("config.nano") == 38000);
+}
+
+Ensure(Cgreen, sectionBadTest) {
+    ReadConfigFile  conf {};
+    assert_that(conf.openConfigFile("config/config.secbad") == -1);
+    //assert_that(conf.getIntValue("config.nano") == 38000);
+}
+
+int main(const int argc, char **argv) {
+    mdclog_severity_t loglevel = MDCLOG_INFO;
+    init_log();
+    mdclog_level_set(loglevel);
+
+    //TestSuite *suite = create_test_suite();
+    TestSuite *suite = create_named_test_suite_(__FUNCTION__, __FILE__, __LINE__);
+
+    add_test_with_context(suite, Cgreen, fileNotExist);
+    add_test_with_context(suite, Cgreen, fileExists);
+    add_test_with_context(suite, Cgreen, goodparams);
+    add_test_with_context(suite, Cgreen, badParams);
+    add_test_with_context(suite, Cgreen, wrongType);
+    add_test_with_context(suite, Cgreen, badValues);
+    add_test_with_context(suite, Cgreen, sectionTest);
+    add_test_with_context(suite, Cgreen, sectionBadTest);
+
+    return cgreen::run_test_suite(suite, create_text_reporter());
+
+}
\ No newline at end of file
diff --git a/RIC-E2-TERMINATION/TEST/T1/E2Builder.h b/RIC-E2-TERMINATION/TEST/T1/E2Builder.h
new file mode 100644 (file)
index 0000000..78b853c
--- /dev/null
@@ -0,0 +1,750 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 12/10/19.
+//
+
+#ifndef E2_E2BUILDER_H
+#define E2_E2BUILDER_H
+
+#include <cstring>
+#include <cstdio>
+#include <cerrno>
+#include <cstdlib>
+#include <sys/types.h>
+#include <error.h>
+#include <mdclog/mdclog.h>
+#include <algorithm>
+
+
+#include <mdclog/mdclog.h>
+
+
+#include "asn1cFiles/E2AP-PDU.h"
+#include "asn1cFiles/InitiatingMessage.h"
+#include "asn1cFiles/SuccessfulOutcome.h"
+#include "asn1cFiles/UnsuccessfulOutcome.h"
+
+#include "asn1cFiles/ProtocolIE-Field.h"
+
+#include "asn1cFiles/FDD-Info.h"
+#include "asn1cFiles/TDD-Info.h"
+#include "asn1cFiles/Neighbour-Information.h"
+
+
+#include "asn1cFiles/constr_TYPE.h"
+#include "asn1cFiles/asn_constant.h"
+
+using namespace std;
+
+#define printEntry(type, function) \
+    if (mdclog_level_get() >= MDCLOG_DEBUG) { \
+        mdclog_write(MDCLOG_DEBUG, "start Test %s , %s", type, function); \
+    }
+
+
+static void checkAndPrint(asn_TYPE_descriptor_t *typeDescriptor, void *data, char *dataType, const char *function) {
+    char errbuf[128]; /* Buffer for error message */
+    size_t errlen = sizeof(errbuf); /* Size of the buffer */
+    if (asn_check_constraints(typeDescriptor, data, errbuf, &errlen) != 0) {
+        mdclog_write(MDCLOG_ERR, "%s Constraint validation failed: %s", dataType, errbuf);
+    } else if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        mdclog_write(MDCLOG_DEBUG, "%s successes function %s", dataType, function);
+    }
+}
+
+BIT_STRING_t *createBIT_STRING(int size, int unusedBits, uint8_t *data) {
+    printEntry("BIT_STRING_t", __func__)
+    auto *bitString = (BIT_STRING_t *)calloc(1, sizeof(BIT_STRING_t));
+    ASN_STRUCT_RESET(asn_DEF_BIT_STRING, bitString);
+    bitString->size = size;
+    bitString->bits_unused = unusedBits;
+    bitString->buf = (uint8_t *)calloc(1, size);
+    // set bits to zero
+    data[bitString->size - 1] = ((unsigned)(data[bitString->size - 1] >>
+            (unsigned)bitString->bits_unused) << (unsigned)bitString->bits_unused);
+    memcpy(bitString->buf, data, size);
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_BIT_STRING, bitString, (char *)"BIT_STRING_t", __func__);
+    }
+
+    return bitString;
+}
+
+
+OCTET_STRING_t *createOCTET_STRING(const unsigned char *data, int size) {
+    printEntry("OCTET_STRING_t", __func__)
+    auto *octs = (PLMN_Identity_t *)calloc(1, sizeof(PLMN_Identity_t));
+    ASN_STRUCT_RESET(asn_DEF_OCTET_STRING, octs);
+    octs->size = size;
+    octs->buf = (uint8_t *)calloc(1, size);
+    memcpy(octs->buf, data, size);
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_OCTET_STRING, octs, (char *)"OCTET_STRING_t", __func__);
+    }
+    return octs;
+}
+
+
+PLMN_Identity_t *createPLMN_ID(const unsigned char *data) {
+    printEntry("PLMN_Identity_t", __func__)
+    auto *plmnId = (PLMN_Identity_t *)calloc(1, sizeof(PLMN_Identity_t));
+    ASN_STRUCT_RESET(asn_DEF_PLMN_Identity, plmnId);
+    plmnId->size = 3;
+    plmnId->buf = (uint8_t *)calloc(1, 3);
+    memcpy(plmnId->buf, data, 3);
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_PLMN_Identity, plmnId, (char *)"PLMN_Identity_t", __func__);
+    }
+    return plmnId;
+}
+
+ENB_ID_t *createENB_ID(ENB_ID_PR enbType, unsigned char *data) {
+    printEntry("ENB_ID_t", __func__)
+    auto *enb = (ENB_ID_t *)calloc(1, sizeof(ENB_ID_t));
+    ASN_STRUCT_RESET(asn_DEF_ENB_ID, enb);
+
+    enb->present = enbType;
+
+    switch (enbType) {
+        case ENB_ID_PR_macro_eNB_ID: { // 20 bit 3 bytes
+            enb->choice.macro_eNB_ID.size = 3;
+            enb->choice.macro_eNB_ID.bits_unused = 4;
+
+            enb->present = ENB_ID_PR_macro_eNB_ID;
+
+            enb->choice.macro_eNB_ID.buf = (uint8_t *)calloc(1, enb->choice.macro_eNB_ID.size);
+            data[enb->choice.macro_eNB_ID.size - 1] = ((unsigned)(data[enb->choice.macro_eNB_ID.size - 1] >>
+                    (unsigned)enb->choice.macro_eNB_ID.bits_unused) << (unsigned)enb->choice.macro_eNB_ID.bits_unused);
+            memcpy(enb->choice.macro_eNB_ID.buf, data, enb->choice.macro_eNB_ID.size);
+
+            break;
+        }
+        case ENB_ID_PR_home_eNB_ID: { // 28 bit 4 bytes
+            enb->choice.home_eNB_ID.size = 4;
+            enb->choice.home_eNB_ID.bits_unused = 4;
+            enb->present = ENB_ID_PR_home_eNB_ID;
+
+            enb->choice.home_eNB_ID.buf = (uint8_t *)calloc(1, enb->choice.home_eNB_ID.size);
+            data[enb->choice.home_eNB_ID.size - 1] = ((unsigned)(data[enb->choice.home_eNB_ID.size - 1] >>
+                    (unsigned)enb->choice.home_eNB_ID.bits_unused) << (unsigned)enb->choice.home_eNB_ID.bits_unused);
+            memcpy(enb->choice.home_eNB_ID.buf, data, enb->choice.home_eNB_ID.size);
+            break;
+        }
+        case ENB_ID_PR_short_Macro_eNB_ID: { // 18 bit - 3 bytes
+            enb->choice.short_Macro_eNB_ID.size = 3;
+            enb->choice.short_Macro_eNB_ID.bits_unused = 6;
+            enb->present = ENB_ID_PR_short_Macro_eNB_ID;
+
+            enb->choice.short_Macro_eNB_ID.buf = (uint8_t *)calloc(1, enb->choice.short_Macro_eNB_ID.size);
+            data[enb->choice.short_Macro_eNB_ID.size - 1] = ((unsigned)(data[enb->choice.short_Macro_eNB_ID.size - 1] >>
+                    (unsigned)enb->choice.short_Macro_eNB_ID.bits_unused) << (unsigned)enb->choice.short_Macro_eNB_ID.bits_unused);
+            memcpy(enb->choice.short_Macro_eNB_ID.buf, data, enb->choice.short_Macro_eNB_ID.size);
+            break;
+        }
+        case ENB_ID_PR_long_Macro_eNB_ID: { // 21
+            enb->choice.long_Macro_eNB_ID.size = 3;
+            enb->choice.long_Macro_eNB_ID.bits_unused = 3;
+            enb->present = ENB_ID_PR_long_Macro_eNB_ID;
+
+            enb->choice.long_Macro_eNB_ID.buf = (uint8_t *)calloc(1, enb->choice.long_Macro_eNB_ID.size);
+            data[enb->choice.long_Macro_eNB_ID.size - 1] = ((unsigned)(data[enb->choice.long_Macro_eNB_ID.size - 1] >>
+                    (unsigned)enb->choice.long_Macro_eNB_ID.bits_unused) << (unsigned)enb->choice.long_Macro_eNB_ID.bits_unused);
+            memcpy(enb->choice.long_Macro_eNB_ID.buf, data, enb->choice.long_Macro_eNB_ID.size);
+            break;
+        }
+        default:
+            free(enb);
+            return nullptr;
+    }
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_ENB_ID, enb, (char *)"ENB_ID_t", __func__);
+    }
+    return enb;
+}
+
+GlobalENB_ID_t *createGlobalENB_ID(PLMN_Identity_t *plmnIdentity, ENB_ID_t *enbId) {
+    printEntry("GlobalENB_ID_t", __func__)
+    auto *genbId = (GlobalENB_ID_t *)calloc(1, sizeof(GlobalENB_ID_t));
+    ASN_STRUCT_RESET(asn_DEF_GlobalENB_ID, genbId);
+    memcpy(&genbId->pLMN_Identity, plmnIdentity, sizeof(PLMN_Identity_t));
+    memcpy(&genbId->eNB_ID, enbId, sizeof(ENB_ID_t));
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_GlobalENB_ID, genbId, (char *)"GlobalENB_ID_t", __func__);
+    }
+    return genbId;
+}
+
+
+ECGI_t *CreateECGI(PLMN_Identity_t *plmnIdentity, BIT_STRING_t * eUtran) {
+    printEntry("ECGI_t", __func__)
+    auto *ecgi = (ECGI_t *)calloc(1, sizeof(ECGI_t));
+    ASN_STRUCT_RESET(asn_DEF_ECGI, ecgi);
+
+    memcpy(&ecgi->pLMN_Identity, plmnIdentity, sizeof(PLMN_Identity_t));
+    memcpy(&ecgi->eUTRANcellIdentifier, eUtran, sizeof(BIT_STRING_t));
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_ECGI, ecgi, (char *)"ECGI_t", __func__);
+    }
+    return ecgi;
+}
+
+//
+//FDD-Info ::= SEQUENCE {
+//        uL-EARFCN                                            EARFCN,
+//        dL-EARFCN                                            EARFCN,
+//        uL-Transmission-Bandwidth            Transmission-Bandwidth,
+//        dL-Transmission-Bandwidth            Transmission-Bandwidth,
+//        iE-Extensions                                ProtocolExtensionContainer { {FDD-Info-ExtIEs} } OPTIONAL,
+//        ...
+//}
+//
+//FDD-Info-ExtIEs X2AP-PROTOCOL-EXTENSION ::= {
+//        { ID id-UL-EARFCNExtension                                           CRITICALITY reject      EXTENSION EARFCNExtension                                                                       PRESENCE optional}|
+//        { ID id-DL-EARFCNExtension                                           CRITICALITY reject      EXTENSION EARFCNExtension                                                                       PRESENCE optional}|
+//        { ID id-OffsetOfNbiotChannelNumberToDL-EARFCN        CRITICALITY reject      EXTENSION OffsetOfNbiotChannelNumberToEARFCN            PRESENCE optional}|
+//        { ID id-OffsetOfNbiotChannelNumberToUL-EARFCN        CRITICALITY reject      EXTENSION OffsetOfNbiotChannelNumberToEARFCN            PRESENCE optional}|
+//        { ID id-NRS-NSSS-PowerOffset                                 CRITICALITY ignore      EXTENSION NRS-NSSS-PowerOffset                                                  PRESENCE optional}|
+//        { ID id-NSSS-NumOccasionDifferentPrecoder            CRITICALITY ignore      EXTENSION NSSS-NumOccasionDifferentPrecoder                     PRESENCE optional},
+//        ...
+//}
+
+static FDD_Info_t *create_fdd(long dL_EARFCN,
+        long uL_EARFCN,
+        e_Transmission_Bandwidth ultb,
+        e_Transmission_Bandwidth dltb) {
+    printEntry("FDD_Info_t", __func__)
+    auto *fdd = (FDD_Info_t *)calloc(1, sizeof(FDD_Info_t));
+    ASN_STRUCT_RESET(asn_DEF_FDD_Info, fdd);
+
+    //EARFCN ::= INTEGER (0..maxEARFCN)
+
+    if (dL_EARFCN >= 0 && dL_EARFCN <= maxEARFCN) {
+        fdd->dL_EARFCN = dL_EARFCN;
+    } else {
+        fdd->dL_EARFCN = maxEARFCN;
+    }
+    if (uL_EARFCN >= 0 && uL_EARFCN <= maxEARFCN) {
+        fdd->uL_EARFCN = uL_EARFCN;
+    } else {
+        fdd->uL_EARFCN = maxEARFCN;
+    }
+
+    fdd->uL_Transmission_Bandwidth = ultb;
+    fdd->dL_Transmission_Bandwidth = dltb;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_FDD_Info, fdd, (char *)"FDD_Info_t", __func__);
+    }
+
+    return fdd;
+}
+
+SpecialSubframe_Info_t *createSpecialSubframe_Info(e_CyclicPrefixDL eCyclicPrefixDl,
+        e_CyclicPrefixUL eCyclicPrefixUl,
+        e_SpecialSubframePatterns eSpecialSubframePatterns) {
+    printEntry("SpecialSubframe_Info_t", __func__)
+    auto *ssf = (SpecialSubframe_Info_t *)calloc(1, sizeof(SpecialSubframe_Info_t));
+    ASN_STRUCT_RESET(asn_DEF_SpecialSubframe_Info, ssf);
+
+    ssf->cyclicPrefixDL = eCyclicPrefixDl;
+    ssf->cyclicPrefixUL = eCyclicPrefixUl;
+    ssf->specialSubframePatterns = eSpecialSubframePatterns;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_SpecialSubframe_Info, ssf, (char *)"SpecialSubframe_Info_t", __func__);
+    }
+    return ssf;
+}
+
+//TDD-Info ::= SEQUENCE {
+//        eARFCN                                                       EARFCN,
+//        transmission-Bandwidth                       Transmission-Bandwidth,
+//        subframeAssignment                           SubframeAssignment,
+//        specialSubframe-Info                 SpecialSubframe-Info,
+//        iE-Extensions                                        ProtocolExtensionContainer { {TDD-Info-ExtIEs} } OPTIONAL,
+//        ...
+//}
+//
+//TDD-Info-ExtIEs X2AP-PROTOCOL-EXTENSION ::= {
+//        { ID id-AdditionalSpecialSubframe-Info                       CRITICALITY ignore      EXTENSION AdditionalSpecialSubframe-Info                                PRESENCE optional}|
+//        { ID id-eARFCNExtension                                                      CRITICALITY reject      EXTENSION EARFCNExtension                                                                       PRESENCE optional}|
+//        { ID id-AdditionalSpecialSubframeExtension-Info      CRITICALITY ignore      EXTENSION AdditionalSpecialSubframeExtension-Info       PRESENCE optional}|
+//        { ID id-OffsetOfNbiotChannelNumberToDL-EARFCN        CRITICALITY reject      EXTENSION OffsetOfNbiotChannelNumberToEARFCN            PRESENCE optional}|
+//        { ID id-NBIoT-UL-DL-AlignmentOffset                          CRITICALITY reject      EXTENSION NBIoT-UL-DL-AlignmentOffset                                   PRESENCE optional},
+//        ...
+//}
+
+static TDD_Info_t *create_Tdd(long eARFCN,
+        e_Transmission_Bandwidth tb,
+        e_SubframeAssignment sfA,
+        SpecialSubframe_Info_t *ssfi) {
+    printEntry("TDD_Info_t", __func__)
+    auto *tdd = (TDD_Info_t *)calloc(1, sizeof(FDD_Info_t));
+    ASN_STRUCT_RESET(asn_DEF_TDD_Info, tdd);
+
+    if (eARFCN >= 0 && eARFCN <= maxEARFCN) {
+        tdd->eARFCN = eARFCN;
+    } else {
+        tdd->eARFCN = maxEARFCN;
+    }
+    tdd->transmission_Bandwidth = tb;
+    tdd->subframeAssignment = sfA;
+    memcpy(&tdd->specialSubframe_Info, ssfi, sizeof(SpecialSubframe_Info_t));
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_TDD_Info, tdd, (char *)"TDD_Info_t", __func__);
+    }
+    return tdd;
+}
+
+static EUTRA_Mode_Info_t *createEUTRA_Mode_Info_FDD(FDD_Info_t *fdd) {
+    printEntry("EUTRA_Mode_Info_t", __func__)
+    auto *eutraModeInfo = (EUTRA_Mode_Info_t *)calloc(1, sizeof(EUTRA_Mode_Info_t));
+    ASN_STRUCT_RESET(asn_DEF_EUTRA_Mode_Info, eutraModeInfo);
+
+    eutraModeInfo->present = EUTRA_Mode_Info_PR_fDD;
+    eutraModeInfo->choice.fDD = fdd;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_EUTRA_Mode_Info, eutraModeInfo, (char *)"EUTRA_Mode_Info_t", __func__);
+    }
+    return eutraModeInfo;
+
+}
+
+static EUTRA_Mode_Info_t *createEUTRA_Mode_Info_TDD(TDD_Info_t *tdd) {
+    printEntry("EUTRA_Mode_Info_t", __func__)
+    auto *eutraModeInfo = (EUTRA_Mode_Info_t *)calloc(1, sizeof(EUTRA_Mode_Info_t));
+    ASN_STRUCT_RESET(asn_DEF_EUTRA_Mode_Info, eutraModeInfo);
+
+    eutraModeInfo->present = EUTRA_Mode_Info_PR_tDD;
+    eutraModeInfo->choice.tDD = tdd;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_EUTRA_Mode_Info, eutraModeInfo, (char *)"EUTRA_Mode_Info_t", __func__);
+    }
+    return eutraModeInfo;
+
+}
+
+Neighbour_Information__Member *createNeighbour_Information__Member(ECGI_t *eCGI, long pci, long eARFCN) {
+    printEntry("Neighbour_Information__Member", __func__)
+    auto *nigborInformation = (Neighbour_Information__Member *)calloc(1, sizeof(Neighbour_Information__Member));
+    ASN_STRUCT_RESET(asn_DEF_Neighbour_Information, nigborInformation);
+
+    memcpy(&nigborInformation->eCGI, eCGI, sizeof(ECGI_t));
+    nigborInformation->pCI = pci;
+    nigborInformation->eARFCN = eARFCN;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_Neighbour_Information, nigborInformation, (char *)"Neighbour_Information__Member", __func__);
+    }
+    return nigborInformation;
+}
+
+void buildNeighbour_InformationVector(Neighbour_Information_t *neighbourInformation, Neighbour_Information__Member *member) {
+    ASN_SEQUENCE_ADD(&neighbourInformation->list, member);
+}
+
+//ServedCell-Information ::= SEQUENCE {
+//        pCI                                  PCI,
+//        cellId                               ECGI,
+//        tAC                                  TAC,
+//        broadcastPLMNs               BroadcastPLMNs-Item,
+//        eUTRA-Mode-Info              EUTRA-Mode-Info,
+//        iE-Extensions                ProtocolExtensionContainer { {ServedCell-Information-ExtIEs} } OPTIONAL,
+//        ...
+//}
+//
+//ServedCell-Information-ExtIEs X2AP-PROTOCOL-EXTENSION ::= {
+//        { ID id-Number-of-Antennaports                               CRITICALITY ignore      EXTENSION Number-of-Antennaports                                        PRESENCE optional}|
+//        { ID id-PRACH-Configuration                                  CRITICALITY ignore      EXTENSION PRACH-Configuration                                           PRESENCE optional}|
+//        { ID id-MBSFN-Subframe-Info                                  CRITICALITY ignore      EXTENSION MBSFN-Subframe-Infolist                               PRESENCE optional}|
+//        { ID id-CSG-Id                                                               CRITICALITY ignore      EXTENSION CSG-Id                                                                        PRESENCE optional}|
+//        { ID id-MBMS-Service-Area-List                               CRITICALITY ignore      EXTENSION MBMS-Service-Area-Identity-List               PRESENCE optional}|
+//        { ID id-MultibandInfoList                                    CRITICALITY ignore      EXTENSION MultibandInfoList                                                     PRESENCE optional}|
+//        { ID id-FreqBandIndicatorPriority                    CRITICALITY ignore      EXTENSION FreqBandIndicatorPriority                             PRESENCE optional}|
+//        { ID id-BandwidthReducedSI                                   CRITICALITY ignore      EXTENSION BandwidthReducedSI                                            PRESENCE optional}|
+//        { ID id-ProtectedEUTRAResourceIndication     CRITICALITY ignore      EXTENSION ProtectedEUTRAResourceIndication      PRESENCE optional}|
+//        { ID id-BPLMN-ID-Info-EUTRA                                  CRITICALITY ignore      EXTENSION BPLMN-ID-Info-EUTRA                                           PRESENCE optional},
+//        ...
+//}
+
+/**
+ *
+ * @param pci
+ * @param cellId
+ * @param tac
+ * @param broadcastPLMNs
+ * @param eutranModeInfo
+ * @return
+ */
+ServedCell_Information_t *createServedCellInfo(long pci,
+        ECGI_t *cellId,
+        TAC_t *tac,
+        vector<PLMN_Identity_t> &broadcastPLMNs,
+        EUTRA_Mode_Info_t *eutranModeInfo) {
+
+    printEntry("ServedCell_Information_t", __func__)
+    auto servedCellinfo = (ServedCell_Information_t *)calloc(1, sizeof(ServedCell_Information_t));
+    ASN_STRUCT_RESET(asn_DEF_ServedCell_Information, servedCellinfo);
+
+    servedCellinfo->pCI = pci;
+    memcpy(&servedCellinfo->cellId, cellId, sizeof(ECGI_t));
+    memcpy(&servedCellinfo->tAC, tac, sizeof(TAC_t));
+
+    for (auto v : broadcastPLMNs) {
+        ASN_SEQUENCE_ADD(&servedCellinfo->broadcastPLMNs.list, &v);
+    }
+
+    memcpy(&servedCellinfo->eUTRA_Mode_Info, eutranModeInfo, sizeof(EUTRA_Mode_Info_t));
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_ServedCell_Information, servedCellinfo, (char *)"ServedCell_Information_t", __func__);
+    }
+
+    return servedCellinfo;
+}
+
+
+ServedCells__Member *createServedCellsMember(ServedCell_Information_t *servedCellInfo, Neighbour_Information_t *neighbourInformation) {
+    printEntry("ServedCells__Member", __func__)
+    auto servedCellMember = (ServedCells__Member *)calloc(1, sizeof(ServedCells__Member));
+
+    memcpy(&servedCellMember->servedCellInfo, servedCellInfo, sizeof(ServedCell_Information_t));
+    servedCellMember->neighbour_Info = neighbourInformation;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_ServedCells, servedCellMember, (char *)"ServedCells__Member", __func__);
+    }
+
+    return servedCellMember;
+}
+
+void buildServedCells(ServedCells_t *servedCells, ServedCells__Member *member) {
+    ASN_SEQUENCE_ADD(&servedCells->list, member);
+}
+
+
+static void buildInitiatingMessagePDU(E2AP_PDU_t &pdu, InitiatingMessage_t *initMsg) {
+    pdu.present = E2AP_PDU_PR_initiatingMessage;
+    pdu.choice.initiatingMessage = initMsg;
+}
+
+template<typename T>
+static void buildInitMsg(InitiatingMessage_t &initMsg,
+                         InitiatingMessage__value_PR present,
+                         ProcedureCode_t procedureCode,
+                         Criticality_t criticality,
+                         T *value) {
+    initMsg.value.present = present;
+    initMsg.procedureCode = procedureCode;
+    initMsg.criticality = criticality;
+
+    switch (present) {
+        case InitiatingMessage__value_PR_RICsubscriptionRequest: {
+            memcpy(&initMsg.value.choice.RICsubscriptionRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_RICsubscriptionDeleteRequest: {
+            memcpy(&initMsg.value.choice.RICsubscriptionDeleteRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_RICserviceUpdate: {
+            memcpy(&initMsg.value.choice.RICserviceUpdate, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_RICcontrolRequest: {
+            memcpy(&initMsg.value.choice.RICcontrolRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_X2SetupRequest: {
+            memcpy(&initMsg.value.choice.X2SetupRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ENDCX2SetupRequest: {
+            memcpy(&initMsg.value.choice.ENDCX2SetupRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ResourceStatusRequest: {
+            memcpy(&initMsg.value.choice.ResourceStatusRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ENBConfigurationUpdate: {
+            memcpy(&initMsg.value.choice.ENBConfigurationUpdate, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ENDCConfigurationUpdate: {
+            memcpy(&initMsg.value.choice.ENDCConfigurationUpdate, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ResetRequest: {
+            memcpy(&initMsg.value.choice.ResetRequest, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_RICindication: {
+            memcpy(&initMsg.value.choice.RICindication, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_RICserviceQuery: {
+            memcpy(&initMsg.value.choice.RICserviceQuery, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_LoadInformation: {
+            memcpy(&initMsg.value.choice.LoadInformation, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_GNBStatusIndication: {
+            memcpy(&initMsg.value.choice.GNBStatusIndication, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ResourceStatusUpdate: {
+            memcpy(&initMsg.value.choice.ResourceStatusUpdate, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_ErrorIndication: {
+            memcpy(&initMsg.value.choice.ErrorIndication, value, sizeof(*value));
+            break;
+        }
+        case InitiatingMessage__value_PR_NOTHING:
+        default : {
+            break;
+        }
+    }
+}
+
+static void buildSuccsesfulMessagePDU(E2AP_PDU_t &pdu, SuccessfulOutcome_t *succMsg) {
+    pdu.present = E2AP_PDU_PR_successfulOutcome;
+    pdu.choice.successfulOutcome = succMsg;
+}
+
+template<typename T>
+static void buildSuccMsg(SuccessfulOutcome_t &succMsg,
+                         SuccessfulOutcome__value_PR present,
+                         ProcedureCode_t procedureCode,
+                         Criticality_t criticality,
+                         T *value) {
+    succMsg.value.present = present;
+    succMsg.procedureCode = procedureCode;
+    succMsg.criticality = criticality;
+
+    switch (present) {
+        case SuccessfulOutcome__value_PR_RICsubscriptionResponse: {
+            memcpy(&succMsg.value.choice.RICsubscriptionResponse, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_RICsubscriptionDeleteResponse: {
+            memcpy(&succMsg.value.choice.RICsubscriptionDeleteResponse, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_RICserviceUpdateAcknowledge: {
+            memcpy(&succMsg.value.choice.RICserviceUpdateAcknowledge, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_RICcontrolAcknowledge: {
+            memcpy(&succMsg.value.choice.RICcontrolAcknowledge, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_X2SetupResponse: {
+            memcpy(&succMsg.value.choice.X2SetupResponse, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_ENDCX2SetupResponse: {
+            memcpy(&succMsg.value.choice.ENDCX2SetupResponse, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_ResourceStatusResponse: {
+            memcpy(&succMsg.value.choice.ResourceStatusResponse, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_ENBConfigurationUpdateAcknowledge: {
+            memcpy(&succMsg.value.choice.ENBConfigurationUpdateAcknowledge, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_ENDCConfigurationUpdateAcknowledge: {
+            memcpy(&succMsg.value.choice.ENDCConfigurationUpdateAcknowledge, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_ResetResponse: {
+            memcpy(&succMsg.value.choice.ResetResponse, value, sizeof(*value));
+            break;
+        }
+        case SuccessfulOutcome__value_PR_NOTHING:
+        default:
+            break;
+    }
+}
+
+
+static void buildUnSucssesfullMessagePDU(E2AP_PDU_t &pdu, UnsuccessfulOutcome_t *unSuccMsg) {
+    pdu.present = E2AP_PDU_PR_unsuccessfulOutcome;
+    pdu.choice.unsuccessfulOutcome = unSuccMsg;
+}
+
+template<typename T>
+static void buildUnSuccMsg(UnsuccessfulOutcome_t &unSuccMsg,
+                           UnsuccessfulOutcome__value_PR present,
+                           ProcedureCode_t procedureCode,
+                           Criticality_t criticality,
+                           T *value) {
+    unSuccMsg.value.present = present;
+    unSuccMsg.procedureCode = procedureCode;
+    unSuccMsg.criticality = criticality;
+
+    switch (present) {
+        case UnsuccessfulOutcome__value_PR_RICsubscriptionFailure: {
+            memcpy(&unSuccMsg.value.choice.RICsubscriptionFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_RICsubscriptionDeleteFailure: {
+            memcpy(&unSuccMsg.value.choice.RICsubscriptionDeleteFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_RICserviceUpdateFailure: {
+            memcpy(&unSuccMsg.value.choice.RICserviceUpdateFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_RICcontrolFailure: {
+            memcpy(&unSuccMsg.value.choice.RICcontrolFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_X2SetupFailure: {
+            memcpy(&unSuccMsg.value.choice.X2SetupFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_ENDCX2SetupFailure: {
+            memcpy(&unSuccMsg.value.choice.ENDCX2SetupFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_ResourceStatusFailure: {
+            memcpy(&unSuccMsg.value.choice.ResourceStatusFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_ENBConfigurationUpdateFailure: {
+            memcpy(&unSuccMsg.value.choice.ENBConfigurationUpdateFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_ENDCConfigurationUpdateFailure: {
+            memcpy(&unSuccMsg.value.choice.ENDCConfigurationUpdateFailure, value, sizeof(*value));
+            break;
+        }
+        case UnsuccessfulOutcome__value_PR_NOTHING:
+        default:
+            break;
+    }
+}
+
+
+static void createPLMN_ID(PLMN_Identity_t &plmnId, const unsigned char *data) {
+    //printEntry("PLMN_Identity_t", __func__)
+    //PLMN_Identity_t *plmnId = calloc(1, sizeof(PLMN_Identity_t));
+    ASN_STRUCT_RESET(asn_DEF_PLMN_Identity, &plmnId);
+    plmnId.size = 3;
+    plmnId.buf = (uint8_t *) calloc(1, 3);
+    memcpy(plmnId.buf, data, 3);
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_PLMN_Identity, &plmnId, (char *) "PLMN_Identity_t", __func__);
+    }
+
+}
+
+static void createENB_ID(ENB_ID_t &enb, ENB_ID_PR enbType, unsigned char *data) {
+    //printEntry("ENB_ID_t", __func__)
+    ASN_STRUCT_RESET(asn_DEF_ENB_ID, &enb);
+    enb.present = enbType;
+    switch (enbType) {
+        case ENB_ID_PR_macro_eNB_ID: { // 20 bit 3 bytes
+            enb.choice.macro_eNB_ID.size = 3;
+            enb.choice.macro_eNB_ID.bits_unused = 4;
+
+            enb.present = ENB_ID_PR_macro_eNB_ID;
+
+            enb.choice.macro_eNB_ID.buf = (uint8_t *) calloc(1, enb.choice.macro_eNB_ID.size);
+            data[enb.choice.macro_eNB_ID.size - 1] = ((unsigned) (data[enb.choice.macro_eNB_ID.size - 1]
+                    >> (unsigned) enb.choice.macro_eNB_ID.bits_unused)
+                    << (unsigned) enb.choice.macro_eNB_ID.bits_unused);
+            memcpy(enb.choice.macro_eNB_ID.buf, data, enb.choice.macro_eNB_ID.size);
+
+            break;
+        }
+        case ENB_ID_PR_home_eNB_ID: { // 28 bit 4 bytes
+            enb.choice.home_eNB_ID.size = 4;
+            enb.choice.home_eNB_ID.bits_unused = 4;
+            enb.present = ENB_ID_PR_home_eNB_ID;
+
+            enb.choice.home_eNB_ID.buf = (uint8_t *) calloc(1, enb.choice.home_eNB_ID.size);
+            data[enb.choice.home_eNB_ID.size - 1] = ((unsigned) (data[enb.choice.home_eNB_ID.size - 1]
+                    >> (unsigned) enb.choice.home_eNB_ID.bits_unused)
+                    << (unsigned) enb.choice.home_eNB_ID.bits_unused);
+            memcpy(enb.choice.home_eNB_ID.buf, data, enb.choice.home_eNB_ID.size);
+            break;
+        }
+        case ENB_ID_PR_short_Macro_eNB_ID: { // 18 bit - 3 bytes
+            enb.choice.short_Macro_eNB_ID.size = 3;
+            enb.choice.short_Macro_eNB_ID.bits_unused = 6;
+            enb.present = ENB_ID_PR_short_Macro_eNB_ID;
+
+            enb.choice.short_Macro_eNB_ID.buf = (uint8_t *) calloc(1, enb.choice.short_Macro_eNB_ID.size);
+            data[enb.choice.short_Macro_eNB_ID.size - 1] = ((unsigned) (data[enb.choice.short_Macro_eNB_ID.size - 1]
+                    >> (unsigned) enb.choice.short_Macro_eNB_ID.bits_unused)
+                    << (unsigned) enb.choice.short_Macro_eNB_ID.bits_unused);
+            memcpy(enb.choice.short_Macro_eNB_ID.buf, data, enb.choice.short_Macro_eNB_ID.size);
+            break;
+        }
+        case ENB_ID_PR_long_Macro_eNB_ID: { // 21
+            enb.choice.long_Macro_eNB_ID.size = 3;
+            enb.choice.long_Macro_eNB_ID.bits_unused = 3;
+            enb.present = ENB_ID_PR_long_Macro_eNB_ID;
+
+            enb.choice.long_Macro_eNB_ID.buf = (uint8_t *) calloc(1, enb.choice.long_Macro_eNB_ID.size);
+            data[enb.choice.long_Macro_eNB_ID.size - 1] = ((unsigned) (data[enb.choice.long_Macro_eNB_ID.size - 1]
+                    >> (unsigned) enb.choice.long_Macro_eNB_ID.bits_unused)
+                    << (unsigned) enb.choice.long_Macro_eNB_ID.bits_unused);
+            memcpy(enb.choice.long_Macro_eNB_ID.buf, data, enb.choice.long_Macro_eNB_ID.size);
+            break;
+        }
+        default:
+            break;
+    }
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_ENB_ID, &enb, (char *) "ENB_ID_t", __func__);
+    }
+}
+
+
+static void buildGlobalENB_ID(GlobalENB_ID_t *gnbId,
+                              const unsigned char *gnbData,
+                              ENB_ID_PR enbType,
+                              unsigned char *enbData) {
+    createPLMN_ID(gnbId->pLMN_Identity, gnbData);
+    createENB_ID(gnbId->eNB_ID, enbType, enbData);
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        checkAndPrint(&asn_DEF_GlobalENB_ID, gnbId, (char *) "GlobalENB_ID_t", __func__);
+    }
+}
+
+#endif //E2_E2BUILDER_H
diff --git a/RIC-E2-TERMINATION/TEST/T1/E2Setup.cpp b/RIC-E2-TERMINATION/TEST/T1/E2Setup.cpp
new file mode 100644 (file)
index 0000000..efc3bd3
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 12/10/19.
+//
+
+#include "E2Builder.h"
+
+#include "asn1cFiles/ProtocolIE-Field.h"
+
+template<typename T>
+X2SetupRequest_IEs_t *buildX2SetupIE(ProtocolIE_ID_t id,
+        Criticality_t criticality,
+        X2SetupRequest_IEs__value_PR present,
+        T *value) {
+    auto *x2SetupIE = (X2SetupRequest_IEs_t *)calloc(1, sizeof(X2SetupRequest_IEs_t));
+    x2SetupIE->id = id;
+    x2SetupIE->criticality = criticality;
+    x2SetupIE->value.present = present;
+
+    switch (present) {
+        case X2SetupRequest_IEs__value_PR_GlobalENB_ID: {
+            memcpy(&x2SetupIE->value.choice.GlobalENB_ID, value, sizeof(GlobalENB_ID_t));
+            break;
+        }
+        case X2SetupRequest_IEs__value_PR_ServedCells: {
+            memcpy(&x2SetupIE->value.choice.ServedCells, value, sizeof(ServedCells_t));
+            break;
+        }
+        case X2SetupRequest_IEs__value_PR_GUGroupIDList: {
+            memcpy(&x2SetupIE->value.choice.GUGroupIDList, value, sizeof(GUGroupIDList_t));
+            break;
+        }
+        case X2SetupRequest_IEs__value_PR_LHN_ID: {
+            memcpy(&x2SetupIE->value.choice.LHN_ID, value, sizeof(LHN_ID_t));
+            break;
+        }
+        case X2SetupRequest_IEs__value_PR_NOTHING:
+        default:
+            free(x2SetupIE);
+            x2SetupIE = nullptr;
+            break;
+    }
+    return x2SetupIE;
+}
+
+/**
+ *
+ * @param x2Setup
+ * @param member
+ */
+void buildE2SetupRequest(X2SetupRequest_t *x2Setup, vector<X2SetupRequest_IEs_t> &member) {
+    for (auto v : member) {
+        ASN_SEQUENCE_ADD(&x2Setup->protocolIEs.list, &v);
+    }
+}
+
+void init_log() {
+    mdclog_attr_t *attr;
+    mdclog_attr_init(&attr);
+    mdclog_attr_set_ident(attr, "setup Request");
+    mdclog_init(attr);
+    mdclog_attr_destroy(attr);
+}
+
+int main(const int argc, char **argv) {
+    init_log();
+    //mdclog_level_set(MDCLOG_WARN);
+    //mdclog_level_set(MDCLOG_INFO);
+    mdclog_level_set(MDCLOG_DEBUG);
+
+//    x2Setup  X2AP-ELEMENTARY-PROCEDURE ::= {
+//            INITIATING MESSAGE               X2SetupRequest
+//            SUCCESSFUL OUTCOME               X2SetupResponse
+//            UNSUCCESSFUL OUTCOME     X2SetupFailure
+//            PROCEDURE CODE                   id-x2Setup
+//            CRITICALITY                              reject
+//    }
+//
+//
+
+//    X2SetupRequest ::= SEQUENCE {
+//            protocolIEs              ProtocolIE-Container    {{X2SetupRequest-IEs}},
+//            ...
+//    }
+//
+//    X2SetupRequest-IEs X2AP-PROTOCOL-IES ::= {
+//            { ID id-GlobalENB-ID                     CRITICALITY reject      TYPE GlobalENB-ID                       PRESENCE mandatory}|
+//            { ID id-ServedCells                              CRITICALITY reject      TYPE ServedCells                        PRESENCE mandatory}|
+//            { ID id-GUGroupIDList                    CRITICALITY reject      TYPE GUGroupIDList                      PRESENCE optional}|
+//            { ID id-LHN-ID                                   CRITICALITY ignore      TYPE LHN-ID                                     PRESENCE optional},
+//            ...
+//    }
+
+
+
+}
\ No newline at end of file
index 2ba5fed..fa20111 100644 (file)
 
 #include <mdclog/mdclog.h>
 
-#include "asn/type_defs.h"
-#include "asn/per/codec.hpp"
-#include "asn/printer.hpp"
+#include "asn1cFiles/E2AP-PDU.h"
+#include "asn1cFiles/InitiatingMessage.h"
+
 
-#include "X2AP-CommonDataTypes.hpp"
-#include "X2AP-Containers.hpp"
-#include "X2AP-Constants.hpp"
-#include "X2AP-IEs.hpp"
-#include "X2AP-PDU-Contents.hpp"
 
-#include "E2AP-Constants.hpp"
-#include "E2AP-IEs.hpp"
-#include "E2AP-PDU-Contents.hpp"
-#include "E2AP-PDU-Descriptions.hpp"
 
 #include <iostream>
 #include <cstdio>
 #include <cctype>
 #include <cstring>
+#include <unistd.h>
 
 #include <pthread.h>
 #include <rmr/rmr.h>
@@ -156,7 +148,7 @@ int main(const int argc, char **argv) {
         mdclog_write(MDCLOG_INFO, "RMR running");
     }
 
-    E2AP_PDU pdu {};
+    E2AP_PDU_t pdu {};
     auto &initiatingMsg = pdu.select_initiatingMessage();
     initiatingMsg.ref_procedureCode().select_id_x2Setup();
     initiatingMsg.ref_criticality().select_id_x2Setup();
diff --git a/RIC-E2-TERMINATION/TEST/base64/testBase64.cpp b/RIC-E2-TERMINATION/TEST/base64/testBase64.cpp
new file mode 100644 (file)
index 0000000..e30dca9
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+
+//
+// Created by adi ENZEL on 11/27/19.
+//
+
+#include "base64.h"
+#include <mdclog/mdclog.h>
+#include <cgreen/cgreen.h>
+#include <cstdio>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+
+using namespace std;
+
+Describe(base64);
+BeforeEach(base64) {}
+AfterEach(base64) {}
+
+using namespace cgreen;
+
+void init_log() {
+    mdclog_attr_t *attr;
+    mdclog_attr_init(&attr);
+    mdclog_attr_set_ident(attr, "TestConfiguration");
+    mdclog_init(attr);
+    mdclog_attr_destroy(attr);
+}
+
+const char *data = "ABC123Test Lets Try this' input and see What \"happens\"";
+
+Ensure(base64, encDec) {
+    string str = "ABC123Test Lets Try this' input and see What \"happens\"";
+    auto *buf = (unsigned char *)malloc(str.length() * 2);
+    auto length = (long)(str.length() * 2);
+    base64::encode((unsigned char *)str.c_str(), str.length(), buf, length);
+    auto *backBackBuff = (unsigned char *)malloc(length);
+    auto length2 = length;
+    assert_that(base64::decode(buf, length, backBackBuff, length2) == 0);
+    std::string str1( backBackBuff, backBackBuff + sizeof backBackBuff / sizeof backBackBuff[0]);
+
+    assert_that(str.length() == (ulong)length2)
+    //auto val = str.compare((const char *)backBackBuff);
+    assert_that(str.compare((const char *)backBackBuff) == 0)
+    free(backBackBuff);
+    free(buf);
+}
+
+Ensure(base64, errorsHandling) {
+    string str = "ABC123Test Lets Try this' input and see What \"happens\"";
+    auto *buf = (unsigned char *)malloc(str.length() * 2);
+    auto length = (long)(str.length());
+    assert_that(base64::encode((unsigned char *)str.c_str(), str.length(), buf, length) == -1);
+    length = (long)(str.length() * 2);
+    assert_that(base64::encode((unsigned char *)str.c_str(), str.length(), buf, length) == 0);
+    auto *backBackBuff = (unsigned char *)malloc(length);
+    auto length2 = length >> 2;
+    assert_that(base64::decode(buf, length, backBackBuff, length2) == -1);
+    //std::string str1( backBackBuff, backBackBuff + sizeof backBackBuff / sizeof backBackBuff[0]);
+    auto length1 = 0l;
+    assert_that(base64::encode((unsigned char *)str.c_str(), str.length(), nullptr , length) == -1);
+//    assert_that(base64::encode((unsigned char *)str.c_str(), str.length(), nullptr , length) == -1);
+    assert_that(base64::encode(nullptr, str.length(), backBackBuff , length) == -1);
+    assert_that(base64::encode((unsigned char *)str.c_str(), length1, backBackBuff , length) == -1);
+    assert_that(base64::encode(nullptr, str.length(), backBackBuff , length1) == -1);
+    length1 = -1;
+    assert_that(base64::encode((unsigned char *)str.c_str(), length1, backBackBuff , length) == -1);
+    assert_that(base64::encode(nullptr, str.length(), backBackBuff , length1) == -1);
+
+}
+
+
+int main(const int argc, char **argv) {
+    mdclog_severity_t loglevel = MDCLOG_INFO;
+    init_log();
+    mdclog_level_set(loglevel);
+
+    //TestSuite *suite = create_test_suite();
+    TestSuite *suite = create_named_test_suite_(__FUNCTION__, __FILE__, __LINE__);
+
+    add_test_with_context(suite, base64, encDec);
+    add_test_with_context(suite, base64, errorsHandling);
+
+    return cgreen::run_test_suite(suite, create_text_reporter());
+
+}
\ No newline at end of file
index 9915948..12d6097 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
+ /*
  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
  * platform project (RICP).
  */
 
-
 //
 // Created by adi ENZEL on 6/19/19.
 //
@@ -56,7 +55,7 @@ static size_t encodebuff(int codingType,
     clock_gettime(CLOCK_MONOTONIC, &end);
     if (er.encoded == -1) {
         mdclog_write(MDCLOG_ERR, "encoding of %s failed, %s", asn_DEF_E2SM_gNB_X2_eventTriggerDefinition.name, strerror(errno));
-    } else if (er.encoded > buffer_size) {
+    } else if (er.encoded > (ssize_t)buffer_size) {
         mdclog_write(MDCLOG_ERR, "Buffer of size %d is to small for %s", (int) buffer_size,
                      typeDescriptor->name);
     } else if (mdclog_level_get() >= MDCLOG_DEBUG) {
@@ -82,7 +81,7 @@ static size_t encodebuff(int codingType,
 }
 
 PLMN_Identity_t *createPLMN_ID(const unsigned char *data) {
-    printEntry("PLMN_Identity_t", __func__);
+    printEntry("PLMN_Identity_t", __func__)
     PLMN_Identity_t *plmnId = calloc(1, sizeof(PLMN_Identity_t));
     ASN_STRUCT_RESET(asn_DEF_PLMN_Identity, plmnId);
     plmnId->size = 3;
@@ -97,9 +96,12 @@ PLMN_Identity_t *createPLMN_ID(const unsigned char *data) {
 }
 
 ENB_ID_t *createENB_ID(ENB_ID_PR enbType, unsigned char *data) {
-    printEntry("ENB_ID_t", __func__);
+    printEntry("ENB_ID_t", __func__)
     ENB_ID_t *enb = calloc(1, sizeof(ENB_ID_t));
     ASN_STRUCT_RESET(asn_DEF_ENB_ID, enb);
+
+    enb->present = enbType;
+
     switch (enbType) {
         case ENB_ID_PR_macro_eNB_ID: { // 20 bit 3 bytes
             enb->choice.macro_eNB_ID.size = 3;
@@ -160,7 +162,7 @@ ENB_ID_t *createENB_ID(ENB_ID_PR enbType, unsigned char *data) {
 }
 
 GNB_ID_t *createGnb_id(const unsigned char *data, int numOfBits) {
-    printEntry("GNB_ID_t", __func__);
+    printEntry("GNB_ID_t", __func__)
     if (numOfBits < 22 || numOfBits > 32) {
         mdclog_write(MDCLOG_ERR, "GNB_ID_t number of bits = %d, needs to be 22 .. 32", numOfBits);
         return NULL;
@@ -170,7 +172,7 @@ GNB_ID_t *createGnb_id(const unsigned char *data, int numOfBits) {
 
     gnb->present = GNB_ID_PR_gNB_ID;
     gnb->choice.gNB_ID.size = numOfBits % 8 == 0 ? (unsigned int)(numOfBits / 8) : (unsigned int)(numOfBits / 8 + 1);
-    gnb->choice.gNB_ID.bits_unused = gnb->choice.gNB_ID.size * 8 - numOfBits;
+    gnb->choice.gNB_ID.bits_unused = (int)gnb->choice.gNB_ID.size * 8 - numOfBits;
     gnb->choice.gNB_ID.buf = calloc(1, gnb->choice.gNB_ID.size);
     memcpy(gnb->choice.gNB_ID.buf, data, gnb->choice.gNB_ID.size);
     gnb->choice.gNB_ID.buf[gnb->choice.gNB_ID.size - 1] =
@@ -186,7 +188,7 @@ GNB_ID_t *createGnb_id(const unsigned char *data, int numOfBits) {
 }
 
 GlobalENB_ID_t *createGlobalENB_ID(PLMN_Identity_t *plmnIdentity, ENB_ID_t *enbId) {
-    printEntry("GlobalENB_ID_t", __func__);
+    printEntry("GlobalENB_ID_t", __func__)
     GlobalENB_ID_t *genbId = calloc(1, sizeof(GlobalENB_ID_t));
     ASN_STRUCT_RESET(asn_DEF_GlobalENB_ID, genbId);
     memcpy(&genbId->pLMN_Identity, plmnIdentity, sizeof(PLMN_Identity_t));
@@ -199,7 +201,7 @@ GlobalENB_ID_t *createGlobalENB_ID(PLMN_Identity_t *plmnIdentity, ENB_ID_t *enbI
 }
 
 GlobalGNB_ID_t *createGlobalGNB_ID(PLMN_Identity_t *plmnIdentity, GNB_ID_t *gnb) {
-    printEntry("GlobalGNB_ID_t", __func__);
+    printEntry("GlobalGNB_ID_t", __func__)
     GlobalGNB_ID_t *ggnbId = calloc(1, sizeof(GlobalGNB_ID_t));
     ASN_STRUCT_RESET(asn_DEF_GlobalGNB_ID, ggnbId);
 
@@ -215,7 +217,7 @@ GlobalGNB_ID_t *createGlobalGNB_ID(PLMN_Identity_t *plmnIdentity, GNB_ID_t *gnb)
 
 
 Interface_ID_t *createInterfaceIDForGnb(GlobalGNB_ID_t *gnb) {
-    printEntry("Interface_ID_t", __func__);
+    printEntry("Interface_ID_t", __func__)
     Interface_ID_t *interfaceId = calloc(1, sizeof(Interface_ID_t));
     ASN_STRUCT_RESET(asn_DEF_Interface_ID, interfaceId);
 
@@ -231,7 +233,7 @@ Interface_ID_t *createInterfaceIDForGnb(GlobalGNB_ID_t *gnb) {
 }
 
 Interface_ID_t *createInterfaceIDForEnb(GlobalENB_ID_t *enb) {
-    printEntry("Interface_ID_t", __func__);
+    printEntry("Interface_ID_t", __func__)
     Interface_ID_t *interfaceId = calloc(1, sizeof(Interface_ID_t));
     ASN_STRUCT_RESET(asn_DEF_Interface_ID, interfaceId);
 
@@ -249,7 +251,7 @@ Interface_ID_t *createInterfaceIDForEnb(GlobalENB_ID_t *enb) {
 
 
 InterfaceMessageType_t *createInterfaceMessageInitiating(long procedureCode) {
-    printEntry("InterfaceMessageType_t", __func__);
+    printEntry("InterfaceMessageType_t", __func__)
     InterfaceMessageType_t *intMsgT = calloc(1, sizeof(InterfaceMessageType_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceMessageType, intMsgT);
 
@@ -264,7 +266,7 @@ InterfaceMessageType_t *createInterfaceMessageInitiating(long procedureCode) {
 }
 
 InterfaceMessageType_t *createInterfaceMessageSuccsesful(long procedureCode) {
-    printEntry("InterfaceMessageType_t", __func__);
+    printEntry("InterfaceMessageType_t", __func__)
     InterfaceMessageType_t *intMsgT = calloc(1, sizeof(InterfaceMessageType_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceMessageType, intMsgT);
 
@@ -279,7 +281,7 @@ InterfaceMessageType_t *createInterfaceMessageSuccsesful(long procedureCode) {
 }
 
 InterfaceMessageType_t *createInterfaceMessageUnsuccessful(long procedureCode) {
-    printEntry("InterfaceMessageType_t", __func__);
+    printEntry("InterfaceMessageType_t", __func__)
     InterfaceMessageType_t *intMsgT = calloc(1, sizeof(InterfaceMessageType_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceMessageType, intMsgT);
 
@@ -294,7 +296,7 @@ InterfaceMessageType_t *createInterfaceMessageUnsuccessful(long procedureCode) {
 }
 
 InterfaceProtocolIE_Value_t *createInterfaceProtocolValueInt(long number) {
-    printEntry("InterfaceProtocolIE_Value_t", __func__);
+    printEntry("InterfaceProtocolIE_Value_t", __func__)
     InterfaceProtocolIE_Value_t *value = calloc(1, sizeof(InterfaceProtocolIE_Value_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceProtocolIE_Value, value);
 
@@ -309,7 +311,7 @@ InterfaceProtocolIE_Value_t *createInterfaceProtocolValueInt(long number) {
 }
 
 InterfaceProtocolIE_Value_t *createInterfaceProtocolValueEnum(long number) {
-    printEntry("InterfaceProtocolIE_Value_t", __func__);
+    printEntry("InterfaceProtocolIE_Value_t", __func__)
     InterfaceProtocolIE_Value_t *value = calloc(1, sizeof(InterfaceProtocolIE_Value_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceProtocolIE_Value, value);
 
@@ -324,7 +326,7 @@ InterfaceProtocolIE_Value_t *createInterfaceProtocolValueEnum(long number) {
 }
 
 InterfaceProtocolIE_Value_t *createInterfaceProtocolValueBool(int val) {
-    printEntry("InterfaceProtocolIE_Value_t", __func__);
+    printEntry("InterfaceProtocolIE_Value_t", __func__)
     InterfaceProtocolIE_Value_t *value = calloc(1, sizeof(InterfaceProtocolIE_Value_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceProtocolIE_Value, value);
 
@@ -340,7 +342,7 @@ InterfaceProtocolIE_Value_t *createInterfaceProtocolValueBool(int val) {
 
 
 InterfaceProtocolIE_Value_t *createInterfaceProtocolValueBitString(unsigned char *buf, int numOfBits) {
-    printEntry("InterfaceProtocolIE_Value_t", __func__);
+    printEntry("InterfaceProtocolIE_Value_t", __func__)
     size_t size = numOfBits % 8 == 0 ? (unsigned int)(numOfBits / 8) : (unsigned int)(numOfBits / 8 + 1);
     if (strlen((const char *)buf) < size) {
         mdclog_write(MDCLOG_ERR, "size of buffer is small : %d needs to be %d in %s", (int)strlen((const char *)buf), (int)size, __func__);
@@ -351,7 +353,7 @@ InterfaceProtocolIE_Value_t *createInterfaceProtocolValueBitString(unsigned char
     value->present = InterfaceProtocolIE_Value_PR_valueBitS;
     value->choice.valueBitS.size = numOfBits % 8 == 0 ? (unsigned int)(numOfBits / 8) : (unsigned int)(numOfBits / 8 + 1);
     value->choice.valueBitS.buf = calloc(1, value->choice.valueBitS.size);
-    int bits_unused = value->choice.valueBitS.size * 8 - numOfBits;
+    int bits_unused = (int)value->choice.valueBitS.size * 8 - numOfBits;
     value->choice.valueBitS.bits_unused = bits_unused;
 
     memcpy(value->choice.valueBitS.buf, buf, value->choice.valueBitS.size);
@@ -366,7 +368,7 @@ InterfaceProtocolIE_Value_t *createInterfaceProtocolValueBitString(unsigned char
 
 
 InterfaceProtocolIE_Value_t *createInterfaceProtocolValueOCTETS(uint8_t *buf) {
-    printEntry("InterfaceProtocolIE_Value_t", __func__);
+    printEntry("InterfaceProtocolIE_Value_t", __func__)
     size_t size = strlen((const char *)buf);
     InterfaceProtocolIE_Value_t *value = calloc(1, sizeof(InterfaceProtocolIE_Value_t));
     ASN_STRUCT_RESET(asn_DEF_InterfaceProtocolIE_Value, value);
@@ -385,7 +387,7 @@ InterfaceProtocolIE_Value_t *createInterfaceProtocolValueOCTETS(uint8_t *buf) {
 
 
 InterfaceProtocolIE_Item_t *createInterfaceProtocolIE_Item(long id, long test, InterfaceProtocolIE_Value_t *value) {
-    printEntry("InterfaceProtocolIE_Item_t", __func__);
+    printEntry("InterfaceProtocolIE_Item_t", __func__)
     if (test < InterfaceProtocolIE_Test_equal || test > InterfaceProtocolIE_Test_present) {
         mdclog_write(MDCLOG_ERR, "InterfaceProtocolIE_Item_t test value is %ld,  out of scope %d .. %d ",
                 test, InterfaceProtocolIE_Test_equal, InterfaceProtocolIE_Test_present);
@@ -412,7 +414,7 @@ InterfaceProtocolIE_Item_t *createInterfaceProtocolIE_Item(long id, long test, I
 
 
 ActionParameter_Value_t *createActionParameterValue_Int(long number) {
-    printEntry("ActionParameter_Value_t", __func__);
+    printEntry("ActionParameter_Value_t", __func__)
     ActionParameter_Value_t *value = calloc(1, sizeof(ActionParameter_Value_t));
     ASN_STRUCT_RESET(asn_DEF_ActionParameter_Value, value);
 
@@ -427,7 +429,7 @@ ActionParameter_Value_t *createActionParameterValue_Int(long number) {
 }
 
 ActionParameter_Value_t *createActionParameterValue_Enum(long number) {
-    printEntry("ActionParameter_Value_t", __func__);
+    printEntry("ActionParameter_Value_t", __func__)
     ActionParameter_Value_t *value = calloc(1, sizeof(ActionParameter_Value_t));
     ASN_STRUCT_RESET(asn_DEF_ActionParameter_Value, value);
 
@@ -442,7 +444,7 @@ ActionParameter_Value_t *createActionParameterValue_Enum(long number) {
 }
 
 ActionParameter_Value_t *createActionParameterValue_Bool(int val) {
-    printEntry("ActionParameter_Value_t", __func__);
+    printEntry("ActionParameter_Value_t", __func__)
     ActionParameter_Value_t *value = calloc(1, sizeof(ActionParameter_Value_t));
     ASN_STRUCT_RESET(asn_DEF_ActionParameter_Value, value);
 
@@ -458,12 +460,12 @@ ActionParameter_Value_t *createActionParameterValue_Bool(int val) {
 
 
 ActionParameter_Value_t *createActionParameterValue_Bit_String(unsigned char *buf, int numOfBits) {
-    printEntry("ActionParameter_Value_t", __func__);
+    printEntry("ActionParameter_Value_t", __func__)
     size_t size = numOfBits % 8 == 0 ? (unsigned int)(numOfBits / 8) : (unsigned int)(numOfBits / 8 + 1);
     if (strlen((const char *)buf) < size) {
         mdclog_write(MDCLOG_ERR, "size of buffer is small : %d needs to be %d in %s", (int)strlen((const char *)buf), (int)size, __func__);
     }
-    int bits_unused = size * 8 - numOfBits;
+    int bits_unused = (int)size * 8 - numOfBits;
 
     ActionParameter_Value_t *value = calloc(1, sizeof(ActionParameter_Value_t));
     ASN_STRUCT_RESET(asn_DEF_ActionParameter_Value, value);
@@ -485,7 +487,7 @@ ActionParameter_Value_t *createActionParameterValue_Bit_String(unsigned char *bu
 
 
 ActionParameter_Value_t *createActionParameterValue_OCTETS(uint8_t *buf) {
-    printEntry("ActionParameter_Value_t", __func__);
+    printEntry("ActionParameter_Value_t", __func__)
     size_t size = strlen((const char *)buf);
     ActionParameter_Value_t *value = calloc(1, sizeof(ActionParameter_Value_t));
     ASN_STRUCT_RESET(asn_DEF_ActionParameter_Value, value);
@@ -508,7 +510,7 @@ ActionParameter_Value_t *createActionParameterValue_OCTETS(uint8_t *buf) {
  * @return ActionParameter_Value_t *
  */
 ActionParameter_Value_t *createActionParameterValue_PRINTS(char *buf) {
-    printEntry("ActionParameter_Value_t", __func__);
+    printEntry("ActionParameter_Value_t", __func__)
     size_t size = strlen((const char *)buf);
     ActionParameter_Value_t *value = calloc(1, sizeof(ActionParameter_Value_t));
     ASN_STRUCT_RESET(asn_DEF_ActionParameter_Value, value);
@@ -526,7 +528,7 @@ ActionParameter_Value_t *createActionParameterValue_PRINTS(char *buf) {
 }
 
 ActionParameter_Item_t *creatActionParameter_Item(long id, ActionParameter_Value_t *val) {
-    printEntry("ActionParameter_Item_t", __func__);
+    printEntry("ActionParameter_Item_t", __func__)
     if (id < 0 || id > 255) {
         mdclog_write(MDCLOG_ERR, "ActionParameter_Item_t id = %ld, values are 0 .. 255", id);
         return NULL;
@@ -561,7 +563,7 @@ size_t createEventTrigger(Interface_ID_t *interfaceId, long direction,
                           int listSize,
                           uint8_t *buffer,
                           size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_eventTriggerDefinition_t", __func__);
+    printEntry("E2SM_gNB_X2_eventTriggerDefinition_t", __func__)
     if (direction < InterfaceDirection_incoming || direction > InterfaceDirection_outgoing) {
         mdclog_write(MDCLOG_ERR, "E2SM_gNB_X2_eventTriggerDefinition_t direction = %ld, values are %d .. %d",
                      direction, InterfaceDirection_incoming, InterfaceDirection_outgoing);
@@ -592,7 +594,7 @@ size_t createEventTrigger(Interface_ID_t *interfaceId, long direction,
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_eventTriggerDefinition,
                                  eventTrigger,
                                  buf1,
@@ -607,7 +609,7 @@ size_t createEventTrigger(Interface_ID_t *interfaceId, long direction,
 size_t createActionDefinition(long styleId, ActionParameter_Item_t actionParamList[], int listSize,
                                                        uint8_t *buffer,
                                                        size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_actionDefinition_t", __func__);
+    printEntry("E2SM_gNB_X2_actionDefinition_t", __func__)
     E2SM_gNB_X2_actionDefinition_t *actDef = calloc(1, sizeof(E2SM_gNB_X2_actionDefinition_t));
     ASN_STRUCT_RESET(asn_DEF_E2SM_gNB_X2_actionDefinition, actDef);
 
@@ -628,7 +630,7 @@ size_t createActionDefinition(long styleId, ActionParameter_Item_t actionParamLi
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_actionDefinition,
                    actDef,
                    buf1,
@@ -645,7 +647,7 @@ size_t createE2SM_gNB_X2_indicationHeader(long direction,
                                           int size,
                                           uint8_t *buffer,
                                           size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_indicationHeader_t", __func__);
+    printEntry("E2SM_gNB_X2_indicationHeader_t", __func__)
     if (direction < InterfaceDirection_incoming || direction > InterfaceDirection_outgoing) {
         mdclog_write(MDCLOG_ERR, "E2SM_gNB_X2_indicationHeader_t direction = %ld, values are %d .. %d",
                      direction, InterfaceDirection_incoming, InterfaceDirection_outgoing);
@@ -674,7 +676,7 @@ size_t createE2SM_gNB_X2_indicationHeader(long direction,
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_indicationHeader,
                    indiHead,
                    buf1,
@@ -688,7 +690,7 @@ size_t createE2SM_gNB_X2_indicationHeader(long direction,
 size_t createE2SM_gNB_X2_indicationMessage(uint8_t *message, uint msgSize,
                                                                      uint8_t *buffer,
                                                                      size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_indicationMessage_t", __func__);
+    printEntry("E2SM_gNB_X2_indicationMessage_t", __func__)
     if (msgSize <= 0) {
         mdclog_write(MDCLOG_ERR, "E2SM_gNB_X2_indicationMessage_t failed messsage size =  %d", msgSize);
         return -1;
@@ -713,7 +715,7 @@ size_t createE2SM_gNB_X2_indicationMessage(uint8_t *message, uint msgSize,
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_indicationMessage,
                    indicationMessage,
                    buf1,
@@ -728,7 +730,7 @@ size_t createE2SM_gNB_X2_indicationMessage(uint8_t *message, uint msgSize,
 size_t createE2SM_gNB_X2_callProcessID(long callProcess_Id,
                                                              uint8_t *buffer,
                                                              size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_callProcessID_t", __func__);
+    printEntry("E2SM_gNB_X2_callProcessID_t", __func__)
     E2SM_gNB_X2_callProcessID_t *callProcessId = calloc(1, sizeof(E2SM_gNB_X2_callProcessID_t));
     ASN_STRUCT_RESET(asn_DEF_E2SM_gNB_X2_callProcessID, callProcessId);
 
@@ -746,7 +748,7 @@ size_t createE2SM_gNB_X2_callProcessID(long callProcess_Id,
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_callProcessID,
                    callProcessId,
                    buf1,
@@ -760,7 +762,7 @@ size_t createE2SM_gNB_X2_callProcessID(long callProcess_Id,
 size_t createE2SM_gNB_X2_controlHeader(Interface_ID_t *interfaceId, long direction,
                                                              uint8_t *buffer,
                                                              size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_controlHeader_t", __func__);
+    printEntry("E2SM_gNB_X2_controlHeader_t", __func__)
     if (direction < InterfaceDirection_incoming || direction > InterfaceDirection_outgoing) {
         mdclog_write(MDCLOG_ERR, "E2SM_gNB_X2_controlHeader_t direction = %ld, values are %d .. %d",
                      direction, InterfaceDirection_incoming, InterfaceDirection_outgoing);
@@ -784,7 +786,7 @@ size_t createE2SM_gNB_X2_controlHeader(Interface_ID_t *interfaceId, long directi
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_controlHeader,
                    controlHeader,
                    buf1,
@@ -799,7 +801,7 @@ size_t createE2SM_gNB_X2_controlHeader(Interface_ID_t *interfaceId, long directi
 size_t createE2SM_gNB_X2_controlMessage(uint8_t *message, uint msgSize,
                                                                uint8_t *buffer,
                                                                size_t buffer_size) {
-    printEntry("E2SM_gNB_X2_controlMessage_t", __func__);
+    printEntry("E2SM_gNB_X2_controlMessage_t", __func__)
     E2SM_gNB_X2_controlMessage_t *controlMsg = calloc(1, sizeof(E2SM_gNB_X2_controlMessage_t));
     ASN_STRUCT_RESET(asn_DEF_E2SM_gNB_X2_controlMessage, controlMsg);
 
@@ -819,7 +821,7 @@ size_t createE2SM_gNB_X2_controlMessage(uint8_t *message, uint msgSize,
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
         uint8_t buf1[4096];
-        asn_enc_rval_t er1;
+        //asn_enc_rval_t er1;
         encodebuff(ATS_BASIC_XER, &asn_DEF_E2SM_gNB_X2_controlMessage,
                    controlMsg,
                    buf1,
@@ -828,4 +830,4 @@ size_t createE2SM_gNB_X2_controlMessage(uint8_t *message, uint msgSize,
     }
 
     return len;
-}
\ No newline at end of file
+}
index 6cc3729..7cbc24d 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
+ /*
  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
  * platform project (RICP).
  */
 
-
 //
 // Created by adi ENZEL on 6/19/19.
 //
@@ -49,26 +48,26 @@ extern "C"
 #include <math.h>
 
 
-#include "../asn1cFiles/ENB-ID.h"
+#include "asn1cFiles/ENB-ID.h"
 
-#include "../asn1cFiles/E2SM-gNB-X2-actionDefinition.h"
+#include "asn1cFiles/E2SM-gNB-X2-actionDefinition.h"
 
-#include "../asn1cFiles/E2SM-gNB-X2-callProcessID.h"
-#include "../asn1cFiles/E2SM-gNB-X2-controlHeader.h"
-#include "../asn1cFiles/E2SM-gNB-X2-controlMessage.h"
-#include "../asn1cFiles/E2SM-gNB-X2-indicationHeader.h"
-#include "../asn1cFiles/E2SM-gNB-X2-indicationMessage.h"
-#include "../asn1cFiles/E2SM-gNB-X2-eventTriggerDefinition.h"
+#include "asn1cFiles/E2SM-gNB-X2-callProcessID.h"
+#include "asn1cFiles/E2SM-gNB-X2-controlHeader.h"
+#include "asn1cFiles/E2SM-gNB-X2-controlMessage.h"
+#include "asn1cFiles/E2SM-gNB-X2-indicationHeader.h"
+#include "asn1cFiles/E2SM-gNB-X2-indicationMessage.h"
+#include "asn1cFiles/E2SM-gNB-X2-eventTriggerDefinition.h"
 
 
-#include "../asn1cFiles/ActionParameter-Item.h"
-#include "../asn1cFiles/ActionParameter-Value.h"
-#include "../asn1cFiles/PLMN-Identity.h"
-#include "../asn1cFiles/GlobalENB-ID.h"
-#include "../asn1cFiles/GlobalGNB-ID.h"
-#include "../asn1cFiles/Interface-ID.h"
-#include "../asn1cFiles/InterfaceMessageType.h"
-#include "../asn1cFiles/InterfaceProtocolIE-Item.h"
+#include "asn1cFiles/ActionParameter-Item.h"
+#include "asn1cFiles/ActionParameter-Value.h"
+#include "asn1cFiles/PLMN-Identity.h"
+#include "asn1cFiles/GlobalENB-ID.h"
+#include "asn1cFiles/GlobalGNB-ID.h"
+#include "asn1cFiles/Interface-ID.h"
+#include "asn1cFiles/InterfaceMessageType.h"
+#include "asn1cFiles/InterfaceProtocolIE-Item.h"
 
 /**
  *
@@ -99,7 +98,10 @@ GNB_ID_t *createGnb_id(const unsigned char *data, int numOfBits);
 GlobalENB_ID_t *createGlobalENB_ID(PLMN_Identity_t *plmnIdentity, ENB_ID_t *enbId);
 /**
  *
- * @param plmnIdentity
+ * @param plmnIdent#ifdef __cplusplus
+}
+#endif
+ity
  * @param gnb
  * @return
  */
diff --git a/RIC-E2-TERMINATION/TEST/e2test.cpp b/RIC-E2-TERMINATION/TEST/e2test.cpp
new file mode 100644 (file)
index 0000000..fad77b8
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+ /*
+ * This source code is part of the near-RT RIC (RAN Intelligent Controller)
+ * platform project (RICP).
+ */
+
+//
+// Created by adi ENZEL on 12/19/19.
+//
+
+#include "e2test.h"
+
+
+
+int main(const int argc, char **argv) {
+
+}
\ No newline at end of file
diff --git a/RIC-E2-TERMINATION/TEST/e2test.h b/RIC-E2-TERMINATION/TEST/e2test.h
new file mode 100644 (file)
index 0000000..527bfab
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 2019 Nokia
+ *
+ * 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.
+ */
+ /*
+ * This source code is part of the near-RT RIC (RAN Intelligent Controller)
+ * platform project (RICP).
+ */
+
+//
+// Created by adi ENZEL on 12/19/19.
+//
+
+#ifndef E2_E2TEST_H
+#define E2_E2TEST_H
+
+#include <algorithm>
+
+#include <pistache/net.h>
+#include <pistache/http.h>
+#include <pistache/peer.h>
+#include <pistache/http_headers.h>
+#include <pistache/cookie.h>
+#include <pistache/endpoint.h>
+#include <pistache/common.h>
+#include <pistache/router.h>
+
+
+using namespace Pistache;
+
+class e2test  {
+
+    Rest::Router router;
+
+};
+
+
+#endif //E2_E2TEST_H
index 9b97d82..fa9e498 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
+ /*
  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
  * platform project (RICP).
  */
 
-
 //
 // Created by adi ENZEL on 9/26/19.
 //
 
 #include "base64.h"
 
-void base64::encode(const unsigned char *src, const int srcLen, char unsigned *dst, int &dstLen) {
+int base64::encode(const unsigned char *src, int srcLen, char unsigned *dst, long &dstLen) {
     unsigned char *pos;
     const unsigned char *end, *in;
-    if (dstLen < srcLen) {
-        mdclog_write(MDCLOG_ERR, "Destination size %d must be at least 140 percent from source size %d",
+
+    if (dstLen <= 0 || srcLen <= 0) {
+        mdclog_write(MDCLOG_ERR, "source or destination length are 0. dst =%ld source = %d",
                      dstLen, srcLen);
-        return;
+        return -1;
+    }
+    if (dstLen < (srcLen * 4 / 3)) {
+        mdclog_write(MDCLOG_ERR, "Destination size %ld must be at least 140 percent from source size %d",
+                     dstLen, srcLen);
+        return -1;
     }
     if (dst == nullptr) {
         mdclog_write(MDCLOG_ERR, "Destination must be allocated and freed by caller the function not allocate the memory");
-        return;
+        return -1;
+    }
+    if (src == nullptr) {
+        mdclog_write(MDCLOG_ERR, "source is null pointer");
+        return -1;
     }
 
     end = src + srcLen;
@@ -64,6 +73,77 @@ void base64::encode(const unsigned char *src, const int srcLen, char unsigned *d
     }
 
     *pos = '\0';
-    dstLen = pos - dst;
+    dstLen = pos - dst;return 0;
 }
 
+int base64::decode(const unsigned char *src, int srcLen, char unsigned *dst, long &dstLen) {
+    unsigned char inv_table[INVERSE_TABLE_SIZE];
+    memset(inv_table, 0x80, INVERSE_TABLE_SIZE);
+    for (ulong i = 0; i < sizeof(base64_table) - 1; i++) {
+        inv_table[base64_table[i]] = (unsigned char) i;
+    }
+    inv_table['='] = 0;
+
+
+    if (dstLen == 0 || dstLen  < (int)(srcLen / 4 * 3)) {
+        mdclog_write(MDCLOG_ERR, "Destination size %ld can be up to 40  smaller then source size %d",
+                     dstLen, srcLen);
+        return -1;
+    }
+    if (dst == nullptr) {
+        mdclog_write(MDCLOG_ERR, "Destination must be allocated and freed by caller the function not allocate the memory");
+        return -1;
+    }
+
+    unsigned char *pos, block[4], tmp;
+    long i;
+    int pad = 0;
+
+    size_t count = 0;
+
+    for (i = 0; i < srcLen; i++) {
+        if (inv_table[src[i]] != 0x80) {
+            count++;
+        }
+    }
+
+    if (count == 0 || count % 4)
+        return -1;
+
+    pos = dst;
+    count = 0;
+    for (i = 0; i < srcLen; i++) {
+        tmp = inv_table[src[i]];
+        if (tmp == 0x80) {
+            continue;
+        }
+        block[count] = tmp;
+
+        if (src[i] == '=') {
+            pad++;
+        }
+
+        count++;
+        if (count == 4) {
+            *pos++ = (block[0] << 2) | ((unsigned char)block[1] >> (unsigned int)4);
+            *pos++ = (block[1] << 4) | ((unsigned char)block[2] >> (unsigned int)2);
+            *pos++ = (block[2] << 6) | block[3];
+            count = 0;
+            if (pad) {
+                if (pad == 1) {
+                    pos--;
+                }
+                else if (pad == 2) {
+                    pos -= 2;
+                }
+                else {
+                    return -1;
+                }
+                break;
+            }
+        }
+    }
+
+    dstLen = pos - dst;
+    return 0;
+}
index 61fdd63..f2f7b6f 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
+ /*
  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
  * platform project (RICP).
  */
 
-
 //
 // Created by adi ENZEL on 9/26/19.
 //
 #define E2_BASE64_H
 
 #include <mdclog/mdclog.h>
+#include <cstring>
+#include <zconf.h>
 
 static const unsigned char base64_table[65] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
+#define INVERSE_TABLE_SIZE 256
+
 class base64 {
 public:
-    static void encode(const unsigned char *src, const int srcLen, char unsigned *dst, int &dstLen);
+    /**
+     *
+     * @param src
+     * @param srcLen
+     * @param dst
+     * @param dstLen
+     * @return 0 = OK -1 fault
+     */
+    static int encode(const unsigned char *src, int srcLen, char unsigned *dst, long &dstLen);
+    /**
+     *
+     * @param src
+     * @param srcLen
+     * @param dst
+     * @param dstLen
+     * @return 0 = OK -1 fault
+     */
+    static int decode(const unsigned char *src, int srcLen, char unsigned *dst, long &dstLen);
+
 };
 
 
diff --git a/RIC-E2-TERMINATION/config/config.conf b/RIC-E2-TERMINATION/config/config.conf
new file mode 100644 (file)
index 0000000..ab7be5e
--- /dev/null
@@ -0,0 +1,7 @@
+nano=38000
+loglevel=info
+volume=log
+local-ip=127.0.0.1
+#trace is start, stop
+trace=start
+external-fqdn=e2t.att.com
\ No newline at end of file
index feb9ae0..e69aab4 100644 (file)
@@ -1,4 +1,3 @@
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
----
-tag: 2.0.10
+tag: 3.0.4.1
index 30b8864..5588419 100644 (file)
@@ -18,4 +18,8 @@ rte|1080|10.0.2.15:3801
 rte|1090|10.0.2.15:38000
 rte|1100|10.0.2.15:3801
 rte|12010|10.0.2.15:38010
+rte|10091|10.0.2.15:4801
+rte|10092|10.0.2.15:4801
+rte|1101|10.0.2.15:38000
+rte|1102|10.0.2.15:3801
 newrt|end
index f4cd98f..31a7e23 100644 (file)
@@ -23,6 +23,8 @@
 
 
 using namespace std::placeholders;
+using namespace boost::filesystem;
+
 #ifdef __TRACING__
 using namespace opentracing;
 #endif
@@ -31,9 +33,20 @@ using namespace opentracing;
 //{
 //#endif
 
+// need to expose without the include of gcov
+extern "C" void __gcov_flush(void);
+
+static void catch_function(int signal) {
+    __gcov_flush();
+    exit(signal);
+}
+
+
 BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger_mt)
 
 boost::shared_ptr<sinks::synchronous_sink<sinks::text_file_backend>> boostLogger;
+double cpuClock = 0.0;
+bool jsonTrace = true;
 
 void init_log() {
     mdclog_attr_t *attr;
@@ -42,15 +55,35 @@ void init_log() {
     mdclog_init(attr);
     mdclog_attr_destroy(attr);
 }
+auto start_time = std::chrono::high_resolution_clock::now();
+typedef std::chrono::duration<double, std::ratio<1,1>> seconds_t;
 
+double age() {
+    return seconds_t(std::chrono::high_resolution_clock::now() - start_time).count();
+}
+
+double approx_CPU_MHz(unsigned sleeptime) {
+    using namespace std::chrono_literals;
+    uint32_t aux = 0;
+    uint64_t cycles_start = rdtscp(aux);
+    double time_start = age();
+    std::this_thread::sleep_for(sleeptime * 1ms);
+    uint64_t elapsed_cycles = rdtscp(aux) - cycles_start;
+    double elapsed_time = age() - time_start;
+    return elapsed_cycles / elapsed_time;
+}
 
 //std::atomic<int64_t> rmrCounter{0};
 std::atomic<int64_t> num_of_messages{0};
+std::atomic<int64_t> num_of_XAPP_messages{0};
 static long transactionCounter = 0;
 
 
 int main(const int argc, char **argv) {
-    sctp_params_t pSctpParams;
+    sctp_params_t sctpParams;
+
+
+
 #ifdef __TRACING__
     opentracing::Tracer::InitGlobal(tracelibcpp::createTracer("E2 Terminator"));
     auto span = opentracing::Tracer::Global()->StartSpan(__FUNCTION__);
@@ -58,130 +91,204 @@ int main(const int argc, char **argv) {
     otSpan span = 0;
 #endif
 
+    {
+        std::random_device device{};
+        std::mt19937 generator(device());
+        std::uniform_int_distribution<long> distribution(1, (long) 1e12);
+        transactionCounter = distribution(generator);
+    }
+
+    uint64_t st = 0,en = 0;
+    uint32_t aux1 = 0;
+    uint32_t aux2 = 0;
+    st = rdtscp(aux1);
+
     unsigned num_cpus = std::thread::hardware_concurrency();
-#ifdef ERROR_LEVEL
-    mdclog_severity_t loglevel = MDCLOG_ERR;
-#else
-    mdclog_severity_t loglevel = MDCLOG_INFO;
-#endif
     init_log();
-    mdclog_level_set(loglevel);
+    mdclog_level_set(MDCLOG_INFO);
 
-    if (argc < 7) {
-        mdclog_mdc_add("app", argv[0]);
-        mdclog_write(MDCLOG_ERR, "Usage nano <rmr port> logLevel <debug/warning/info/error> volume <PATH to log file location>");
-        return -1;
+    if (std::signal(SIGINT, catch_function) == SIG_ERR) {
+        mdclog_write(MDCLOG_ERR, "Errir initializing SIGINT");
+        exit(1);
+    }
+    if (std::signal(SIGABRT, catch_function)== SIG_ERR) {
+        mdclog_write(MDCLOG_ERR, "Errir initializing SIGABRT");
+        exit(1);
+    }
+    if (std::signal(SIGTERM, catch_function)== SIG_ERR) {
+        mdclog_write(MDCLOG_ERR, "Errir initializing SIGTERM");
+        exit(1);
     }
 
-    {
-        std::random_device device{};
-        std::mt19937 generator(device());
-        std::uniform_int_distribution<long> distribution(1, (long) 1e12);
 
-        transactionCounter = distribution(generator);
+    cpuClock = approx_CPU_MHz(100);
+
+    mdclog_write(MDCLOG_DEBUG, "CPU speed %11.11f", cpuClock);
+    auto result = parse(argc, argv, sctpParams);
+
+    path p = (sctpParams.configFilePath + "/" + sctpParams.configFileName).c_str();
+    if (exists(p)) {
+        const int size = 2048;
+        auto fileSize = file_size(p);
+        if (fileSize > size) {
+            mdclog_write(MDCLOG_ERR, "File %s larger than %d", p.string().c_str(), size);
+            exit(-1);
+        }
+    } else {
+        mdclog_write(MDCLOG_ERR, "Configuration File %s not exists", p.string().c_str());
+        exit(-1);
+    }
+
+
+    ReadConfigFile conf;
+    if (conf.openConfigFile(p.string()) == -1) {
+        mdclog_write(MDCLOG_ERR, "Filed to open config file %s, %s",
+                     p.string().c_str(), strerror(errno));
+        exit(-1);
+    }
+    int rmrPort = conf.getIntValue("nano");
+    if (rmrPort == -1) {
+        mdclog_write(MDCLOG_ERR, "illigal RMR port ");
+        exit(-1);
+    }
+    sctpParams.rmrPort = (uint16_t)rmrPort;
+    snprintf(sctpParams.rmrAddress, sizeof(sctpParams.rmrAddress), "%d", (int) (sctpParams.rmrPort));
+
+    auto tmpStr = conf.getStringValue("loglevel");
+    if (tmpStr.length() == 0) {
+        mdclog_write(MDCLOG_ERR, "illigal loglevel. Set loglevel to MDCLOG_INFO");
+        tmpStr = "info";
+    }
+    transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), ::tolower);
+
+    if ((tmpStr.compare("debug")) == 0) {
+        sctpParams.logLevel = MDCLOG_DEBUG;
+    } else if ((tmpStr.compare("info")) == 0) {
+        sctpParams.logLevel = MDCLOG_INFO;
+    } else if ((tmpStr.compare("warning")) == 0) {
+        sctpParams.logLevel = MDCLOG_WARN;
+    } else if ((tmpStr.compare("error")) == 0) {
+        sctpParams.logLevel = MDCLOG_ERR;
+    } else {
+        mdclog_write(MDCLOG_ERR, "illigal loglevel = %s. Set loglevel to MDCLOG_INFO", tmpStr.c_str());
+        sctpParams.logLevel = MDCLOG_INFO;
+    }
+    mdclog_level_set(sctpParams.logLevel);
+
+    tmpStr = conf.getStringValue("volume");
+    if (tmpStr.length() == 0) {
+        mdclog_write(MDCLOG_ERR, "illigal volume.");
+        exit(-1);
     }
 
     char tmpLogFilespec[VOLUME_URL_SIZE];
     tmpLogFilespec[0] = 0;
-    pSctpParams.volume[0] = 0;
-    //read paramters from CLI
-    for (auto i = 1; i < argc; i += 2) {
-        char *dummy;
-        if (strcasecmp("nano", argv[i]) == 0) {
-            pSctpParams.rmrPort = (uint16_t) (uint16_t) strtol(argv[i + 1], &dummy, 10);
-        } else if (strcasecmp("loglevel", argv[i]) == 0) {
-            if (strcasecmp("debug", argv[i + 1]) == 0) {
-                loglevel = MDCLOG_DEBUG;
-            } else if (strcasecmp("info", argv[i + 1]) == 0) {
-                loglevel = MDCLOG_INFO;
-            } else if (strcasecmp("warning", argv[i + 1]) == 0) {
-                loglevel = MDCLOG_WARN;
-            } else if (strcasecmp("error", argv[i + 1]) == 0) {
-                loglevel = MDCLOG_ERR;
-            }
-        } else if (strcasecmp("volume", argv[i]) == 0) {
-            snprintf(pSctpParams.volume, VOLUME_URL_SIZE, "%s", argv[i + 1]);
-            snprintf(tmpLogFilespec, VOLUME_URL_SIZE, "%s", argv[i + 1]);
-        }
+    sctpParams.volume[0] = 0;
+    snprintf(sctpParams.volume, VOLUME_URL_SIZE, "%s", tmpStr.c_str());
+    // copy the name to temp file as well
+    snprintf(tmpLogFilespec, VOLUME_URL_SIZE, "%s", tmpStr.c_str());
+
+
+    // define the file name in the tmp directory under the volume
+    strcat(tmpLogFilespec,"/tmp/E2Term_%Y-%m-%d_%H-%M-%S.%N.tmpStr");
+
+    sctpParams.myIP = conf.getStringValue("local-ip");
+    if (sctpParams.myIP.length() == 0) {
+        mdclog_write(MDCLOG_ERR, "illigal local-ip.");
+        exit(-1);
+    }
+
+    sctpParams.myIP = conf.getStringValue("external-fqdn");
+    if (sctpParams.myIP.length() == 0) {
+        mdclog_write(MDCLOG_ERR, "illigal external-fqdn.");
+        exit(-1);
     }
 
+    tmpStr = conf.getStringValue("trace");
+    transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), ::tolower);
+    if ((tmpStr.compare("start")) == 0) {
+        mdclog_write(MDCLOG_INFO, "Trace set to: start");
+        sctpParams.trace = true;
+    } else if ((tmpStr.compare("stop")) == 0) {
+        mdclog_write(MDCLOG_INFO, "Trace set to: stop");
+        sctpParams.trace = false;
+    }
+    jsonTrace = sctpParams.trace;
 
-    pSctpParams.logLevel = loglevel;
-    snprintf(pSctpParams.rmrAddress, sizeof(pSctpParams.rmrAddress) - 1, "%d", (int) (pSctpParams.rmrPort));
+    en = rdtscp(aux2);
 
-    strcat(tmpLogFilespec,"/tmp/E2Term_%Y-%m-%d_%H-%M-%S.%N.log");
+    mdclog_write(MDCLOG_INFO, "start = %lx end = %lx diff = %lx\n", st, en, en - st);
+    mdclog_write(MDCLOG_INFO, "start high = %lx start lo = %lx end high = %lx end lo = %lx\n",
+            st >> 32, st & 0xFFFFFFFF, (int64_t)en >> 32, en & 0xFFFFFFFF);
+    mdclog_write(MDCLOG_INFO, "ellapsed time = %5.9f\n", (double)(en - st)/cpuClock);
 
     if (mdclog_level_get() >= MDCLOG_INFO) {
-        mdclog_mdc_add("RMR Port", to_string(pSctpParams.rmrPort).c_str());
-        mdclog_mdc_add("LogLevel", to_string(pSctpParams.logLevel).c_str());
-        mdclog_mdc_add("volume", pSctpParams.volume);
+        mdclog_mdc_add("RMR Port", to_string(sctpParams.rmrPort).c_str());
+        mdclog_mdc_add("LogLevel", to_string(sctpParams.logLevel).c_str());
+        mdclog_mdc_add("volume", sctpParams.volume);
         mdclog_mdc_add("tmpLogFilespec", tmpLogFilespec);
+        mdclog_mdc_add("my ip", sctpParams.myIP.c_str());
 
         mdclog_write(MDCLOG_INFO, "running parameters");
     }
     mdclog_mdc_clean();
+    sctpParams.ka_message_length = snprintf(sctpParams.ka_message, 4096, "{\"address\": \"%s:%d\","
+                                                                         "\"fqdn\": \"%s\"}",
+                                            (const char *)sctpParams.myIP.c_str(),
+                                            sctpParams.rmrPort,
+                                            sctpParams.fqdn.c_str());
+
 
     // Files written to the current working directory
     boostLogger = logging::add_file_log(
-            keywords::file_name = tmpLogFilespec,
+            keywords::file_name = tmpLogFilespec, // to temp directory
             keywords::rotation_size = 10 * 1024 * 1024,
             keywords::time_based_rotation = sinks::file::rotation_at_time_interval(posix_time::hours(1)),
             keywords::format = "%Message%"
-            //keywords::format = "[%TimeStamp%]: %Message%" // use each log with time stamp
+            //keywords::format = "[%TimeStamp%]: %Message%" // use each tmpStr with time stamp
     );
 
     // Setup a destination folder for collecting rotated (closed) files --since the same volumn can use rename()
     boostLogger->locked_backend()->set_file_collector(sinks::file::make_collector(
-        keywords::target = pSctpParams.volume 
-        //keywords::max_size = 16 * 1024 * 1024, 
-        //keywords::min_free_space = 100 * 1024 * 1024  
+            keywords::target = sctpParams.volume
     ));
 
     // Upon restart, scan the directory for files matching the file_name pattern
     boostLogger->locked_backend()->scan_for_files();
 
-    // Enable auto-flushing after each log record written
+    // Enable auto-flushing after each tmpStr record written
     if (mdclog_level_get() >= MDCLOG_DEBUG) {
        boostLogger->locked_backend()->auto_flush(true);
     }
 
     // start epoll
-    pSctpParams.epoll_fd = epoll_create1(0);
-    if (pSctpParams.epoll_fd == -1) {
+    sctpParams.epoll_fd = epoll_create1(0);
+    if (sctpParams.epoll_fd == -1) {
         mdclog_write(MDCLOG_ERR, "failed to open epoll descriptor");
         exit(-1);
     }
 
-    pSctpParams.rmrCtx = getRmrContext(pSctpParams.rmrAddress, &span);
-    if (pSctpParams.rmrCtx == nullptr) {
-        mdclog_write(MDCLOG_ERR, "Failed to initialize RMR");
-        close(pSctpParams.epoll_fd);
+    getRmrContext(sctpParams, &span);
+    if (sctpParams.rmrCtx == nullptr) {
+        close(sctpParams.epoll_fd);
         exit(-1);
     }
-    rmr_init_trace(pSctpParams.rmrCtx, 200);
-    // get the RMR fd for the epoll
-    pSctpParams.rmrListenFd = rmr_get_rcvfd(pSctpParams.rmrCtx);
-    struct epoll_event event{};
-    // add RMR fd to epoll
-    event.events = (EPOLLIN);
-    event.data.fd = pSctpParams.rmrListenFd;
-    // add listening RMR FD to epoll
-    if (epoll_ctl(pSctpParams.epoll_fd, EPOLL_CTL_ADD, pSctpParams.rmrListenFd, &event)) {
-        mdclog_write(MDCLOG_ERR, "Failed to add RMR descriptor to epoll");
-        close(pSctpParams.rmrListenFd);
-        rmr_close(pSctpParams.rmrCtx);
-        close(pSctpParams.epoll_fd);
+
+    if (buildInotify(sctpParams) == -1) {
+        close(sctpParams.rmrListenFd);
+        rmr_close(sctpParams.rmrCtx);
+        close(sctpParams.epoll_fd);
         exit(-1);
-    }
+     }
 
-    pSctpParams.sctpMap = new mapWrapper();
+    sctpParams.sctpMap = new mapWrapper();
 
     std::vector<std::thread> threads(num_cpus);
 //    std::vector<std::thread> threads;
 
     num_cpus = 1;
     for (unsigned int i = 0; i < num_cpus; i++) {
-        threads[i] = std::thread(listener, &pSctpParams);
+        threads[i] = std::thread(listener, &sctpParams);
 
         cpu_set_t cpuset;
         CPU_ZERO(&cpuset);
@@ -190,32 +297,63 @@ int main(const int argc, char **argv) {
         if (rc != 0) {
             mdclog_write(MDCLOG_ERR, "Error calling pthread_setaffinity_np: %d", rc);
         }
+    }
 
-//        threads.emplace_back(std::thread(listener, &pSctpParams));
+    //loop over term_init until first message from xApp
+    handleTermInit(sctpParams);
+
+    for (auto &t : threads) {
+        t.join();
     }
 
+#ifdef __TRACING__
+    opentracing::Tracer::Global()->Close();
+#endif
+    return 0;
+}
+
+void handleTermInit(sctp_params_t &sctpParams) {
+    sendTermInit(sctpParams);
     //send to e2 manager init of e2 term
     //E2_TERM_INIT
-    auto term_init = false;
 
-    char buff[128]{};
-    auto len = snprintf(buff, 128, "E2 terminator started");
-    rmr_mbuf_t *msg = rmr_alloc_msg(pSctpParams.rmrCtx, 200);
+    int count = 0;
+    while (true) {
+        auto xappMessages = num_of_XAPP_messages.load(std::memory_order_acquire);
+        if (xappMessages > 0) {
+            if (mdclog_level_get() >=  MDCLOG_INFO) {
+                mdclog_write(MDCLOG_INFO, "Got a message from some appliction, stop sending E@_TERM_INIT");
+            }
+            return;
+        }
+        usleep(100000);
+        count++;
+        if (count % 1000 == 0) {
+            mdclog_write(MDCLOG_ERR, "GOT No messages from any xApp");
+            sendTermInit(sctpParams);
+        }
+    }
+}
+
+void sendTermInit(sctp_params_t &sctpParams) {
+    rmr_mbuf_t *msg = rmr_alloc_msg(sctpParams.rmrCtx, sctpParams.ka_message_length);
     auto count = 0;
-    while (!term_init) {
+    while (true) {
         msg->mtype = E2_TERM_INIT;
         msg->state = 0;
-        rmr_bytes2payload(msg, (unsigned char *) buff, len);
+        rmr_bytes2payload(msg, (unsigned char *)sctpParams.ka_message, sctpParams.ka_message_length);
         static unsigned char tx[32];
         auto txLen = snprintf((char *) tx, sizeof tx, "%15ld", transactionCounter++);
         rmr_bytes2xact(msg, tx, txLen);
-        msg = rmr_send_msg(pSctpParams.rmrCtx, msg);
+        msg = rmr_send_msg(sctpParams.rmrCtx, msg);
         if (msg == nullptr) {
-            msg = rmr_alloc_msg(pSctpParams.rmrCtx, 200);
+            msg = rmr_alloc_msg(sctpParams.rmrCtx, sctpParams.myIP.length());
         } else if (msg->state == 0) {
-            term_init = true;
             rmr_free_msg(msg);
-            //break;
+            if (mdclog_level_get() >=  MDCLOG_INFO) {
+                mdclog_write(MDCLOG_INFO, "E2_TERM_INIT succsesfuly sent ");
+            }
+            return;
         } else {
             if (count % 100 == 0) {
                 mdclog_write(MDCLOG_ERR, "Error sending E2_TERM_INIT cause : %d ", msg->state);
@@ -225,13 +363,67 @@ int main(const int argc, char **argv) {
         count++;
     }
 
-    for (auto &t : threads) {
-        t.join();
+}
+
+/**
+ *
+ * @param argc
+ * @param argv
+ * @param sctpParams
+ * @return
+ */
+cxxopts::ParseResult parse(int argc, char *argv[], sctp_params_t &sctpParams) {
+    cxxopts::Options options(argv[0], "e2 term help");
+    options.positional_help("[optional args]").show_positional_help();
+    options.allow_unrecognised_options().add_options()
+            ("p,path", "config file path", cxxopts::value<std::string>(sctpParams.configFilePath)->default_value("config"))
+            ("f,file", "config file name", cxxopts::value<std::string>(sctpParams.configFileName)->default_value("config.conf"))
+            ("h,help", "Print help");
+
+    auto result = options.parse(argc, argv);
+
+    if (result.count("help")) {
+        std::cout << options.help({""}) << std::endl;
+        exit(0);
     }
+    return result;
+}
 
-#ifdef __TRACING__
-    opentracing::Tracer::Global()->Close();
-#endif
+/**
+ *
+ * @param sctpParams
+ * @return -1 failed 0 success
+ */
+int buildInotify(sctp_params_t &sctpParams) {
+    sctpParams.inotifyFD = inotify_init1(IN_NONBLOCK);
+    if (sctpParams.inotifyFD == -1) {
+        mdclog_write(MDCLOG_ERR, "Failed to init inotify (inotify_init1) %s", strerror(errno));
+        close(sctpParams.rmrListenFd);
+        rmr_close(sctpParams.rmrCtx);
+        close(sctpParams.epoll_fd);
+        return -1;
+    }
+
+    sctpParams.inotifyWD = inotify_add_watch(sctpParams.inotifyFD,
+                                              (const char *)sctpParams.configFilePath.c_str(),
+                                              IN_OPEN | IN_CLOSE);
+    if (sctpParams.inotifyWD == -1) {
+        mdclog_write(MDCLOG_ERR, "Failed to add directory : %s to  inotify (inotify_add_watch) %s",
+                sctpParams.configFilePath.c_str(),
+                strerror(errno));
+        close(sctpParams.inotifyFD);
+        return -1;
+    }
+
+    struct epoll_event event{};
+    event.events = (EPOLLIN);
+    event.data.fd = sctpParams.inotifyFD;
+    // add listening RMR FD to epoll
+    if (epoll_ctl(sctpParams.epoll_fd, EPOLL_CTL_ADD, sctpParams.inotifyFD, &event)) {
+        mdclog_write(MDCLOG_ERR, "Failed to add inotify FD to epoll");
+        close(sctpParams.inotifyFD);
+        return -1;
+    }
     return 0;
 }
 
@@ -247,7 +439,6 @@ void listener(sctp_params_t *params) {
     otSpan span = 0;
 #endif
     int num_of_SCTP_messages = 0;
-    int num_of_XAPP_messages = 0;
     auto totalTime = 0.0;
     mdclog_mdc_clean();
     mdclog_level_set(params->logLevel);
@@ -282,6 +473,14 @@ void listener(sctp_params_t *params) {
     rmrMessageBuffer.rcvMessage = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
     rmrMessageBuffer.sendMessage = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
 
+    memcpy(rmrMessageBuffer.ka_message, params->ka_message, params->ka_message_length);
+    rmrMessageBuffer.ka_message_len = params->ka_message_length;
+    rmrMessageBuffer.ka_message[rmrMessageBuffer.ka_message_len] = 0;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        mdclog_write(MDCLOG_DEBUG, "keep alive message is : %s", rmrMessageBuffer.ka_message);
+    }
+
     ReportingMessages_t message {};
 
     for (int i = 0; i < MAX_RMR_BUFF_ARRY; i++) {
@@ -311,94 +510,15 @@ void listener(sctp_params_t *params) {
             clock_gettime(CLOCK_MONOTONIC, &message.message.time);
             start.tv_sec = message.message.time.tv_sec;
             start.tv_nsec = message.message.time.tv_nsec;
-            if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP)) {
-                if (events[i].data.fd != params->rmrListenFd) {
-                    auto *peerInfo = (ConnectedCU_t *)events[i].data.ptr;
-                    mdclog_write(MDCLOG_ERR, "epoll error, events %0x on fd %d, RAN NAME : %s",
-                                 events[i].events, peerInfo->fileDescriptor, peerInfo->enodbName);
-
-                    rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
-                                                         "%s|Failed SCTP Connection",
-                                                         peerInfo->enodbName);
-                    message.message.asndata = rmrMessageBuffer.sendMessage->payload;
-                    message.message.asnLength = rmrMessageBuffer.sendMessage->len;
 
-                    memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
-                    message.message.direction = 'N';
-                    if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer, &span) != 0) {
-                        mdclog_write(MDCLOG_ERR, "SCTP_CONNECTION_FAIL message failed to send to xAPP");
-                    }
 
-                    close(peerInfo->fileDescriptor);
-                    cleanHashEntry((ConnectedCU_t *) events[i].data.ptr, params->sctpMap, &span);
-                } else {
-                    mdclog_write(MDCLOG_ERR, "epoll error, events %0x on RMR FD", events[i].events);
-                }
+            if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP)) {
+                handlepoll_error(events[i], message, rmrMessageBuffer, params, &span);
             } else if (events[i].events & EPOLLOUT) {
-                // this need to send waiting message from connection EINPROGRESS
-                auto *peerInfo = (ConnectedCU_t *) events[i].data.ptr;
-
-                memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
-
-                mdclog_write(MDCLOG_INFO, "file descriptor %d got EPOLLOUT", peerInfo->fileDescriptor);
-                auto retVal = 0;
-                socklen_t retValLen = 0;
-                auto rc = getsockopt(peerInfo->fileDescriptor, SOL_SOCKET, SO_ERROR, &retVal, &retValLen);
-                if (rc != 0 || retVal != 0) {
-                    if (rc != 0) {
-                        rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
-                                                                       "%s|Failed SCTP Connection, after EINPROGRESS the getsockopt%s",
-                                                                       peerInfo->enodbName, strerror(errno));
-                    } else if (retVal != 0) {
-                        rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
-                                                                       "%s|Failed SCTP Connection after EINPROGRESS, SO_ERROR",
-                                                                       peerInfo->enodbName);
-                    }
-
-                    message.message.asndata = rmrMessageBuffer.sendMessage->payload;
-                    message.message.asnLength = rmrMessageBuffer.sendMessage->len;
-                    mdclog_write(MDCLOG_ERR, "%s", rmrMessageBuffer.sendMessage->payload);
-                    message.message.direction = 'N';
-                    if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer, &span) != 0) {
-                        mdclog_write(MDCLOG_ERR, "SCTP_CONNECTION_FAIL message failed to send to xAPP");
-                    }
-                    memset(peerInfo->asnData, 0, peerInfo->asnLength);
-                    peerInfo->asnLength = 0;
-                    peerInfo->mtype = 0;
-                    continue;
-                }
-
-               peerInfo->isConnected = true;
-
-                if (modifyToEpoll(params->epoll_fd, peerInfo, (EPOLLIN | EPOLLET), params->sctpMap, peerInfo->enodbName,
-                                  peerInfo->mtype, &span) != 0) {
-                    mdclog_write(MDCLOG_ERR, "epoll_ctl EPOLL_CTL_MOD");
-                    continue;
-                }
-
-                message.message.asndata = (unsigned char *)peerInfo->asnData;
-                message.message.asnLength = peerInfo->asnLength;
-                message.message.messageType = peerInfo->mtype;
-                memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
-                num_of_messages.fetch_add(1, std::memory_order_release);
-                if (mdclog_level_get() >= MDCLOG_DEBUG) {
-                    mdclog_write(MDCLOG_DEBUG, "send the delayed SETUP/ENDC SETUP to sctp for %s",
-                                 message.message.enodbName);
-                }
-                if (sendSctpMsg(peerInfo, message, params->sctpMap, &span) != 0) {
-                    if (mdclog_level_get() >= MDCLOG_DEBUG) {
-                        mdclog_write(MDCLOG_DEBUG, "Error write to SCTP  %s %d", __func__, __LINE__);
-                    }
-                    continue;
-                }
-
-                memset(peerInfo->asnData, 0, peerInfo->asnLength);
-                peerInfo->asnLength = 0;
-                peerInfo->mtype = 0;
-
+                handleEinprogressMessages(events[i], message, rmrMessageBuffer, params, &span);
             } else if (params->rmrListenFd == events[i].data.fd) {
                 // got message from XAPP
-                num_of_XAPP_messages++;
+                num_of_XAPP_messages.fetch_add(1, std::memory_order_release);
                 num_of_messages.fetch_add(1, std::memory_order_release);
                 if (mdclog_level_get() >= MDCLOG_DEBUG) {
                     mdclog_write(MDCLOG_DEBUG, "new message from RMR");
@@ -410,6 +530,9 @@ void listener(sctp_params_t *params) {
                                         &span) != 0) {
                     mdclog_write(MDCLOG_ERR, "Error handling Xapp message");
                 }
+            } else if (params->inotifyFD == events[i].data.fd) {
+                mdclog_write(MDCLOG_INFO, "Got event from inotify (configuration update)");
+                handleConfigChange(params);
             } else {
                 /* We RMR_ERR_RETRY have data on the fd waiting to be read. Read and display it.
                  * We must read whatever data is available completely, as we are running
@@ -445,6 +568,247 @@ void listener(sctp_params_t *params) {
 #endif
 }
 
+/**
+ *
+ * @param sctpParams
+ */
+void handleConfigChange(sctp_params_t *sctpParams) {
+    char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
+    const struct inotify_event *event;
+    char *ptr;
+
+    path p = (sctpParams->configFilePath + "/" + sctpParams->configFileName).c_str();
+    auto endlessLoop = true;
+    while (endlessLoop) {
+        auto len = read(sctpParams->inotifyFD, buf, sizeof buf);
+        if (len == -1) {
+            if (errno != EAGAIN) {
+                mdclog_write(MDCLOG_ERR, "read %s ", strerror(errno));
+                endlessLoop = false;
+                continue;
+            }
+            else {
+                endlessLoop = false;
+                continue;
+            }
+        }
+
+        for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) {
+            event = (const struct inotify_event *)ptr;
+            if (event->mask & (uint32_t)IN_ISDIR) {
+                continue;
+            }
+
+            // the directory name
+            if (sctpParams->inotifyWD == event->wd) {
+                // not the directory
+            }
+            if (event->len) {
+                if (!(sctpParams->configFileName.compare(event->name))) {
+                    continue;
+                }
+            }
+            // only the file we want
+            if (event->mask & (uint32_t)IN_CLOSE_WRITE) {
+                if (exists(p)) {
+                    const int size = 2048;
+                    auto fileSize = file_size(p);
+                    if (fileSize > size) {
+                        mdclog_write(MDCLOG_ERR, "File %s larger than %d", p.string().c_str(), size);
+                        return;
+                    }
+                } else {
+                    mdclog_write(MDCLOG_ERR, "Configuration File %s not exists", p.string().c_str());
+                    return;
+                }
+
+                ReadConfigFile conf;
+                if (conf.openConfigFile(p.string()) == -1) {
+                    mdclog_write(MDCLOG_ERR, "Filed to open config file %s, %s",
+                                 p.string().c_str(), strerror(errno));
+                    return;
+                }
+
+                auto tmpStr = conf.getStringValue("loglevel");
+                if (tmpStr.length() == 0) {
+                    mdclog_write(MDCLOG_ERR, "illigal loglevel. Set loglevel to MDCLOG_INFO");
+                    tmpStr = "info";
+                }
+                transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), ::tolower);
+
+                if ((tmpStr.compare("debug")) == 0) {
+                    mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_DEBUG");
+                    sctpParams->logLevel = MDCLOG_DEBUG;
+                } else if ((tmpStr.compare("info")) == 0) {
+                    mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_INFO");
+                    sctpParams->logLevel = MDCLOG_INFO;
+                } else if ((tmpStr.compare("warning")) == 0) {
+                    mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_WARN");
+                    sctpParams->logLevel = MDCLOG_WARN;
+                } else if ((tmpStr.compare("error")) == 0) {
+                    mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_ERR");
+                    sctpParams->logLevel = MDCLOG_ERR;
+                } else {
+                    mdclog_write(MDCLOG_ERR, "illigal loglevel = %s. Set loglevel to MDCLOG_INFO", tmpStr.c_str());
+                    sctpParams->logLevel = MDCLOG_INFO;
+                }
+                mdclog_level_set(sctpParams->logLevel);
+
+
+                tmpStr = conf.getStringValue("trace");
+                if (tmpStr.length() == 0) {
+                    mdclog_write(MDCLOG_ERR, "illigal trace. Set trace to stop");
+                    tmpStr = "stop";
+                }
+
+                transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), ::tolower);
+                if ((tmpStr.compare("start")) == 0) {
+                    mdclog_write(MDCLOG_INFO, "Trace set to: start");
+                    sctpParams->trace = true;
+                } else if ((tmpStr.compare("stop")) == 0) {
+                    mdclog_write(MDCLOG_INFO, "Trace set to: stop");
+                    sctpParams->trace = false;
+                } else {
+                    mdclog_write(MDCLOG_ERR, "Trace was set to wrong value %s, set to stop", tmpStr.c_str());
+                    sctpParams->trace = false;
+                }
+                jsonTrace = sctpParams->trace;
+                endlessLoop = false;
+            }
+        }
+    }
+}
+
+/**
+ *
+ * @param event
+ * @param message
+ * @param rmrMessageBuffer
+ * @param params
+ * @param pSpan
+ */
+void handleEinprogressMessages(struct epoll_event &event,
+                               ReportingMessages_t &message,
+                               RmrMessagesBuffer_t &rmrMessageBuffer,
+                               sctp_params_t *params,
+                               otSpan *pSpan) {
+#ifdef __TRACING__
+    auto lspan = opentracing::Tracer::Global()->StartSpan(
+            __FUNCTION__, { opentracing::ChildOf(&pSpan->get()->context()) });
+#else
+    otSpan lspan = 0;
+#endif
+    auto *peerInfo = (ConnectedCU_t *)event.data.ptr;
+    memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
+
+    mdclog_write(MDCLOG_INFO, "file descriptor %d got EPOLLOUT", peerInfo->fileDescriptor);
+    auto retVal = 0;
+    socklen_t retValLen = 0;
+    auto rc = getsockopt(peerInfo->fileDescriptor, SOL_SOCKET, SO_ERROR, &retVal, &retValLen);
+    if (rc != 0 || retVal != 0) {
+        if (rc != 0) {
+            rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
+                                                         "%s|Failed SCTP Connection, after EINPROGRESS the getsockopt%s",
+                                                         peerInfo->enodbName, strerror(errno));
+        } else if (retVal != 0) {
+            rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
+                                                         "%s|Failed SCTP Connection after EINPROGRESS, SO_ERROR",
+                                                         peerInfo->enodbName);
+        }
+
+        message.message.asndata = rmrMessageBuffer.sendMessage->payload;
+        message.message.asnLength = rmrMessageBuffer.sendMessage->len;
+        mdclog_write(MDCLOG_ERR, "%s", rmrMessageBuffer.sendMessage->payload);
+        message.message.direction = 'N';
+        if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer, &lspan) != 0) {
+            mdclog_write(MDCLOG_ERR, "SCTP_CONNECTION_FAIL message failed to send to xAPP");
+        }
+        memset(peerInfo->asnData, 0, peerInfo->asnLength);
+        peerInfo->asnLength = 0;
+        peerInfo->mtype = 0;
+#ifdef __TRACING__
+        lspan->Finish();
+#endif
+        return;
+    }
+
+    peerInfo->isConnected = true;
+
+    if (modifyToEpoll(params->epoll_fd, peerInfo, (EPOLLIN | EPOLLET), params->sctpMap, peerInfo->enodbName,
+                      peerInfo->mtype, &lspan) != 0) {
+        mdclog_write(MDCLOG_ERR, "epoll_ctl EPOLL_CTL_MOD");
+#ifdef __TRACING__
+        lspan->Finish();
+#endif
+        return;
+    }
+
+    message.message.asndata = (unsigned char *)peerInfo->asnData;
+    message.message.asnLength = peerInfo->asnLength;
+    message.message.messageType = peerInfo->mtype;
+    memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
+    num_of_messages.fetch_add(1, std::memory_order_release);
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        mdclog_write(MDCLOG_DEBUG, "send the delayed SETUP/ENDC SETUP to sctp for %s",
+                     message.message.enodbName);
+    }
+    if (sendSctpMsg(peerInfo, message, params->sctpMap, &lspan) != 0) {
+        if (mdclog_level_get() >= MDCLOG_DEBUG) {
+            mdclog_write(MDCLOG_DEBUG, "Error write to SCTP  %s %d", __func__, __LINE__);
+        }
+#ifdef __TRACING__
+        lspan->Finish();
+#endif
+        return;
+    }
+
+    memset(peerInfo->asnData, 0, peerInfo->asnLength);
+    peerInfo->asnLength = 0;
+    peerInfo->mtype = 0;
+#ifdef __TRACING__
+    lspan->Finish();
+#endif
+}
+
+
+void handlepoll_error(struct epoll_event &event,
+                      ReportingMessages_t &message,
+                      RmrMessagesBuffer_t &rmrMessageBuffer,
+                      sctp_params_t *params,
+                      otSpan *pSpan) {
+#ifdef __TRACING__
+    auto lspan = opentracing::Tracer::Global()->StartSpan(
+            __FUNCTION__, { opentracing::ChildOf(&pSpan->get()->context()) });
+#else
+    otSpan lspan = 0;
+#endif
+    if (event.data.fd != params->rmrListenFd) {
+        auto *peerInfo = (ConnectedCU_t *)event.data.ptr;
+        mdclog_write(MDCLOG_ERR, "epoll error, events %0x on fd %d, RAN NAME : %s",
+                     event.events, peerInfo->fileDescriptor, peerInfo->enodbName);
+
+        rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
+                                                     "%s|Failed SCTP Connection",
+                                                     peerInfo->enodbName);
+        message.message.asndata = rmrMessageBuffer.sendMessage->payload;
+        message.message.asnLength = rmrMessageBuffer.sendMessage->len;
+
+        memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
+        message.message.direction = 'N';
+        if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer, &lspan) != 0) {
+            mdclog_write(MDCLOG_ERR, "SCTP_CONNECTION_FAIL message failed to send to xAPP");
+        }
+
+        close(peerInfo->fileDescriptor);
+        cleanHashEntry((ConnectedCU_t *) event.data.ptr, params->sctpMap, &lspan);
+    } else {
+        mdclog_write(MDCLOG_ERR, "epoll error, events %0x on RMR FD", event.events);
+    }
+#ifdef __TRACING__
+    lspan->Finish();
+#endif
+
+}
 /**
  *
  * @param socket
@@ -1004,9 +1368,16 @@ void asnInitiatingRequest(E2AP_PDU_t *pdu,
                         message.message.messageType = rmrMessageBuffer.sendMessage->mtype = RIC_INDICATION;
                         snprintf((char *) tx, sizeof tx, "%15ld", transactionCounter++);
                         rmr_bytes2xact(rmrMessageBuffer.sendMessage, tx, strlen((const char *) tx));
-                       rmr_bytes2meid(rmrMessageBuffer.sendMessage, (unsigned char *)message.message.enodbName, strlen(message.message.enodbName));
+                        rmr_bytes2meid(rmrMessageBuffer.sendMessage,
+                                (unsigned char *)message.message.enodbName,
+                                strlen(message.message.enodbName));
                         rmrMessageBuffer.sendMessage->state = 0;
                         rmrMessageBuffer.sendMessage->sub_id = (int) ie->value.choice.RICrequestID.ricRequestorID;
+                        if (mdclog_level_get() >= MDCLOG_DEBUG) {
+                            mdclog_write(MDCLOG_DEBUG, "RIC sub id = %d, message type = %d",
+                                    rmrMessageBuffer.sendMessage->sub_id,
+                                    rmrMessageBuffer.sendMessage->mtype);
+                        }
                         sendRmrMessage(rmrMessageBuffer, message, &lspan);
                         messageSent = true;
                     } else {
@@ -1181,7 +1552,9 @@ void asnSuccsesfulMsg(E2AP_PDU_t *pdu, ReportingMessages_t &message, Sctp_Map_t
                         static unsigned char tx[32];
                         snprintf((char *) tx, sizeof tx, "%15ld", transactionCounter++);
                         rmr_bytes2xact(rmrMessageBuffer.sendMessage, tx, strlen((const char *) tx));
-                       rmr_bytes2meid(rmrMessageBuffer.sendMessage, (unsigned char *)message.message.enodbName, strlen(message.message.enodbName));
+                        rmr_bytes2meid(rmrMessageBuffer.sendMessage,
+                                (unsigned char *)message.message.enodbName,
+                                strlen(message.message.enodbName));
 
                         sendRmrMessage(rmrMessageBuffer, message, &lspan);
                         messageSent = true;
@@ -1396,26 +1769,24 @@ int sendRequestToXapp(ReportingMessages_t &message,
 }
 
 
-void *getRmrContext(char *rmrAddress, otSpan *pSpan) {
+void getRmrContext(sctp_params_t &pSctpParams, otSpan *pSpan) {
 #ifdef __TRACING__
     auto lspan = opentracing::Tracer::Global()->StartSpan(
             __FUNCTION__, { opentracing::ChildOf(&pSpan->get()->context()) });
 #else
 //    otSpan lspan = 0;
 #endif
-    void *rmrCtx = rmr_init(rmrAddress, RMR_MAX_RCV_BYTES, RMRFL_NONE);
-
-
-    if (rmrCtx == nullptr) {
-        mdclog_write(MDCLOG_ERR, "RMR failed to initialise : %s", strerror(errno));
+    pSctpParams.rmrCtx = nullptr;
+    pSctpParams.rmrCtx = rmr_init(pSctpParams.rmrAddress, RMR_MAX_RCV_BYTES, RMRFL_NONE);
+    if (pSctpParams.rmrCtx == nullptr) {
+        mdclog_write(MDCLOG_ERR, "Failed to initialize RMR");
 #ifdef __TRACING__
         lspan->Finish();
 #endif
-
-        return (nullptr);
+        return;
     }
 
-    rmr_set_stimeout(rmrCtx, 0);    // disable retries for any send operation
+    rmr_set_stimeout(pSctpParams.rmrCtx, 0);    // disable retries for any send operation
     // we need to find that routing table exist and we can run
     if (mdclog_level_get() >= MDCLOG_INFO) {
         mdclog_write(MDCLOG_INFO, "We are after RMR INIT wait for RMR_Ready");
@@ -1423,7 +1794,7 @@ void *getRmrContext(char *rmrAddress, otSpan *pSpan) {
     int rmrReady = 0;
     int count = 0;
     while (!rmrReady) {
-        if ((rmrReady = rmr_ready(rmrCtx)) == 0) {
+        if ((rmrReady = rmr_ready(pSctpParams.rmrCtx)) == 0) {
             sleep(1);
         }
         count++;
@@ -1437,8 +1808,20 @@ void *getRmrContext(char *rmrAddress, otSpan *pSpan) {
 #ifdef __TRACING__
     lspan->Finish();
 #endif
-
-    return rmrCtx;
+    rmr_init_trace(pSctpParams.rmrCtx, 200);
+    // get the RMR fd for the epoll
+    pSctpParams.rmrListenFd = rmr_get_rcvfd(pSctpParams.rmrCtx);
+    struct epoll_event event{};
+    // add RMR fd to epoll
+    event.events = (EPOLLIN);
+    event.data.fd = pSctpParams.rmrListenFd;
+    // add listening RMR FD to epoll
+    if (epoll_ctl(pSctpParams.epoll_fd, EPOLL_CTL_ADD, pSctpParams.rmrListenFd, &event)) {
+        mdclog_write(MDCLOG_ERR, "Failed to add RMR descriptor to epoll");
+        close(pSctpParams.rmrListenFd);
+        rmr_close(pSctpParams.rmrCtx);
+        pSctpParams.rmrCtx = nullptr;
+    }
 }
 
 /**
@@ -1739,6 +2122,28 @@ int receiveXappMessages(int epoll_fd,
             sctpMap->clear();
             break;
         }
+        case E2_TERM_KEEP_ALIVE_REQ: {
+            // send message back
+            if (mdclog_level_get() >= MDCLOG_INFO) {
+                mdclog_write(MDCLOG_INFO, "Got Keep Alive Request send : %s", rmrMessageBuffer.ka_message);
+            }
+            rmr_bytes2payload(rmrMessageBuffer.sendMessage,
+                    (unsigned char *)rmrMessageBuffer.ka_message,
+                    rmrMessageBuffer.ka_message_len);
+            rmrMessageBuffer.sendMessage->mtype = E2_TERM_KEEP_ALIVE_RESP;
+            rmrMessageBuffer.sendMessage->state = 0;
+            static unsigned char tx[32];
+            auto txLen = snprintf((char *) tx, sizeof tx, "%15ld", transactionCounter++);
+            rmr_bytes2xact(rmrMessageBuffer.sendMessage, tx, txLen);
+            rmrMessageBuffer.sendMessage = rmr_send_msg(rmrMessageBuffer.rmrCtx, rmrMessageBuffer.sendMessage);
+            if (rmrMessageBuffer.sendMessage == nullptr) {
+                rmrMessageBuffer.sendMessage = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
+                mdclog_write(MDCLOG_ERR, "Failed to send E2_TERM_KEEP_ALIVE_RESP");
+            } else if (rmrMessageBuffer.sendMessage->state != 0)  {
+                mdclog_write(MDCLOG_ERR, "Failed to send E2_TERM_KEEP_ALIVE_RESP");
+            }
+            break;
+        }
         default:
             mdclog_write(MDCLOG_WARN, "Message Type : %d is not seported", rmrMessageBuffer.rcvMessage->mtype);
             message.message.asndata = rmrMessageBuffer.rcvMessage->payload;
@@ -2420,41 +2825,36 @@ int sendRmrMessage(RmrMessagesBuffer_t &rmrMessageBuffer, ReportingMessages_t &m
 }
 
 void buildJsonMessage(ReportingMessages_t &message) {
-       message.outLen = sizeof(message.base64Data);
-    base64::encode((const unsigned char *)message.message.asndata,
-                   (const int)message.message.asnLength,
-                  message.base64Data,
-                  message.outLen);
-    if (mdclog_level_get() >= MDCLOG_DEBUG) {
-        mdclog_write(MDCLOG_DEBUG, "asn data length = %d, base64 message length = %d ",
-                     (int)message.message.asnLength,
-                     (int)message.outLen);
-    }
-
-//    char buff[256];
-//    // build day time to seconds from epoc
-//    strftime(buff, sizeof message.message.time, "%D %T", gmtime(&message.message.time.tv_sec));
-//    // add nanosecond
-//    snprintf(buff, sizeof buff, "%s.%09ld UTC\n", buff, message.message.time.tv_nsec);
-
-    message.bufferLen = snprintf(message.buffer, sizeof(message.buffer),
-            "{\"header\": {\"ts\": \"%ld.%09ld\","
-            "\"ranName\": \"%s\","
-            "\"messageType\": %d,"
-            "\"direction\": \"%c\"},"
-            "\"base64Length\": %d,"
-            "\"asnBase64\": \"%s\"}",
-            message.message.time.tv_sec,
-            message.message.time.tv_nsec,
-            message.message.enodbName,
-            message.message.messageType,
-            message.message.direction,
-            (int)message.outLen,
-            message.base64Data);
-    static src::logger_mt& lg = my_logger::get();
-
-    BOOST_LOG(lg) << message.buffer;
-
+    if (jsonTrace) {
+        message.outLen = sizeof(message.base64Data);
+        base64::encode((const unsigned char *) message.message.asndata,
+                       (const int) message.message.asnLength,
+                       message.base64Data,
+                       message.outLen);
+        if (mdclog_level_get() >= MDCLOG_DEBUG) {
+            mdclog_write(MDCLOG_DEBUG, "asn data length = %d, base64 message length = %d ",
+                         (int) message.message.asnLength,
+                         (int) message.outLen);
+        }
+
+        snprintf(message.buffer, sizeof(message.buffer),
+                                     "{\"header\": {\"ts\": \"%ld.%09ld\","
+                                     "\"ranName\": \"%s\","
+                                     "\"messageType\": %d,"
+                                     "\"direction\": \"%c\"},"
+                                     "\"base64Length\": %d,"
+                                     "\"asnBase64\": \"%s\"}",
+                                     message.message.time.tv_sec,
+                                     message.message.time.tv_nsec,
+                                     message.message.enodbName,
+                                     message.message.messageType,
+                                     message.message.direction,
+                                     (int) message.outLen,
+                                     message.base64Data);
+        static src::logger_mt &lg = my_logger::get();
+
+        BOOST_LOG(lg) << message.buffer;
+    }
 }
 
 
index 2149cd3..588f6a8 100644 (file)
  * 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.
- */
+*/
 
 /*
  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
  * platform project (RICP).
  */
 
-
 #ifndef X2_SCTP_THREAD_H
 #define X2_SCTP_THREAD_H
 
@@ -49,6 +48,8 @@
 #include <shared_mutex>
 #include <iterator>
 #include <map>
+#include <sys/inotify.h>
+#include <csignal>
 
 #include <rmr/rmr.h>
 #include <rmr/RIC_message_types.h>
 #include <boost/log/sources/global_logger_storage.hpp>
 #include <boost/log/utility/setup/file.hpp>
 #include <boost/log/utility/setup/common_attributes.hpp>
-
+#include <boost/filesystem.hpp>
 
 #include <mdclog/mdclog.h>
 
-#include "3rdparty/asn1cFiles/E2AP-PDU.h"
-#include <3rdparty/asn1cFiles/ProtocolIE-Container.h>
-#include "3rdparty/asn1cFiles/InitiatingMessage.h"
-#include "3rdparty/asn1cFiles/SuccessfulOutcome.h"
-#include "3rdparty/asn1cFiles/UnsuccessfulOutcome.h"
-#include "3rdparty/asn1cFiles/ProtocolIE-Container.h"
-#include "3rdparty/asn1cFiles/ProtocolIE-Field.h"
+#include "asn1cFiles/E2AP-PDU.h"
+#include "asn1cFiles/ProtocolIE-Container.h"
+#include "asn1cFiles/InitiatingMessage.h"
+#include "asn1cFiles/SuccessfulOutcome.h"
+#include "asn1cFiles/UnsuccessfulOutcome.h"
+#include "asn1cFiles/ProtocolIE-Container.h"
+#include "asn1cFiles/ProtocolIE-Field.h"
+
+#include "cxxopts.hpp"
+//#include "config-cpp/include/config-cpp/config-cpp.h"
 
 #ifdef __TRACING__
 #include "openTracing.h"
@@ -84,6 +88,8 @@
 
 #include "base64.h"
 
+#include "ReadConfigFile.h"
+
 using namespace std;
 namespace logging = boost::log;
 namespace src = boost::log::sources;
@@ -115,11 +121,20 @@ typedef struct sctp_params {
     uint16_t rmrPort = 0;
     int      epoll_fd = 0;
     int      rmrListenFd = 0;
+    int      inotifyFD = 0;
+    int      inotifyWD = 0;
     void     *rmrCtx = nullptr;
     Sctp_Map_t *sctpMap = nullptr;
+    char      ka_message[4096] {};
+    int       ka_message_length = 0;
     char       rmrAddress[256] {}; // "tcp:portnumber" "tcp:5566" listen to all address on port 5566
     mdclog_severity_t logLevel = MDCLOG_INFO;
     char volume[VOLUME_URL_SIZE];
+    string myIP {};
+    string fqdn {};
+    string configFilePath {};
+    string configFileName {};
+    bool trace = true;
     //shared_timed_mutex fence; // moved to mapWrapper
 } sctp_params_t;
 
@@ -136,11 +151,13 @@ typedef struct ConnectedCU {
 
 #define MAX_RMR_BUFF_ARRY 32
 typedef struct RmrMessagesBuffer {
-    void *rmrCtx;
-    rmr_mbuf_t *sendMessage;
-    rmr_mbuf_t *sendBufferedMessages[MAX_RMR_BUFF_ARRY];
-    rmr_mbuf_t *rcvMessage;
-    rmr_mbuf_t *rcvBufferedMessages[MAX_RMR_BUFF_ARRY];
+    char ka_message[4096] {};
+    int  ka_message_len = 0;
+    void *rmrCtx = nullptr;
+    rmr_mbuf_t *sendMessage= nullptr;
+    rmr_mbuf_t *sendBufferedMessages[MAX_RMR_BUFF_ARRY] {};
+    rmr_mbuf_t *rcvMessage= nullptr;
+    rmr_mbuf_t *rcvBufferedMessages[MAX_RMR_BUFF_ARRY] {};
 } RmrMessagesBuffer_t;
 
 typedef struct formatedMessage {
@@ -154,17 +171,38 @@ typedef struct formatedMessage {
 
 typedef struct ReportingMessages {
     FormatedMessage_t message;
-    int outLen;
+    long outLen;
     unsigned char base64Data[RECEIVE_SCTP_BUFFER_SIZE * 2];
     char buffer[RECEIVE_SCTP_BUFFER_SIZE * 8];
-    size_t bufferLen;
 } ReportingMessages_t;
 
+cxxopts::ParseResult parse(int argc, char *argv[], sctp_params_t &pSctpParams);
+
+int buildInotify(sctp_params_t &sctpParams);
+
+void handleTermInit(sctp_params_t &sctpParams);
+
+void handleConfigChange(sctp_params_t *sctpParams);
 
 void listener(sctp_params_t *params);
 
+void sendTermInit(sctp_params_t &sctpParams);
+
 int setSocketNoBlocking(int socket);
 
+void handleEinprogressMessages(struct epoll_event &event,
+                               ReportingMessages_t &message,
+                               RmrMessagesBuffer_t &rmrMessageBuffer,
+                               sctp_params_t *params,
+                               otSpan *pSpan);
+
+void handlepoll_error(struct epoll_event &event,
+                      ReportingMessages_t &message,
+                      RmrMessagesBuffer_t &rmrMessageBuffer,
+                      sctp_params_t *params,
+                      otSpan *pSpan);
+
+
 void cleanHashEntry(ConnectedCU_t *peerInfo, Sctp_Map_t *m, otSpan *pSpan);
 
 int getSetupRequestMetaData(ReportingMessages_t &message, char *data, char *host, uint16_t &port, otSpan *pSpan);
@@ -254,7 +292,7 @@ int receiveDataFromSctp(struct epoll_event *events,
  * @param pSpan
  * @return
  */
-void *getRmrContext(char *rmrAddress, otSpan *pSpan);
+void getRmrContext(sctp_params_t &pSctpParams, otSpan *pSpan);
 
 /**
  *
@@ -385,6 +423,12 @@ void buildJsonMessage(ReportingMessages_t &message);
  */
 string translateRmrErrorMessages(int state);
 
+
+static inline uint64_t rdtscp(uint32_t &aux) {
+    uint64_t rax,rdx;
+    asm volatile ("rdtscp\n" : "=a" (rax), "=d" (rdx), "=c" (aux) : :);
+    return (rdx << 32) + rax;
+}
 #ifndef RIC_SCTP_CONNECTION_FAILURE
 #define RIC_SCTP_CONNECTION_FAILURE  10080
 #endif
diff --git a/config/config.bad b/config/config.bad
new file mode 100644 (file)
index 0000000..980bbd5
--- /dev/null
@@ -0,0 +1,10 @@
+nano=38000
+loglevel=info
+volume=log
+local-ip=127.0.0.1
+stam string
+
+xxx=
+#trace is start, stop
+trace=start
+external-fqdn=e2t.att.com
\ No newline at end of file
diff --git a/config/config.sec b/config/config.sec
new file mode 100644 (file)
index 0000000..bf7689f
--- /dev/null
@@ -0,0 +1,9 @@
+[config]
+nano=38000
+loglevel=info
+volume=log
+local-ip=127.0.0.1
+[xxxyyy]
+#trace is start, stop
+trace=start
+external-fqdn=e2t.att.com
\ No newline at end of file
diff --git a/config/config.secbad b/config/config.secbad
new file mode 100644 (file)
index 0000000..9b5db3d
--- /dev/null
@@ -0,0 +1,9 @@
+[config]
+nano=38000
+loglevel=info
+volume=log
+local-ip=127.0.0.1
+[xxxyyy
+#trace is start, stop
+trace=start
+external-fqdn=e2t.att.com
\ No newline at end of file