Wrapper code on top of generated asn1c code

Add wrapper on top of generated asn1c code. Wrapper contains
logic for E2AP message encode/decode.

Issue-ID: RIC-773
Change-Id: I033ac8949cc2359701ab1bb2f11a6caecaaecff6
Signed-off-by: subhash kumar singh <subh.singh@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de81724..3dd4de5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -149,7 +149,7 @@
 # enable code to find them after we build them.
 #
 # the source directories need to be explicitly added here
-include_directories( "${srcd}/src/e2ap" )
+include_directories( "${srcd}/src/e2ap" "${srcd}/src/wrapper")
 
 # Compiler flags
 #
@@ -179,11 +179,12 @@
 # Include modules
 #
 add_subdirectory( src/e2ap )
+add_subdirectory( src/wrapper )
 
 # shared and static libraries are built from the same object files.
 #
 add_library(  riclibe2ap SHARED
-	"$<TARGET_OBJECTS:e2ap_objects>;"
+	"$<TARGET_OBJECTS:e2ap_objects>;$<TARGET_OBJECTS:wrapper_objects>;"
 )
 set_target_properties( riclibe2ap
 	PROPERTIES
@@ -195,7 +196,7 @@
 # we only build/export the static archive (.a) if generating a dev package
 if( DEV_PKG )
 	add_library( riclibe2ap_static STATIC
-		"$<TARGET_OBJECTS:e2ap_objects>;"
+		"$<TARGET_OBJECTS:e2ap_objects>;$<TARGET_OBJECTS:wrapper_objects>;"
 	)
 	set_target_properties( riclibe2ap_static
 		PROPERTIES
diff --git a/README b/README
deleted file mode 100644
index 111f9aa..0000000
--- a/README
+++ /dev/null
@@ -1,4 +0,0 @@
-
-This repo contains code that is generated from ASN1 descriptions
-as well as CMake bits that allow it to be used as a submodule
-to other projects.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..315a781
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+# LIBE2AP
+
+## Table of contents
+* [Introduction] (#introduction)
+* [Project folders structure](#project-folders-structure)
+* [Installation guide](#installation-guide)
+  * [Compiling code](#compiling-code)
+
+## Introduction
+This repo contains code that is generated from ASN1 descriptions
+as well as CMake bits that allow it to be used as a submodule
+to other projects.
+
+## Project folder structure
+
+```
+├── src
+│   ├── e2ap        // E2AP v1.0 message structure
+│   └── wrapper     // E2AP message encoding and decoding
+```
+
+## Installation guide
+
+### Compiling code
+
+Use cmake and then make to build code from project root.
+
+```
+$ cmake .
++++ riclibe2ap library install target directory: lib
++++ mmp version from tag: '1;0;0'
++++ pkg name: riclibe2ap-rotten_1.0.0_amd64.deb
+### make package will generate only deb package; cannot find support to generate rpm packages
++++ profiling is off
+-- Configuring done
+-- Generating done
+-- Build files have been written to: <path>/libe2ap
+```
+
+Use make to generate shared library (.so).
+
+```
+$ sudo make 
+```
+
+Use make to install shared library (.so).
+
+```
+$ sudo make install
+```
\ No newline at end of file
diff --git a/src/wrapper/CMakeLists.txt b/src/wrapper/CMakeLists.txt
new file mode 100644
index 0000000..3554140
--- /dev/null
+++ b/src/wrapper/CMakeLists.txt
@@ -0,0 +1,44 @@
+# vim: sw=4 ts=4 noet:
+#
+#==================================================================================
+#   Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved.
+#
+#   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.
+#==================================================================================
+#
+
+
+# pick up everything
+#
+file( GLOB wrapper_files *.c *.h )
+file( GLOB wrapper_headers *.h )
+
+# For clarity: this generates object, not a lib as the CM command implies.
+#
+add_library( wrapper_objects OBJECT ${wrapper_files} )
+
+target_include_directories (
+	wrapper_objects PUBLIC
+	$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+	$<INSTALL_INTERFACE:include>
+	PRIVATE src
+)
+
+# header files should go into .../include/riclibe2ap/
+if( DEV_PKG )
+	install( FILES
+		${wrapper_headers}
+		DESTINATION ${install_inc}
+	)
+endif()
+
diff --git a/src/wrapper/wrapper.c b/src/wrapper/wrapper.c
new file mode 100644
index 0000000..8d5ea7b
--- /dev/null
+++ b/src/wrapper/wrapper.c
@@ -0,0 +1,851 @@
+/*
+ *
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved.
+ *
+ * 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.
+ *
+ */
+
+#include <errno.h>
+#include "wrapper.h"
+
+size_t encode_E2AP_PDU(E2AP_PDU_t* pdu, void* buffer, size_t buf_size)
+{
+    asn_enc_rval_t encode_result;
+    encode_result = aper_encode_to_buffer(&asn_DEF_E2AP_PDU, NULL, pdu, buffer, buf_size);
+    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    if(encode_result.encoded == -1) {
+        fprintf(stderr, "Cannot encode %s: %s\n", encode_result.failed_type->name, strerror(errno));
+        return -1;
+    } else {
+        return encode_result.encoded;
+    }
+}
+
+E2AP_PDU_t* decode_E2AP_PDU(const void* buffer, size_t buf_size)
+{
+    asn_dec_rval_t decode_result;
+    E2AP_PDU_t *pdu = 0;
+    decode_result = aper_decode_complete(NULL, &asn_DEF_E2AP_PDU, (void **)&pdu, buffer, buf_size);
+    if(decode_result.code == RC_OK) {
+        return pdu;
+    } else {
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+        return 0;
+    }
+}
+
+/* RICsubscriptionRequest */
+long e2ap_get_ric_subscription_request_sequence_number(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_initiatingMessage)
+    {
+        InitiatingMessage_t* initiatingMessage = pdu->choice.initiatingMessage;
+        if ( initiatingMessage->procedureCode == ProcedureCode_id_RICsubscription
+            && initiatingMessage->value.present == InitiatingMessage__value_PR_RICsubscriptionRequest)
+        {
+            RICsubscriptionRequest_t *ric_subscription_request = &(initiatingMessage->value.choice.RICsubscriptionRequest);
+            for (int i = 0; i < ric_subscription_request->protocolIEs.list.count; ++i )
+            {
+                if ( ric_subscription_request->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    long sequenceNumber = ric_subscription_request->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                    return sequenceNumber;
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+ssize_t  e2ap_set_ric_subscription_request_sequence_number(void *buffer, size_t buf_size, long sequence_number)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_initiatingMessage)
+    {
+        InitiatingMessage_t* initiatingMessage = pdu->choice.initiatingMessage;
+        if ( initiatingMessage->procedureCode == ProcedureCode_id_RICsubscription
+            && initiatingMessage->value.present == InitiatingMessage__value_PR_RICsubscriptionRequest)
+        {
+            RICsubscriptionRequest_t *ricSubscriptionRequest = &initiatingMessage->value.choice.RICsubscriptionRequest;
+            for (int i = 0; i < ricSubscriptionRequest->protocolIEs.list.count; ++i )
+            {
+                if ( ricSubscriptionRequest->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    ricSubscriptionRequest->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID = sequence_number;
+                    return encode_E2AP_PDU(pdu, buffer, buf_size);
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+ssize_t e2ap_encode_ric_subscription_request_message(void *buffer, size_t buf_size, long ricRequestorID, long ricRequestSequenceNumber, long ranFunctionID, void *eventTriggerDefinition, size_t eventTriggerDefinitionSize, int actionCount, long *actionIds, long* actionTypes, RICactionDefinition *actionDefinitions, RICSubsequentAction *subsequentActionTypes) 
+{
+    E2AP_PDU_t *init = (E2AP_PDU_t *)calloc(1, sizeof(E2AP_PDU_t));
+    if(!init) {
+        fprintf(stderr, "alloc E2AP_PDU failed\n");
+        return -1;
+    }
+    
+    InitiatingMessage_t *initiatingMsg = (InitiatingMessage_t *)calloc(1, sizeof(InitiatingMessage_t));
+    if(!initiatingMsg) {
+        fprintf(stderr, "alloc InitiatingMessage failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    init->choice.initiatingMessage = initiatingMsg;
+    init->present = E2AP_PDU_PR_initiatingMessage;
+
+    initiatingMsg->procedureCode = ProcedureCode_id_RICsubscription;
+    initiatingMsg->criticality = Criticality_reject;
+    initiatingMsg->value.present = InitiatingMessage__value_PR_RICsubscriptionRequest;
+
+    RICsubscriptionRequest_t *subscription_request = &initiatingMsg->value.choice.RICsubscriptionRequest;
+    
+    // request contains 5 IEs
+
+    // RICrequestID
+    RICsubscriptionRequest_IEs_t *ies_reqID = (RICsubscriptionRequest_IEs_t *)calloc(1, sizeof(RICsubscriptionRequest_IEs_t));
+    if(!ies_reqID) {
+        fprintf(stderr, "alloc RICrequestID failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_reqID->criticality = Criticality_reject;
+    ies_reqID->id = ProtocolIE_ID_id_RICrequestID;
+    ies_reqID->value.present = RICsubscriptionRequest_IEs__value_PR_RICrequestID;
+    RICrequestID_t *ricrequest_ie = &ies_reqID->value.choice.RICrequestID;
+    ricrequest_ie->ricRequestorID = ricRequestorID;
+    ricrequest_ie->ricInstanceID = ricRequestSequenceNumber;
+    ASN_SEQUENCE_ADD(&subscription_request->protocolIEs.list, ies_reqID);
+
+    // RICfunctionID
+    RICsubscriptionRequest_IEs_t *ies_ranfunc = (RICsubscriptionRequest_IEs_t *)calloc(1, sizeof(RICsubscriptionRequest_IEs_t));
+    if(!ies_ranfunc) {
+        fprintf(stderr, "alloc RICfunctionID failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_ranfunc->criticality = Criticality_reject;
+    ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
+    ies_ranfunc->value.present = RICsubscriptionRequest_IEs__value_PR_RANfunctionID;
+    RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+    *ranfunction_ie = ranFunctionID;
+    ASN_SEQUENCE_ADD(&subscription_request->protocolIEs.list, ies_ranfunc);
+
+    // RICsubscription
+    RICsubscriptionRequest_IEs_t *ies_subscription = (RICsubscriptionRequest_IEs_t *)calloc(1, sizeof(RICsubscriptionRequest_IEs_t));
+    if(!ies_subscription) {
+        fprintf(stderr, "alloc RICsubscription failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_subscription->criticality = Criticality_reject;
+    ies_subscription->id = ProtocolIE_ID_id_RICsubscriptionDetails;
+    ies_subscription->value.present = RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails;
+    RICsubscriptionDetails_t *ricsubscription_ie = &ies_subscription->value.choice.RICsubscriptionDetails;
+
+    // RICeventTriggerDefinition
+    RICeventTriggerDefinition_t *eventTrigger = &ricsubscription_ie->ricEventTriggerDefinition;
+    eventTrigger->buf = (uint8_t *)calloc(1, eventTriggerDefinitionSize);
+    if(!eventTrigger->buf) {
+        fprintf(stderr, "alloc eventTrigger failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    memcpy(eventTrigger->buf, eventTriggerDefinition, eventTriggerDefinitionSize);
+    eventTrigger->size = eventTriggerDefinitionSize;
+    
+    // RICactions-ToBeSetup-List
+    RICactions_ToBeSetup_List_t *ricActions = &ricsubscription_ie->ricAction_ToBeSetup_List;
+    int index = 0;
+    while (index < actionCount) {
+        RICaction_ToBeSetup_ItemIEs_t *ies_action = (RICaction_ToBeSetup_ItemIEs_t *)calloc(1, sizeof(RICaction_ToBeSetup_ItemIEs_t));
+        if(!ies_action) {
+            fprintf(stderr, "alloc RICaction failed\n");
+            ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+            return -1;
+        }
+
+        ies_action->criticality = Criticality_reject;
+        ies_action->id = ProtocolIE_ID_id_RICaction_ToBeSetup_Item;
+        ies_action->value.present = RICaction_ToBeSetup_ItemIEs__value_PR_RICaction_ToBeSetup_Item;
+        RICaction_ToBeSetup_Item_t *ricaction_ie = &ies_action->value.choice.RICaction_ToBeSetup_Item;
+        ricaction_ie->ricActionID = actionIds[index];
+        ricaction_ie->ricActionType = actionTypes[index];
+
+        int actionDefinitionSize = actionDefinitions[index].size;
+        if(actionDefinitionSize != 0) {
+            RICactionDefinition_t *actionDefinition = ricaction_ie->ricActionDefinition;
+            
+            actionDefinition->buf = (uint8_t *)calloc(1, actionDefinitionSize);
+            if(!actionDefinition->buf) {
+                fprintf(stderr, "alloc actionDefinition[%d] failed\n", index);
+                ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+                return -1;
+            }
+
+            memcpy(actionDefinition->buf, actionDefinitions[index].actionDefinition, actionDefinitionSize);
+            actionDefinition->size = actionDefinitionSize;
+        }
+
+        if(subsequentActionTypes[index].isValid != 0) {
+            RICsubsequentAction_t *subsequentAction = ricaction_ie->ricSubsequentAction;
+            subsequentAction->ricSubsequentActionType = subsequentActionTypes[index].subsequentActionType;
+            subsequentAction->ricTimeToWait = subsequentActionTypes[index].timeToWait;
+        }
+
+        ASN_SEQUENCE_ADD(&ricActions->list, ies_action);
+        index++;
+    }
+    ASN_SEQUENCE_ADD(&subscription_request->protocolIEs.list, ies_subscription);
+
+    return encode_E2AP_PDU(init, buffer, buf_size);
+}
+
+/* RICsubscriptionResponse */
+long e2ap_get_ric_subscription_response_sequence_number(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_successfulOutcome )
+    {
+        SuccessfulOutcome_t* successfulOutcome = pdu->choice.successfulOutcome;
+        if ( successfulOutcome->procedureCode == ProcedureCode_id_RICsubscription
+            && successfulOutcome->value.present == SuccessfulOutcome__value_PR_RICsubscriptionResponse)
+        {
+            RICsubscriptionResponse_t *ricSubscriptionResponse = &successfulOutcome->value.choice.RICsubscriptionResponse;
+            for (int i = 0; i < ricSubscriptionResponse->protocolIEs.list.count; ++i )
+            {
+                if ( ricSubscriptionResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    long sequenceNumber = ricSubscriptionResponse->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                    return sequenceNumber;
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+ssize_t  e2ap_set_ric_subscription_response_sequence_number(void *buffer, size_t buf_size, long sequence_number)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_successfulOutcome )
+    {
+        SuccessfulOutcome_t* successfulOutcome = pdu->choice.successfulOutcome;
+        if ( successfulOutcome->procedureCode == ProcedureCode_id_RICsubscription
+            && successfulOutcome->value.present == SuccessfulOutcome__value_PR_RICsubscriptionResponse)
+        {
+            RICsubscriptionResponse_t *ricSubscriptionResponse = &successfulOutcome->value.choice.RICsubscriptionResponse;
+            for (int i = 0; i < ricSubscriptionResponse->protocolIEs.list.count; ++i )
+            {
+                if ( ricSubscriptionResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    ricSubscriptionResponse->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID = sequence_number;
+                    return encode_E2AP_PDU(pdu, buffer, buf_size);
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+RICsubscriptionResponseMsg* e2ap_decode_ric_subscription_response_message(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_successfulOutcome)
+    {
+        SuccessfulOutcome_t* successfulOutcome = pdu->choice.successfulOutcome;
+        if ( successfulOutcome->procedureCode == ProcedureCode_id_RICsubscription
+            && successfulOutcome->value.present == SuccessfulOutcome__value_PR_RICsubscriptionResponse)
+        {
+            RICsubscriptionResponse_t *subscriptionResponse = &(successfulOutcome->value.choice.RICsubscriptionResponse);
+            RICsubscriptionResponseMsg *msg = (RICsubscriptionResponseMsg *)calloc(1, sizeof(RICsubscriptionResponseMsg));
+            for (int i = 0; i < subscriptionResponse->protocolIEs.list.count; ++i )
+            {
+                if (subscriptionResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID) {
+                    msg->requestorID = subscriptionResponse->protocolIEs.list.array[i]->value.choice.RICrequestID.ricRequestorID;
+                    msg->requestSequenceNumber = subscriptionResponse->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                }
+                else if (subscriptionResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RANfunctionID) {
+                    msg->ranfunctionID = subscriptionResponse->protocolIEs.list.array[i]->value.choice.RANfunctionID;
+                }
+                else if (subscriptionResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICactions_Admitted) {
+                    RICaction_Admitted_List_t *ricActionAdmittedList = &(subscriptionResponse->protocolIEs.list.array[i]->value.choice.RICaction_Admitted_List);
+                    int index = 0;
+                    while (index < ricActionAdmittedList->list.count) {
+                        RICaction_Admitted_ItemIEs_t *ricActionAdmittedItem = (RICaction_Admitted_ItemIEs_t *)ricActionAdmittedList->list.array[index];
+                        if (ricActionAdmittedItem->id == ProtocolIE_ID_id_RICaction_Admitted_Item) {
+                            msg->ricActionAdmittedList.ricActionID[index] = ricActionAdmittedItem->value.choice.RICaction_Admitted_Item.ricActionID;
+                        }
+                        index++;
+                    }
+                    msg->ricActionAdmittedList.count = index;
+                }
+                else if (subscriptionResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICactions_NotAdmitted) {
+                    RICaction_NotAdmitted_List_t *ricActionNotAdmittedList = &(subscriptionResponse->protocolIEs.list.array[i]->value.choice.RICaction_NotAdmitted_List);
+                    int index = 0;
+                    while (index < ricActionNotAdmittedList->list.count) {
+                        RICaction_NotAdmitted_ItemIEs_t *ricActionNotAdmittedItem = (RICaction_NotAdmitted_ItemIEs_t *)ricActionNotAdmittedList->list.array[index];
+                        if (ricActionNotAdmittedItem->id == ProtocolIE_ID_id_RICaction_NotAdmitted_Item) {
+                            msg->ricActionNotAdmittedList.ricActionID[index] = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.ricActionID;
+                            int RICcauseType = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.cause.present;
+                            switch(RICcauseType) {
+                                case Cause_PR_ricRequest:
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseType = Cause_PR_ricRequest;
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseID = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.cause.choice.ricRequest;
+                                    break;
+                                case Cause_PR_ricService:
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseType = Cause_PR_ricService;
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseID = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.cause.choice.ricService;
+                                    break;
+                                case Cause_PR_transport:
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseType = Cause_PR_transport;
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseID = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.cause.choice.transport;
+                                    break;
+                                case Cause_PR_protocol:
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseType = Cause_PR_protocol;
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseID = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.cause.choice.protocol;
+                                    break;
+                                case Cause_PR_misc:
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseType = Cause_PR_misc;
+                                    msg->ricActionNotAdmittedList.ricCause[index].ricCauseID = ricActionNotAdmittedItem->value.choice.RICaction_NotAdmitted_Item.cause.choice.misc;
+                                    break;
+                            }
+                        }
+                        index++;
+                    }
+                    msg->ricActionNotAdmittedList.count = index;
+                }
+            }
+            return msg;
+        }
+    }
+    return NULL;
+}
+
+/* RICsubscriptionFailure */
+long e2ap_get_ric_subscription_failure_sequence_number(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_unsuccessfulOutcome )
+    {
+        UnsuccessfulOutcome_t* unsuccessfulOutcome = pdu->choice.unsuccessfulOutcome;
+        if ( unsuccessfulOutcome->procedureCode == ProcedureCode_id_RICsubscription
+            && unsuccessfulOutcome->value.present == UnsuccessfulOutcome__value_PR_RICsubscriptionFailure)
+        {
+            RICsubscriptionFailure_t *ricSubscriptionFailure = &unsuccessfulOutcome->value.choice.RICsubscriptionFailure;
+            for (int i = 0; i < ricSubscriptionFailure->protocolIEs.list.count; ++i )
+            {
+                if ( ricSubscriptionFailure->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    long sequenceNumber = ricSubscriptionFailure->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                    return sequenceNumber;
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+/* RICsubscriptionDeleteRequest */
+long e2ap_get_ric_subscription_delete_request_sequence_number(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_initiatingMessage )
+    {
+        InitiatingMessage_t* initiatingMessage = pdu->choice.initiatingMessage;
+        if ( initiatingMessage->procedureCode == ProcedureCode_id_RICsubscriptionDelete
+            && initiatingMessage->value.present == InitiatingMessage__value_PR_RICsubscriptionDeleteRequest )
+        {
+            RICsubscriptionDeleteRequest_t *subscriptionDeleteRequest = &initiatingMessage->value.choice.RICsubscriptionDeleteRequest;
+            for (int i = 0; i < subscriptionDeleteRequest->protocolIEs.list.count; ++i )
+            {
+                if ( subscriptionDeleteRequest->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    long sequenceNumber = subscriptionDeleteRequest->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                    return sequenceNumber;
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+ssize_t  e2ap_set_ric_subscription_delete_request_sequence_number(void *buffer, size_t buf_size, long sequence_number)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_initiatingMessage )
+    {
+        InitiatingMessage_t* initiatingMessage = pdu->choice.initiatingMessage;
+        if ( initiatingMessage->procedureCode == ProcedureCode_id_RICsubscriptionDelete
+            && initiatingMessage->value.present == InitiatingMessage__value_PR_RICsubscriptionDeleteRequest )
+        {
+            RICsubscriptionDeleteRequest_t* subscriptionDeleteRequest = &initiatingMessage->value.choice.RICsubscriptionDeleteRequest;
+            for (int i = 0; i < subscriptionDeleteRequest->protocolIEs.list.count; ++i )
+            {
+                if ( subscriptionDeleteRequest->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    subscriptionDeleteRequest->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID = sequence_number;
+                    return encode_E2AP_PDU(pdu, buffer, buf_size);
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+ssize_t e2ap_encode_ric_subscription_delete_request_message(void *buffer, size_t buf_size, long ricRequestorID, long ricRequestSequenceNumber, long ranFunctionID)
+{
+    E2AP_PDU_t *init = (E2AP_PDU_t *)calloc(1, sizeof(E2AP_PDU_t));
+    if(!init) {
+        fprintf(stderr, "alloc E2AP_PDU failed\n");
+        return -1;
+    }
+
+    InitiatingMessage_t *initiatingMsg = (InitiatingMessage_t *)calloc(1, sizeof(InitiatingMessage_t));
+    if(!initiatingMsg) {
+        fprintf(stderr, "alloc InitiatingMessage failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    init->choice.initiatingMessage = initiatingMsg;
+    init->present = E2AP_PDU_PR_initiatingMessage;
+
+    initiatingMsg->procedureCode = ProcedureCode_id_RICsubscriptionDelete;
+    initiatingMsg->criticality = Criticality_reject;
+    initiatingMsg->value.present = InitiatingMessage__value_PR_RICsubscriptionDeleteRequest;
+
+    RICsubscriptionDeleteRequest_t *subscription_delete_request = &initiatingMsg->value.choice.RICsubscriptionDeleteRequest;
+    
+    // request contains 2 IEs
+
+    // RICrequestID
+    RICsubscriptionDeleteRequest_IEs_t *ies_reqID = (RICsubscriptionDeleteRequest_IEs_t *)calloc(1, sizeof(RICsubscriptionDeleteRequest_IEs_t));
+    if(!ies_reqID) {
+        fprintf(stderr, "alloc RICrequestID failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_reqID->criticality = Criticality_reject;
+    ies_reqID->id = ProtocolIE_ID_id_RICrequestID;
+    ies_reqID->value.present = RICsubscriptionDeleteRequest_IEs__value_PR_RICrequestID;
+    RICrequestID_t *ricrequest_ie = &ies_reqID->value.choice.RICrequestID;
+    ricrequest_ie->ricRequestorID = ricRequestorID;
+    ricrequest_ie->ricInstanceID = ricRequestSequenceNumber;
+    ASN_SEQUENCE_ADD(&subscription_delete_request->protocolIEs.list, ies_reqID);
+
+    // RICfunctionID
+    RICsubscriptionDeleteRequest_IEs_t *ies_ranfunc = (RICsubscriptionDeleteRequest_IEs_t *)calloc(1, sizeof(RICsubscriptionDeleteRequest_IEs_t));
+    if(!ies_ranfunc) {
+        fprintf(stderr, "alloc RICfunctionID failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_ranfunc->criticality = Criticality_reject;
+    ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
+    ies_ranfunc->value.present = RICsubscriptionDeleteRequest_IEs__value_PR_RANfunctionID;
+    RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+    *ranfunction_ie = ranFunctionID;
+    ASN_SEQUENCE_ADD(&subscription_delete_request->protocolIEs.list, ies_ranfunc);
+
+    return encode_E2AP_PDU(init, buffer, buf_size);
+}
+
+/* RICsubscriptionDeleteResponse */
+long e2ap_get_ric_subscription_delete_response_sequence_number(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_successfulOutcome )
+    {
+        SuccessfulOutcome_t* successfulOutcome = pdu->choice.successfulOutcome;
+        if ( successfulOutcome->procedureCode == ProcedureCode_id_RICsubscriptionDelete
+            && successfulOutcome->value.present == SuccessfulOutcome__value_PR_RICsubscriptionDeleteResponse )
+        {
+            RICsubscriptionDeleteResponse_t* subscriptionDeleteResponse = &successfulOutcome->value.choice.RICsubscriptionDeleteResponse;
+            for (int i = 0; i < subscriptionDeleteResponse->protocolIEs.list.count; ++i )
+            {
+                if ( subscriptionDeleteResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    long sequenceNumber = subscriptionDeleteResponse->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                    return sequenceNumber;
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+ssize_t  e2ap_set_ric_subscription_delete_response_sequence_number(void *buffer, size_t buf_size, long sequence_number)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_successfulOutcome )
+    {
+        SuccessfulOutcome_t* successfulOutcome = pdu->choice.successfulOutcome;
+        if ( successfulOutcome->procedureCode == ProcedureCode_id_RICsubscriptionDelete
+            && successfulOutcome->value.present == SuccessfulOutcome__value_PR_RICsubscriptionDeleteResponse )
+        {
+            RICsubscriptionDeleteResponse_t* subscriptionDeleteResponse = &successfulOutcome->value.choice.RICsubscriptionDeleteResponse;
+            for (int i = 0; i < subscriptionDeleteResponse->protocolIEs.list.count; ++i )
+            {
+                if ( subscriptionDeleteResponse->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    subscriptionDeleteResponse->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID = sequence_number;
+                    return encode_E2AP_PDU(pdu, buffer, buf_size);
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+/* RICsubscriptionDeleteFailure */
+long e2ap_get_ric_subscription_delete_failure_sequence_number(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_unsuccessfulOutcome )
+    {
+        UnsuccessfulOutcome_t* unsuccessfulOutcome = pdu->choice.unsuccessfulOutcome;
+        if ( unsuccessfulOutcome->procedureCode == ProcedureCode_id_RICsubscriptionDelete
+            && unsuccessfulOutcome->value.present == UnsuccessfulOutcome__value_PR_RICsubscriptionDeleteFailure)
+        {
+            RICsubscriptionDeleteFailure_t *ricSubscriptionDeleteFailure = &unsuccessfulOutcome->value.choice.RICsubscriptionDeleteFailure;
+            for (int i = 0; i < ricSubscriptionDeleteFailure->protocolIEs.list.count; ++i )
+            {
+                if ( ricSubscriptionDeleteFailure->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID )
+                {
+                    long sequenceNumber = ricSubscriptionDeleteFailure->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                    ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                    return sequenceNumber;
+                }
+            }
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return -1;
+}
+
+/* RICindication */
+
+RICindicationMsg* e2ap_decode_ric_indication_message(void *buffer, size_t buf_size)
+{
+    E2AP_PDU_t *pdu = decode_E2AP_PDU(buffer, buf_size);
+    if ( pdu != NULL && pdu->present == E2AP_PDU_PR_initiatingMessage)
+    {
+        InitiatingMessage_t* initiatingMessage = pdu->choice.initiatingMessage;
+        if ( initiatingMessage->procedureCode == ProcedureCode_id_RICindication
+            && initiatingMessage->value.present == InitiatingMessage__value_PR_RICindication)
+        {
+            RICindication_t *indication = &(initiatingMessage->value.choice.RICindication);
+            RICindicationMsg *msg = (RICindicationMsg *)calloc(1, sizeof(RICindicationMsg));
+            for (int i = 0; i < indication->protocolIEs.list.count; ++i )
+            {
+                if (indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICrequestID) {
+                    msg->requestorID = indication->protocolIEs.list.array[i]->value.choice.RICrequestID.ricRequestorID;
+                    msg->requestSequenceNumber = indication->protocolIEs.list.array[i]->value.choice.RICrequestID.ricInstanceID;
+                }
+                else if (indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RANfunctionID) {
+                    msg->ranfunctionID = indication->protocolIEs.list.array[i]->value.choice.RANfunctionID;
+                }
+                else if (indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICactionID) {
+                    msg->actionID = indication->protocolIEs.list.array[i]->value.choice.RICactionID;
+                }
+                else if(indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICindicationSN) {
+                    msg->indicationSN = indication->protocolIEs.list.array[i]->value.choice.RICindicationSN;
+                }
+                else if(indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICindicationType) {
+                    msg->indicationType = indication->protocolIEs.list.array[i]->value.choice.RICindicationType;
+                }
+                else if(indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICindicationHeader) {
+                    size_t headerSize = indication->protocolIEs.list.array[i]->value.choice.RICindicationHeader.size;
+                    msg->indicationHeader = calloc(1, headerSize);
+                    if (!msg->indicationHeader) {
+                        fprintf(stderr, "alloc RICindicationHeader failed\n");
+                        e2ap_free_decoded_ric_indication_message(msg);
+                        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                        return NULL;
+                    }
+
+                    memcpy(msg->indicationHeader, indication->protocolIEs.list.array[i]->value.choice.RICindicationHeader.buf, headerSize);
+                    msg->indicationHeaderSize = headerSize;
+                }
+                else if(indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICindicationMessage) {
+                    size_t messsageSize = indication->protocolIEs.list.array[i]->value.choice.RICindicationMessage.size;
+                    msg->indicationMessage = calloc(1, messsageSize);
+                    if (!msg->indicationMessage) {
+                        fprintf(stderr, "alloc RICindicationMessage failed\n");
+                        e2ap_free_decoded_ric_indication_message(msg);
+                        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                        return NULL;
+                    }
+
+                    memcpy(msg->indicationMessage, indication->protocolIEs.list.array[i]->value.choice.RICindicationMessage.buf, messsageSize);
+                    msg->indicationMessageSize = messsageSize;
+                }
+                else if(indication->protocolIEs.list.array[i]->id == ProtocolIE_ID_id_RICcallProcessID) {
+                    size_t callProcessIDSize = indication->protocolIEs.list.array[i]->value.choice.RICcallProcessID.size;
+                    msg->callProcessID = calloc(1, callProcessIDSize);
+                    if (!msg->callProcessID) {
+                        fprintf(stderr, "alloc RICcallProcessID failed\n");
+                        e2ap_free_decoded_ric_indication_message(msg);
+                        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+                        return NULL;
+                    }
+
+                    memcpy(msg->callProcessID, indication->protocolIEs.list.array[i]->value.choice.RICcallProcessID.buf, callProcessIDSize);
+                    msg->callProcessIDSize = callProcessIDSize;
+                }
+            }
+            return msg;
+        }
+    }
+
+    if(pdu != NULL) 
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+    return NULL;
+}
+
+
+/* RICControl */
+ssize_t e2ap_encode_ric_control_request_message(void *buffer, size_t buf_size, long ricRequestorID, long ricRequestSequenceNumber, long ranFunctionID, void *callProcessIDBuffer, size_t callProcessIDSize, void *controlHeaderBuffer, size_t controlHeaderSize, void *controlMessageBuffer, size_t controlMessageSize, long controlAckRequest)
+{
+    E2AP_PDU_t *init = (E2AP_PDU_t *)calloc(1, sizeof(E2AP_PDU_t));
+    if (!init)
+    {
+        fprintf(stderr, "alloc E2AP_PDU failed\n");
+        return -1;
+    }
+
+    InitiatingMessage_t *initiatingMsg = (InitiatingMessage_t *)calloc(1, sizeof(InitiatingMessage_t));
+    if (!initiatingMsg)
+    {
+        fprintf(stderr, "alloc InitiatingMessage failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    init->choice.initiatingMessage = initiatingMsg;
+    init->present = E2AP_PDU_PR_initiatingMessage;
+
+    initiatingMsg->procedureCode = ProcedureCode_id_RICcontrol;
+    initiatingMsg->criticality = Criticality_reject;
+    initiatingMsg->value.present = InitiatingMessage__value_PR_RICcontrolRequest;
+
+    RICcontrolRequest_t *control_request = &(initiatingMsg->value.choice.RICcontrolRequest);
+
+    // request contains 6 IEs
+
+    // RICrequestID
+    RICcontrolRequest_IEs_t *ies_reqID = (RICcontrolRequest_IEs_t *)calloc(1, sizeof(RICcontrolRequest_IEs_t));
+    if (!ies_reqID)
+    {
+        fprintf(stderr, "alloc RICrequestID failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_reqID->criticality = Criticality_reject;
+    ies_reqID->id = ProtocolIE_ID_id_RICrequestID;
+    ies_reqID->value.present = RICcontrolRequest_IEs__value_PR_RICrequestID;
+    RICrequestID_t *ricrequest_ie = &ies_reqID->value.choice.RICrequestID;
+    ricrequest_ie->ricRequestorID = ricRequestorID;
+    ricrequest_ie->ricInstanceID = ricRequestSequenceNumber;
+    ASN_SEQUENCE_ADD(&control_request->protocolIEs.list, ies_reqID);
+
+    // RICfunctionID
+    RICcontrolRequest_IEs_t *ies_ranfunc = (RICcontrolRequest_IEs_t *)calloc(1, sizeof(RICcontrolRequest_IEs_t));
+    if (!ies_ranfunc)
+    {
+        fprintf(stderr, "alloc RICfunctionID failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_ranfunc->criticality = Criticality_reject;
+    ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
+    ies_ranfunc->value.present = RICcontrolRequest_IEs__value_PR_RANfunctionID;
+    RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+    *ranfunction_ie = ranFunctionID;
+    ASN_SEQUENCE_ADD(&control_request->protocolIEs.list, ies_ranfunc);
+
+    // RICcallProcessID
+    if (callProcessIDBuffer != NULL)
+    {
+        RICcontrolRequest_IEs_t *ies_callproc = (RICcontrolRequest_IEs_t *)calloc(1, sizeof(RICcontrolRequest_IEs_t));
+        if (!ies_callproc)
+        {
+            fprintf(stderr, "alloc RICcallProcessID failed\n");
+            ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+            return -1;
+        }
+
+        ies_callproc->criticality = Criticality_reject;
+        ies_callproc->id = ProtocolIE_ID_id_RICcallProcessID;
+        ies_callproc->value.present = RICcontrolRequest_IEs__value_PR_RICcallProcessID;
+        RICcallProcessID_t *riccallprocess_ie = &ies_callproc->value.choice.RICcallProcessID;
+
+        riccallprocess_ie->buf = (uint8_t *)calloc(1, callProcessIDSize);
+        if (!riccallprocess_ie->buf)
+        {
+            fprintf(stderr, "alloc RICcallProcessID buf failed\n");
+            ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+            return -1;
+        }
+
+        memcpy(riccallprocess_ie->buf, callProcessIDBuffer, callProcessIDSize);
+        riccallprocess_ie->size = callProcessIDSize;
+
+        ASN_SEQUENCE_ADD(&control_request->protocolIEs.list, ies_callproc);
+    }
+
+    // RICcontrolHeader
+    RICcontrolRequest_IEs_t *ies_ctlheader = (RICcontrolRequest_IEs_t *)calloc(1, sizeof(RICcontrolRequest_IEs_t));
+    if (!ies_ctlheader)
+    {
+        fprintf(stderr, "alloc RICcontrolHeader failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_ctlheader->criticality = Criticality_reject;
+    ies_ctlheader->id = ProtocolIE_ID_id_RICcontrolHeader;
+    ies_ctlheader->value.present = RICcontrolRequest_IEs__value_PR_RICcontrolHeader;
+    RICcontrolHeader_t *ricctlheader_ie = &ies_ctlheader->value.choice.RICcontrolHeader;
+
+    ricctlheader_ie->buf = (uint8_t *)calloc(1, controlHeaderSize);
+    if (!ricctlheader_ie->buf)
+    {
+        fprintf(stderr, "alloc RICcontrolHeader buf failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    memcpy(ricctlheader_ie->buf, controlHeaderBuffer, controlHeaderSize);
+    ricctlheader_ie->size = controlHeaderSize;
+
+    ASN_SEQUENCE_ADD(&control_request->protocolIEs.list, ies_ctlheader);
+
+    // RICcontrolMessage
+    RICcontrolRequest_IEs_t *ies_ctlmsg = (RICcontrolRequest_IEs_t *)calloc(1, sizeof(RICcontrolRequest_IEs_t));
+    if (!ies_ctlmsg)
+    {
+        fprintf(stderr, "alloc RICcontrolMessage failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    ies_ctlmsg->criticality = Criticality_reject;
+    ies_ctlmsg->id = ProtocolIE_ID_id_RICcontrolMessage;
+    ies_ctlmsg->value.present = RICcontrolRequest_IEs__value_PR_RICcontrolMessage;
+    RICcontrolMessage_t *ricctlmsg_ie = &ies_ctlmsg->value.choice.RICcontrolMessage;
+
+    ricctlmsg_ie->buf = (uint8_t *)calloc(1, controlMessageSize);
+    if (!ricctlmsg_ie->buf)
+    {
+        fprintf(stderr, "alloc RICcontrolMessage buf failed\n");
+        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+        return -1;
+    }
+
+    memcpy(ricctlmsg_ie->buf, controlMessageBuffer, controlMessageSize);
+    ricctlmsg_ie->size = controlMessageSize;
+
+    ASN_SEQUENCE_ADD(&control_request->protocolIEs.list, ies_ctlmsg);
+
+    // RICcontrolAckRequest
+    if (controlAckRequest != -1)
+    {
+        RICcontrolRequest_IEs_t *ies_ctlackreq = (RICcontrolRequest_IEs_t *)calloc(1, sizeof(RICcontrolRequest_IEs_t));
+        if (!ies_ctlackreq)
+        {
+            fprintf(stderr, "alloc RICcontrolAckRequest failed\n");
+            ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, init);
+            return -1;
+        }
+
+        ies_ctlackreq->criticality = Criticality_reject;
+        ies_ctlackreq->id = ProtocolIE_ID_id_RICcontrolAckRequest;
+        ies_ctlackreq->value.present = RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest;
+        RICcontrolAckRequest_t *ricctlackreq_ie = &ies_ctlackreq->value.choice.RICcontrolAckRequest;
+        *ricctlackreq_ie = controlAckRequest;
+        ASN_SEQUENCE_ADD(&control_request->protocolIEs.list, ies_ctlackreq);
+    }
+
+    return encode_E2AP_PDU(init, buffer, buf_size);
+}
+
+void e2ap_free_decoded_ric_indication_message(RICindicationMsg* msg) {
+    if(msg == NULL) {
+        return;
+    }
+
+    if(msg->indicationHeader != NULL) {
+        free(msg->indicationHeader);
+        msg->indicationHeader = NULL;
+    }
+    if(msg->indicationMessage != NULL) {
+        free(msg->indicationMessage);
+        msg->indicationMessage = NULL;
+    }
+    if(msg->callProcessID != NULL) {
+        free(msg->callProcessID);
+        msg->callProcessID = NULL;
+    }
+    free(msg);
+    msg = NULL;
+}
diff --git a/src/wrapper/wrapper.h b/src/wrapper/wrapper.h
new file mode 100644
index 0000000..f5cbb5d
--- /dev/null
+++ b/src/wrapper/wrapper.h
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef	_WRAPPER_H_
+#define	_WRAPPER_H_
+
+#include "RICsubscriptionRequest.h"
+#include "RICsubscriptionResponse.h"
+#include "RICsubscriptionDeleteRequest.h"
+#include "RICsubscriptionDeleteResponse.h"
+#include "RICcontrolRequest.h"
+#include "RICindication.h"
+#include "E2AP-PDU.h"
+#include "InitiatingMessage.h"
+#include "SuccessfulOutcome.h"
+#include "UnsuccessfulOutcome.h"
+#include "ProtocolIE-Container.h"
+#include "ProtocolIE-Field.h"
+#include "RICactionDefinition.h"
+#include "RICsubsequentAction.h"
+#include "CauseRIC.h"
+
+typedef struct RICindicationMessage {
+	long requestorID;
+	long requestSequenceNumber;
+	long ranfunctionID;
+	long actionID;
+	long indicationSN;
+	long indicationType;
+	uint8_t *indicationHeader;
+	size_t indicationHeaderSize;
+	uint8_t *indicationMessage;
+	size_t indicationMessageSize;
+	uint8_t *callProcessID;
+	size_t callProcessIDSize;
+} RICindicationMsg;
+
+typedef struct RICcauseItem {
+	int ricCauseType;
+	long ricCauseID;
+} RICcauseItem;
+
+typedef struct RICactionAdmittedList {
+	long ricActionID[16];
+	int count;
+} RICactionAdmittedList;
+
+typedef struct RICactionNotAdmittedList {
+	long ricActionID[16];
+	RICcauseItem ricCause[16];
+	int count;
+} RICactionNotAdmittedList;
+
+typedef struct RICsubscriptionResponseMessage {
+	long requestorID;
+	long requestSequenceNumber;
+	long ranfunctionID;
+	RICactionAdmittedList ricActionAdmittedList;
+	RICactionNotAdmittedList ricActionNotAdmittedList;
+} RICsubscriptionResponseMsg;
+
+typedef struct RICactionDefinition {
+	uint8_t *actionDefinition;
+	int size;
+} RICactionDefinition;
+
+typedef struct RICSubsequentAction {
+	int isValid;
+	long subsequentActionType;
+	long timeToWait;
+} RICSubsequentAction;
+
+size_t encode_E2AP_PDU(E2AP_PDU_t* pdu, void* buffer, size_t buf_size);
+E2AP_PDU_t* decode_E2AP_PDU(const void* buffer, size_t buf_size);
+
+/* RICsubscriptionRequest */
+long e2ap_get_ric_subscription_request_sequence_number(void *buffer, size_t buf_size);
+ssize_t  e2ap_set_ric_subscription_request_sequence_number(void *buffer, size_t buf_size, long sequence_number);
+ssize_t e2ap_encode_ric_subscription_request_message(void *buffer, size_t buf_size, long ricRequestorID, long ricRequestSequenceNumber, long ranFunctionID, void *eventTriggerDefinition, size_t eventTriggerDefinitionSize, int actionCount, long *actionIds, long* actionTypes, RICactionDefinition *actionDefinitions, RICSubsequentAction *subsequentActionTypes);
+
+/* RICsubscriptionResponse */
+long e2ap_get_ric_subscription_response_sequence_number(void *buffer, size_t buf_size);
+ssize_t  e2ap_set_ric_subscription_response_sequence_number(void *buffer, size_t buf_size, long sequence_number);
+RICsubscriptionResponseMsg* e2ap_decode_ric_subscription_response_message(void *buffer, size_t buf_size);
+
+/* RICsubscriptionFailure */
+long e2ap_get_ric_subscription_failure_sequence_number(void *buffer, size_t buf_size);
+
+/* RICsubscriptionDeleteRequest */
+long e2ap_get_ric_subscription_delete_request_sequence_number(void *buffer, size_t buf_size);
+ssize_t  e2ap_set_ric_subscription_delete_request_sequence_number(void *buffer, size_t buf_size, long sequence_number);
+ssize_t e2ap_encode_ric_subscription_delete_request_message(void *buffer, size_t buf_size, long ricRequestorID, long ricRequestSequenceNumber, long ranFunctionID);
+
+/* RICsubscriptionDeleteResponse */
+long e2ap_get_ric_subscription_delete_response_sequence_number(void *buffer, size_t buf_size);
+ssize_t  e2ap_set_ric_subscription_delete_response_sequence_number(void *buffer, size_t buf_size, long sequence_number);
+
+/* RICsubscriptionDeleteFailure */
+long e2ap_get_ric_subscription_delete_failure_sequence_number(void *buffer, size_t buf_size);
+
+/* RICindication */
+RICindicationMsg* e2ap_decode_ric_indication_message(void *buffer, size_t buf_size);
+void e2ap_free_decoded_ric_indication_message(RICindicationMsg* msg);
+
+/* RICControl */
+ssize_t e2ap_encode_ric_control_request_message(void *buffer, size_t buf_size, long ricRequestorID, long ricRequestSequenceNumber, long ranFunctionID, void *callProcessIDBuffer, size_t callProcessIDSize, void *controlHeaderBuffer, size_t controlHeaderSize, void *controlMessageBuffer, size_t controlMessageSize, long controlAckRequest);
+
+#endif /* _WRAPPER_H_ */