Incorporating A1 HealthCheck functionality 83/3083/2
authorsjana <sj492a@att.com>
Tue, 31 Mar 2020 16:14:06 +0000 (12:14 -0400)
committersjana <sj492a@att.com>
Tue, 31 Mar 2020 16:18:13 +0000 (12:18 -0400)
Issue-ID: RICAPP-65

Signed-off-by: sjana <sj492a@att.com>
Change-Id: I1147768efdc0e3f149045a20d94ab474f7fd61fe

36 files changed:
src/Makefile
src/README
src/hw_xapp_main.cc
src/routes.txt
src/run_xapp.sh
src/xapp-formats/e2ap/e2ap_control.cc [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_control.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_control_helper.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_control_response.cc [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_control_response.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_indication.cc [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_indication.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/e2ap_indication_helper.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/generic_helpers.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/response_helper.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_delete_request.cc [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_delete_request.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_delete_response.cc [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_delete_response.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_helper.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_request.cc [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_request.hpp [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_response.cc [new file with mode: 0644]
src/xapp-formats/e2ap/subscription_response.hpp [new file with mode: 0644]
src/xapp-formats/e2sm/e2sm.cc [new file with mode: 0644]
src/xapp-formats/e2sm/e2sm.hpp [new file with mode: 0644]
src/xapp-formats/e2sm/e2sm_helpers.hpp [new file with mode: 0644]
src/xapp-mgmt/format_helper.hpp [new file with mode: 0644]
src/xapp-mgmt/msgs_proc.cc
src/xapp-mgmt/msgs_proc.hpp
src/xapp-mgmt/subs_mgmt.cc
src/xapp-mgmt/subs_mgmt.hpp
src/xapp-utils/xapp_rmr.cc
src/xapp-utils/xapp_rmr.hpp
src/xapp.cc
src/xapp.hpp

index aebc506..eb52483 100755 (executable)
@@ -7,14 +7,14 @@ UTILSRC=./xapp-utils
 MSGSRC:=./xapp-mgmt
 
 ASNSRC:=../asn1c_defs
-E2APSRC:=./xapp-asn/e2ap
-E2SMSRC:=./xapp-asn/e2sm
+E2APSRC:=./xapp-formats/e2ap
+E2SMSRC:=./xapp-formats/e2sm
 
 ####### Logging library and flags
 CLOGFLAGS:= `pkg-config mdclog --cflags`
 LOG_LIBS:= `pkg-config mdclog --libs`
 CURL_LIBS:= `pkg-config libcurl --libs`
-RNIB_LIBS:= -pthread /usr/local/lib/rnibreader.a
+RNIB_LIBS:= -pthread /usr/local/lib/rnibreader_old.a
 ######## Keep include dirs separate so we have transparency
 
 
@@ -76,4 +76,4 @@ install: hw_xapp_main
        install  -D hw_xapp_main  /usr/local/bin/hw_xapp_main
 
 clean:
-       -rm *.o $(ASNSRC)/*.o  $(E2APSRC)/*.o $(UTILSRC)/*.o $(E2SMSRC)/*.o  $(MSGSRC)/*.o $(SRC)/*.o hw_xapp_main 
+       -rm *.o $(ASNSRC)/*.o $(E2APSRC)/*.o $(UTILSRC)/*.o $(E2SMSRC)/*.o  $(MSGSRC)/*.o $(SRC)/*.o hw_xapp_main 
index 2c70d42..41a7ee3 100644 (file)
@@ -23,3 +23,12 @@ It is required to have following features
 3) SDL Access
 4) Health Check
 5)...
+
+
+
+
+Steps for installation/running HWXapp.
+
+$ source ./run_xapp.sh
+$ make
+$ ./hw_xapp_main
index 624d88f..aa51d20 100644 (file)
@@ -61,35 +61,16 @@ int main(int argc, char *argv[]){
 
 
        std::unique_ptr<Xapp> hw_xapp = std::make_unique<Xapp>(std::ref(config),std::ref(*rmr));
+       //hw_xapp->startup();
 
-       //register MsgHandler plugin for a received rmr_buffer
-        std::unique_ptr<XappMsgHandler> mp_handler = std::make_unique<XappMsgHandler>();
-        hw_xapp->register_handler(std::bind(&XappMsgHandler::operator (),mp_handler.get(),std::placeholders::_1,std::placeholders::_2));
-
-        rmr->set_listen(true);
-        hw_xapp->start_xapp_receiver(std::ref(*mp_handler));
-
-        sleep(5);
-
+       std::unique_ptr<XappMsgHandler> mp_handler = std::make_unique<XappMsgHandler>(config[XappSettings::SettingName::XAPP_ID]);
+        //hw_xapp->register_handler(std::bind(&XappMsgHandler::operator (),mp_handler.get(),std::placeholders::_1,std::placeholders::_2));
+       hw_xapp->start_xapp_receiver(std::ref(*mp_handler));
 
        //Delete all subscriptions if any based on Xapp Mode.
        //xapp->shutdown();
 
-       xapp_rmr_header hdr;
-       hdr.message_type = RIC_HEALTH_CHECK_REQ;
-
-       char *strMsg = "HelloWorld: RMR Health Check\0";
-
-       clock_gettime(CLOCK_REALTIME, &(hdr.ts));
-       hdr.payload_length = strlen(strMsg);
-
-       bool res = rmr->xapp_rmr_send(&hdr,(void*)strMsg);
-
-       if (!res){
-          std::cout << "Xapp RMR Send Failure";
-       }
-       usleep(10);
-        while(1){
+       while(1){
                                sleep(1);
                         }
 
index 3dd7cdd..2bcd6d3 100755 (executable)
@@ -2,6 +2,7 @@ newrt|start
 rte|0|localhost:4560
 rte|2|localhost:38000
 rte|100|localhost:4560
+rte|20010|localhost:4560
 rte|10002|localhost:4560
 rte|10005|localhost:4560
 rte|10003|localhost:38000
@@ -14,6 +15,5 @@ rte|12022|localhost:4560
 rte|20000|localhost:4560
 rte|12040|localhost:38000
 rte|20001|localhost:4566
-rte|20011|localhost:4560
 rte|20012|localhost:4560
 newrt|end
index 460e59a..f65a4b7 100755 (executable)
@@ -1,5 +1,6 @@
 #! /bin/bash
 
+export RMR_SEED_RT="routes.txt"
 export RMR_RTG_SVC="9999"
 export XAPP_NAME="HELLOWORLD_XAPP"
 export HW_PORTS="4560"
diff --git a/src/xapp-formats/e2ap/e2ap_control.cc b/src/xapp-formats/e2ap/e2ap_control.cc
new file mode 100644 (file)
index 0000000..e66ddec
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_control_request.c
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#include "e2ap_control.hpp"
+
+// Set up memory allocations for each IE for encoding
+// We are responsible for memory management for each IE for encoding
+// Hence destructor should clear out memory
+// When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called
+// for releasing memory by external calling function)
+ric_control_request::ric_control_request(void){
+
+  e2ap_pdu_obj = 0;
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  initMsg = 0;
+  initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t));
+  assert(initMsg != 0);
+
+  IE_array = 0;
+  IE_array = (E2N_RICcontrolRequest_IEs_t *)calloc(NUM_CONTROL_REQUEST_IES, sizeof(E2N_RICcontrolRequest_IEs_t));
+  assert(IE_array != 0);
+
+  e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage;
+  e2ap_pdu_obj->choice.initiatingMessage = initMsg;
+
+  
+};
+
+
+// Clear assigned protocolIE list from RIC control_request IE container
+ric_control_request::~ric_control_request(void){
+
+  mdclog_write(MDCLOG_DEBUG, "Freeing E2AP Control Request object memory");
+  
+  E2N_RICcontrolRequest_t *ricControl_Request  = &(initMsg->value.choice.RICcontrolRequest);
+  for(int i = 0; i < ricControl_Request->protocolIEs.list.size; i++){
+    ricControl_Request->protocolIEs.list.array[i] = 0;
+  }
+  
+  if (ricControl_Request->protocolIEs.list.size > 0){
+    free(ricControl_Request->protocolIEs.list.array);
+    ricControl_Request->protocolIEs.list.size = 0;
+    ricControl_Request->protocolIEs.list.count = 0;
+  }
+  
+  free(IE_array);
+  free(initMsg);
+  e2ap_pdu_obj->choice.initiatingMessage = 0;
+  
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  mdclog_write(MDCLOG_DEBUG, "Freed E2N_E2AP Control Request object mempory");
+  
+}
+
+
+bool ric_control_request::encode_e2ap_control_request(unsigned char *buf, size_t *size, ric_control_helper & dinput){
+
+  initMsg->procedureCode = E2N_ProcedureCode_id_ricControl;
+  initMsg->criticality = E2N_Criticality_ignore;
+  initMsg->value.present = E2N_InitiatingMessage__value_PR_RICcontrolRequest;
+
+  bool res;
+  
+  res = set_fields(initMsg, dinput);
+  if (!res){
+    return false;
+  }
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(errbuf, errbuf_len);
+    error_string = "Constraints failed for encoding control . Reason = " + error_string;
+    return false;
+  }
+
+  //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+  
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    return false;
+  }
+  else {
+    if(*size < retval.encoded){
+      std::stringstream ss;
+      ss  <<"Error encoding event trigger definition. Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+      error_string = ss.str();
+      return false;
+    }
+  }
+
+  *size = retval.encoded;
+  return true;
+  
+}
+
+bool ric_control_request::set_fields(E2N_InitiatingMessage_t *initMsg, ric_control_helper &dinput){
+  unsigned int ie_index;
+
+  if (initMsg == 0){
+    error_string = "Invalid reference for E2AP Control_Request message in set_fields";
+    return false;
+  }
+
+  E2N_RICcontrolRequest_t * ric_control_request = &(initMsg->value.choice.RICcontrolRequest);
+  ric_control_request->protocolIEs.list.count = 0; // reset 
+  
+  // for(i = 0; i < NUM_CONTROL_REQUEST_IES;i++){
+  //   memset(&(IE_array[i]), 0, sizeof(RICcontrolRequest_IEs_t));
+  // }
+  // Mandatory IE
+  ie_index = 0;
+  E2N_RICcontrolRequest_IEs_t *ies_ricreq = &IE_array[ie_index];  
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = dinput.req_id;
+  ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no;
+  ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index]));
+
+  // Mandatory IE
+  ie_index = 1;
+  E2N_RICcontrolRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICcontrolRequest_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = dinput.func_id;
+  ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index]));
+
+
+  // Mandatory IE
+  ie_index = 2;
+  E2N_RICcontrolRequest_IEs_t *ies_richead = &IE_array[ie_index];
+  ies_richead->criticality = E2N_Criticality_reject;
+  ies_richead->id = E2N_ProtocolIE_ID_id_RICcontrolHeader;
+  ies_richead->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcontrolHeader;
+  E2N_RICcontrolHeader_t *richeader_ie = &ies_richead->value.choice.RICcontrolHeader;
+  richeader_ie->buf = dinput.control_header;
+  richeader_ie->size = dinput.control_header_size;
+  ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index]));
+
+  // Mandatory IE
+  ie_index = 3;
+  E2N_RICcontrolRequest_IEs_t *ies_indmsg = &IE_array[ie_index];
+  ies_indmsg->criticality = E2N_Criticality_reject;
+  ies_indmsg->id = E2N_ProtocolIE_ID_id_RICcontrolMessage;
+  ies_indmsg->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcontrolMessage;
+  E2N_RICcontrolMessage_t *ricmsg_ie = &ies_indmsg->value.choice.RICcontrolMessage;
+  ricmsg_ie->buf = dinput.control_msg;
+  ricmsg_ie->size = dinput.control_msg_size;
+  ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index]));
+
+  // Optional IE
+  ie_index = 4;
+  if (dinput.control_ack >= 0){
+    E2N_RICcontrolRequest_IEs_t *ies_indtyp = &IE_array[ie_index];
+    ies_indtyp->criticality = E2N_Criticality_reject;
+    ies_indtyp->id = E2N_ProtocolIE_ID_id_RICcontrolAckRequest;
+    ies_indtyp->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest;
+    E2N_RICcontrolAckRequest_t *ricackreq_ie = &ies_indtyp->value.choice.RICcontrolAckRequest;
+    *ricackreq_ie = dinput.control_ack;
+    ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index]));
+  }
+
+  // Optional IE
+  ie_index = 5;
+  if(dinput.call_process_id_size > 0){
+    E2N_RICcontrolRequest_IEs_t *ies_callprocid = &IE_array[ie_index];
+    ies_callprocid->criticality = E2N_Criticality_reject;
+    ies_callprocid->id = E2N_ProtocolIE_ID_id_RICcallProcessID;
+    ies_callprocid->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcallProcessID;
+    E2N_RICcallProcessID_t *riccallprocessid_ie = &ies_callprocid->value.choice.RICcallProcessID;
+    riccallprocessid_ie->buf = dinput.call_process_id;
+    riccallprocessid_ie->size = dinput.call_process_id_size;
+    ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index]));
+
+  }
+  return true;
+
+};
+
+  
+
+
+bool ric_control_request:: get_fields(E2N_InitiatingMessage_t * init_msg,  ric_control_helper &dout)
+{
+  if (init_msg == 0){
+    error_string = "Invalid reference for E2AP Control_Request message in get_fields";
+    return false;
+  }
+  
+  for(int edx = 0; edx < init_msg->value.choice.RICcontrolRequest.protocolIEs.list.count; edx++) {
+    E2N_RICcontrolRequest_IEs_t *memb_ptr = init_msg->value.choice.RICcontrolRequest.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICcontrolHeader):
+       dout.control_header = memb_ptr->value.choice.RICcontrolHeader.buf;
+       dout.control_header_size = memb_ptr->value.choice.RICcontrolHeader.size;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICcontrolMessage):
+       dout.control_msg =  memb_ptr->value.choice.RICcontrolMessage.buf;
+       dout.control_msg_size = memb_ptr->value.choice.RICcontrolMessage.size;
+       break;
+
+      case (E2N_ProtocolIE_ID_id_RICcallProcessID):
+       dout.call_process_id =  memb_ptr->value.choice.RICcallProcessID.buf;
+       dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size;
+       break;
+
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID;
+       dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       dout.func_id = memb_ptr->value.choice.RANfunctionID;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICcontrolAckRequest):
+       dout.control_ack = memb_ptr->value.choice.RICcontrolAckRequest;
+       break;
+       
+      default:
+       break;
+      }
+    
+  }
+  
+  return true;
+
+}
+
+E2N_InitiatingMessage_t * ric_control_request::get_message(void)  {
+    return initMsg;
+}
diff --git a/src/xapp-formats/e2ap/e2ap_control.hpp b/src/xapp-formats/e2ap/e2ap_control.hpp
new file mode 100644 (file)
index 0000000..57a2e2d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_indication.h
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#ifndef E2AP_RIC_CONTROL_REQUEST_H_
+#define E2AP_RIC_CONTROL_REQUEST_H_
+
+  
+#include <iostream>
+#include <errno.h>
+#include <mdclog/mdclog.h>
+#include <sstream>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_InitiatingMessage.h>
+#include <E2N_RICcontrolRequest.h>
+#include <E2N_ProtocolIE-Field.h>
+#include "e2ap_control_helper.hpp"
+
+#define NUM_CONTROL_REQUEST_IES 6
+  
+  
+class ric_control_request{
+    
+public:
+  ric_control_request(void);
+  ~ric_control_request(void);
+    
+  bool encode_e2ap_control_request(unsigned char *, size_t *,  ric_control_helper &);
+  E2N_InitiatingMessage_t * get_message (void) ;
+  bool set_fields(E2N_InitiatingMessage_t *, ric_control_helper &);
+  bool get_fields(E2N_InitiatingMessage_t *, ric_control_helper &);
+  std::string get_error(void) const {return error_string ; };
+private:
+
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+  E2N_InitiatingMessage_t *initMsg;
+  E2N_RICcontrolRequest_IEs_t *IE_array;
+  std::string error_string;
+
+  char errbuf[128];
+  size_t errbuf_len = 128;
+};
+
+
+#endif /* E2AP_RIC_CONTROL_REQUEST_H_ */
diff --git a/src/xapp-formats/e2ap/e2ap_control_helper.hpp b/src/xapp-formats/e2ap/e2ap_control_helper.hpp
new file mode 100644 (file)
index 0000000..11f668c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_indication.h
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#ifndef CONTROL_HELPER_H
+#define CONTROL_HELPER_H
+
+// control and indication helper objects are very similar and can be merged into one
+// currently leaving them as two distnict entities till final design becomes clear
+
+typedef struct ric_control_helper ric_control_helper;
+
+struct ric_control_helper{
+  ric_control_helper(void):req_id(1), req_seq_no(1), func_id(0), action_id(1), control_ack(-1), cause(0), sub_cause(0), control_status(1), control_msg(0), control_msg_size(0), control_header(0), control_header_size(0), call_process_id(0), call_process_id_size(0){};
+  
+  long int req_id, req_seq_no, func_id, action_id,  control_ack, cause, sub_cause, control_status;
+  
+  unsigned char* control_msg;
+  size_t control_msg_size;
+  
+  unsigned char* control_header;
+  size_t control_header_size;
+  
+  unsigned char *call_process_id;
+  size_t call_process_id_size;
+  
+};
+
+#endif
diff --git a/src/xapp-formats/e2ap/e2ap_control_response.cc b/src/xapp-formats/e2ap/e2ap_control_response.cc
new file mode 100644 (file)
index 0000000..23ef9ae
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_control_response.c
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#include "e2ap_control_response.hpp"
+
+// Set up the initiating message and also allocate protocolIEs in container
+// Note : this bypasses requirement to use ASN_SEQUENCE_ADD. We can directly
+// assign pointers to the array in ProtocolIE. However, this also leaves us on the
+// hook to manually clear the memory
+
+ric_control_response::ric_control_response(void){
+
+  e2ap_pdu_obj = 0;
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  successMsg = 0;
+  successMsg = (E2N_SuccessfulOutcome_t * )calloc(1, sizeof(E2N_SuccessfulOutcome_t));
+  assert(successMsg != 0);
+
+  successMsg->procedureCode = E2N_ProcedureCode_id_ricControl;
+  successMsg->criticality = E2N_Criticality_reject;
+  successMsg->value.present = E2N_SuccessfulOutcome__value_PR_RICcontrolAcknowledge;
+  
+  unsuccessMsg = 0;
+  unsuccessMsg = (E2N_UnsuccessfulOutcome_t * )calloc(1, sizeof(E2N_UnsuccessfulOutcome_t));
+  assert(unsuccessMsg != 0);
+
+  
+  unsuccessMsg->procedureCode = E2N_ProcedureCode_id_ricControl;
+  unsuccessMsg->criticality = E2N_Criticality_reject;
+  unsuccessMsg->value.present = E2N_UnsuccessfulOutcome__value_PR_RICcontrolFailure;
+
+  IE_array = 0;
+  IE_array = (E2N_RICcontrolAcknowledge_IEs_t *)calloc(NUM_CONTROL_ACKNOWLEDGE_IES, sizeof(E2N_RICcontrolAcknowledge_IEs_t));
+  assert(IE_array != 0);
+
+  E2N_RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge);
+  for(int i = 0; i < NUM_CONTROL_ACKNOWLEDGE_IES; i++){
+    ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), &(IE_array[i]));
+  }
+  
+
+  IE_failure_array = 0;
+  IE_failure_array = (E2N_RICcontrolFailure_IEs_t *)calloc(NUM_CONTROL_FAILURE_IES, sizeof(E2N_RICcontrolFailure_IEs_t));
+  assert(IE_failure_array != 0);
+
+  E2N_RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure);
+  for(int i = 0; i < NUM_CONTROL_FAILURE_IES; i++){
+    ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), &(IE_failure_array[i]));
+  }
+  
+};
+
+
+// Clear assigned protocolIE list from RIC control_request IE container
+ric_control_response::~ric_control_response(void){
+
+  mdclog_write(MDCLOG_DEBUG, "Freeing E2AP Control Response object memory");
+  
+  E2N_RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge);
+  for(int i  = 0; i < ric_acknowledge->protocolIEs.list.size; i++){
+    ric_acknowledge->protocolIEs.list.array[i] = 0;
+  }
+  if (ric_acknowledge->protocolIEs.list.size > 0){
+    free(ric_acknowledge->protocolIEs.list.array);
+    ric_acknowledge->protocolIEs.list.array = 0;
+    ric_acknowledge->protocolIEs.list.count = 0;
+  }
+
+  E2N_RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure);
+  for(int i  = 0; i < ric_failure->protocolIEs.list.size; i++){
+    ric_failure->protocolIEs.list.array[i] = 0;
+  }
+  if (ric_failure->protocolIEs.list.size > 0){
+    free(ric_failure->protocolIEs.list.array);
+    ric_failure->protocolIEs.list.array = 0;
+    ric_failure->protocolIEs.list.count = 0;
+  }
+  
+  free(IE_array);
+  free(IE_failure_array);
+  free(successMsg);
+  free(unsuccessMsg);
+
+  e2ap_pdu_obj->choice.initiatingMessage = 0;
+  e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage;
+  
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  mdclog_write(MDCLOG_DEBUG, "Freed E2AP Control Response object mempory");
+}
+
+
+bool ric_control_response::encode_e2ap_control_response(unsigned char *buf, size_t *size, ric_control_helper & dinput, bool is_success){
+
+  bool res;
+  if (is_success){
+    res = set_fields(successMsg, dinput);
+  }
+  else{
+    res = set_fields(unsuccessMsg, dinput);
+  }
+  
+  if (!res){
+    return false;
+  }
+
+  
+  if (is_success){
+    e2ap_pdu_obj->choice.successfulOutcome = successMsg;
+    e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_successfulOutcome ;
+  }
+  else{
+    e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg;
+    e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_unsuccessfulOutcome ;
+
+  }
+
+  //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(errbuf, errbuf_len);
+    error_string = "Constraints failed for encoding control response. Reason = " + error_string;
+    return false;
+  }
+  
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+  
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    return false;
+  }
+  else {
+    if(*size < retval.encoded){
+      std::stringstream ss;
+      ss  <<"Error encoding E2AP Control response . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+      error_string = ss.str();
+      return false;
+    }
+  }
+
+  *size = retval.encoded;
+  return true;
+  
+}
+
+bool ric_control_response::set_fields(E2N_SuccessfulOutcome_t *successMsg, ric_control_helper &dinput){
+  unsigned int ie_index;
+
+  if (successMsg == 0){
+    error_string = "Invalid reference for E2AP Control Acknowledge in set_fields";
+    return false;
+  }
+
+  // for(i = 0; i < NUM_CONTROL_ACKNOWLEDGE_IES;i++){
+  //   memset(&(IE_array[i]), 0, sizeof(RICcontrolAcknowledge_IEs_t));
+  // }
+
+  //E2N_RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge);
+  //ric_acknowledge->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  E2N_RICcontrolAcknowledge_IEs_t *ies_ricreq = &IE_array[ie_index];  
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = dinput.req_id;
+  ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no;
+  //ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_ricreq);
+  
+  ie_index = 1;
+  E2N_RICcontrolAcknowledge_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = dinput.func_id;
+  //ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_ranfunc);
+
+  // ie_index = 2;
+  // E2N_RICcontrolAcknowledge_IEs_t *ies_riccallprocessid = &IE_array[ie_index];
+  // ies_riccallprocessid->criticality = E2N_Criticality_reject;
+  // ies_riccallprocessid->id = E2N_ProtocolIE_ID_id_RICcallProcessID;
+  // ies_riccallprocessid->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RICcallProcessID;
+  // RICcallProcessID_t *riccallprocessid_ie = &ies_riccallprocessid->value.choice.RICcallProcessID;
+  // riccallprocessid_ie->buf = dinput.call_process_id;
+  // riccallprocessid_ie->size = dinput.call_process_id_size;
+  // ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_riccallprocessid);
+  
+  ie_index = 2;
+  E2N_RICcontrolAcknowledge_IEs_t *ies_ric_cause = &IE_array[ie_index];
+  ies_ric_cause->criticality = E2N_Criticality_reject;
+  ies_ric_cause->id = E2N_ProtocolIE_ID_id_RICcontrolStatus;
+  ies_ric_cause->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RICcontrolStatus;
+  ies_ric_cause->value.choice.RICcontrolStatus = dinput.control_status;  
+  //ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_ric_cause);
+  
+  return true;
+
+};
+
+bool ric_control_response::set_fields(E2N_UnsuccessfulOutcome_t *unsuccessMsg, ric_control_helper &dinput){
+  unsigned int ie_index;
+
+  if (unsuccessMsg == 0){
+    error_string = "Invalid reference for E2AP Control Failure in set_fields";
+    return false;
+  }
+  
+  // for(i = 0; i < NUM_CONTROL_FAILURE_IES;i++){
+  //   memset(&(IE_failure_array[i]), 0, sizeof(RICcontrolFailure_IEs_t));
+  // }
+
+  //E2N_RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure);
+  //ric_failure->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  E2N_RICcontrolFailure_IEs_t *ies_ricreq = &IE_failure_array[ie_index];  
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICcontrolFailure_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &(ies_ricreq->value.choice.RICrequestID);
+  ricrequest_ie->ricRequestorID = dinput.req_id;
+  ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no;
+  //ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_ricreq);
+  
+  ie_index = 1;
+  E2N_RICcontrolFailure_IEs_t *ies_ranfunc = &IE_failure_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICcontrolFailure_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &(ies_ranfunc->value.choice.RANfunctionID);
+  *ranfunction_ie = dinput.func_id;
+  //ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_ranfunc);
+
+  // ie_index = 2;
+  // E2N_RICcontrolFailure_IEs_t *ies_riccallprocessid = &IE_failure_array[i];
+  // ies_riccallprocessid->criticality = E2N_Criticality_reject;
+  // ies_riccallprocessid->id = E2N_ProtocolIE_ID_id_RICcallProcessID;
+  // ies_riccallprocessid->value.present = E2N_RICcontrolFailure_IEs__value_PR_RICcallProcessID;
+  // RICcallProcessID_t *riccallprocessid_ie = &(ies_riccallprocessid->value.choice.RICcallProcessID);
+  // riccallprocessid_ie->buf = dinput.call_process_id;
+  // riccallprocessid_ie->size = dinput.call_process_id_size;
+  // ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_riccallprocessid);
+  
+  ie_index = 2;
+  E2N_RICcontrolFailure_IEs_t *ies_ric_cause = &IE_failure_array[ie_index];
+  ies_ric_cause->criticality = E2N_Criticality_ignore;
+  ies_ric_cause->id = E2N_ProtocolIE_ID_id_RICcause;
+  ies_ric_cause->value.present = E2N_RICcontrolFailure_IEs__value_PR_RICcause;
+  E2N_RICcause_t * ric_cause = &(ies_ric_cause->value.choice.RICcause);
+  ric_cause->present = (E2N_RICcause_PR)dinput.cause;
+  
+  switch(dinput.cause){
+  case E2N_RICcause_PR_radioNetwork:
+    ric_cause->choice.radioNetwork = dinput.sub_cause;
+    break;
+  case E2N_RICcause_PR_transport:
+    ric_cause->choice.transport = dinput.sub_cause;
+    break;
+  case E2N_RICcause_PR_protocol:
+    ric_cause->choice.protocol= dinput.sub_cause;
+    break;
+  case E2N_RICcause_PR_misc:
+    ric_cause->choice.misc = dinput.sub_cause;
+    break;
+  case E2N_RICcause_PR_ric:
+    ric_cause->choice.ric = dinput.sub_cause;
+    break;
+  default:
+    std::cout <<"Error ! Illegal cause enum" << dinput.cause << std::endl;
+    return false;
+  }
+  
+  //ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_ric_cause);
+  return true;
+
+};
+
+  
+
+
+bool ric_control_response:: get_fields(E2N_SuccessfulOutcome_t * success_msg,  ric_control_helper &dout)
+{
+  if (success_msg == 0){
+    error_string = "Invalid reference for E2AP Control Acknowledge message in get_fields";
+    return false;
+  }
+  
+  
+  for(int edx = 0; edx < success_msg->value.choice.RICcontrolAcknowledge.protocolIEs.list.count; edx++) {
+    E2N_RICcontrolAcknowledge_IEs_t *memb_ptr = success_msg->value.choice.RICcontrolAcknowledge.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+       
+      case (E2N_ProtocolIE_ID_id_RICcallProcessID):
+       dout.call_process_id =  memb_ptr->value.choice.RICcallProcessID.buf;
+       dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size;
+       break;
+
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID;
+       dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       dout.func_id = memb_ptr->value.choice.RANfunctionID;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICcause):
+       dout.control_status = memb_ptr->value.choice.RICcontrolStatus;
+       break;
+       
+      }
+    
+  }
+  
+  return true;
+
+}
+
+
+bool ric_control_response:: get_fields(E2N_UnsuccessfulOutcome_t * unsuccess_msg,  ric_control_helper &dout)
+{
+  if (unsuccess_msg == 0){
+    error_string = "Invalid reference for E2AP Control Failure message in get_fields";
+    return false;
+  }
+  
+  
+  for(int edx = 0; edx < unsuccess_msg->value.choice.RICcontrolFailure.protocolIEs.list.count; edx++) {
+    E2N_RICcontrolFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICcontrolFailure.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+       
+      case (E2N_ProtocolIE_ID_id_RICcallProcessID):
+       dout.call_process_id =  memb_ptr->value.choice.RICcallProcessID.buf;
+       dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size;
+       break;
+
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID;
+       dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       dout.func_id = memb_ptr->value.choice.RANfunctionID;
+       break;
+       
+       
+      case (E2N_ProtocolIE_ID_id_RICcause):
+       dout.cause = memb_ptr->value.choice.RICcause.present;
+       switch(dout.cause){
+         case  E2N_RICcause_PR_radioNetwork :
+           dout.sub_cause = memb_ptr->value.choice.RICcause.choice.radioNetwork;
+           break;
+             
+         case E2N_RICcause_PR_transport :
+           dout.sub_cause = memb_ptr->value.choice.RICcause.choice.transport;
+           break;
+             
+         case  E2N_RICcause_PR_protocol :
+           dout.sub_cause = memb_ptr->value.choice.RICcause.choice.protocol;
+           break;
+             
+         case E2N_RICcause_PR_misc :
+           dout.sub_cause = memb_ptr->value.choice.RICcause.choice.misc;
+           break;
+             
+         case E2N_RICcause_PR_ric :
+           dout.sub_cause = memb_ptr->value.choice.RICcause.choice.ric;
+           break;
+               
+       default:
+         dout.sub_cause = -1;
+         break;
+       }       
+
+      default:
+       break;
+      }
+    
+  }
+  
+  return true;
+  
+}
+
diff --git a/src/xapp-formats/e2ap/e2ap_control_response.hpp b/src/xapp-formats/e2ap/e2ap_control_response.hpp
new file mode 100644 (file)
index 0000000..6880e48
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_indication.h
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#ifndef E2AP_RIC_CONTROL_RESPONSE_H_
+#define E2AP_RIC_CONTROL_RESPONSE_H_
+
+  
+#include <iostream>
+#include <errno.h>
+#include <mdclog/mdclog.h>
+#include <sstream>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_SuccessfulOutcome.h>
+#include <E2N_UnsuccessfulOutcome.h>
+#include <E2N_RICcontrolAcknowledge.h>
+#include <E2N_RICcontrolFailure.h>
+#include <E2N_ProtocolIE-Field.h>
+#include "e2ap_control_helper.hpp"
+
+#define NUM_CONTROL_ACKNOWLEDGE_IES 3
+#define NUM_CONTROL_FAILURE_IES 3
+
+  
+class ric_control_response{
+    
+public:
+  ric_control_response(void);
+  ~ric_control_response(void);
+  
+  bool encode_e2ap_control_response(unsigned char *, size_t *,  ric_control_helper &, bool);
+
+
+  bool set_fields(E2N_SuccessfulOutcome_t *, ric_control_helper &);
+  bool get_fields(E2N_SuccessfulOutcome_t *, ric_control_helper &);
+
+  bool set_fields(E2N_UnsuccessfulOutcome_t *, ric_control_helper &);
+  bool get_fields(E2N_UnsuccessfulOutcome_t *, ric_control_helper &);
+  
+  std::string get_error(void) const {return error_string ; };
+
+private:
+  
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+  E2N_SuccessfulOutcome_t * successMsg;
+  E2N_UnsuccessfulOutcome_t * unsuccessMsg;
+  
+  E2N_RICcontrolAcknowledge_IEs_t *IE_array;
+  E2N_RICcontrolFailure_IEs_t *IE_failure_array;
+  
+  std::string error_string;
+  
+  char errbuf[128];
+  size_t errbuf_len = 128;
+};
+
+
+#endif /* E2AP_RIC_CONTROL_RESPONSE_H_ */
diff --git a/src/xapp-formats/e2ap/e2ap_indication.cc b/src/xapp-formats/e2ap/e2ap_indication.cc
new file mode 100644 (file)
index 0000000..33b2095
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_indication.c
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#include "e2ap_indication.hpp"
+
+// Set up memory allocations for each IE for encoding
+// We are responsible for memory management for each IE for encoding
+// Hence destructor should clear out memory
+// When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called
+// for releasing memory by external calling function)
+ric_indication::ric_indication(void){
+
+  e2ap_pdu_obj = 0;
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  initMsg = 0;
+  initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t));
+  assert(initMsg != 0);
+
+  IE_array = 0;
+  IE_array = (E2N_RICindication_IEs_t *)calloc(NUM_INDICATION_IES, sizeof(E2N_RICindication_IEs_t));
+  assert(IE_array != 0);
+
+  e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage;
+  e2ap_pdu_obj->choice.initiatingMessage = initMsg;
+
+                      
+  
+    
+};
+
+
+
+// Clear assigned protocolIE list from RIC indication IE container
+ric_indication::~ric_indication(void){
+
+  mdclog_write(MDCLOG_DEBUG, "Freeing E2AP Indication object memory");
+  E2N_RICindication_t *ricIndication  = &(initMsg->value.choice.RICindication);
+  for(int i = 0; i < ricIndication->protocolIEs.list.size; i++){
+    ricIndication->protocolIEs.list.array[i] = 0;
+  }
+  if (ricIndication->protocolIEs.list.size > 0){
+    free(ricIndication->protocolIEs.list.array);
+    ricIndication->protocolIEs.list.array = 0;
+    ricIndication->protocolIEs.list.count = 0;
+    ricIndication->protocolIEs.list.size = 0;
+  }
+  
+  free(IE_array);
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  mdclog_write(MDCLOG_DEBUG, "Freed E2AP Indication object mempory");
+}
+
+
+bool ric_indication::encode_e2ap_indication(unsigned char *buf, size_t *size, ric_indication_helper & dinput){
+
+  initMsg->procedureCode = E2N_ProcedureCode_id_ricIndication;
+  initMsg->criticality = E2N_Criticality_ignore;
+  initMsg->value.present = E2N_InitiatingMessage__value_PR_RICindication;
+
+  bool res;
+  asn_enc_rval_t retval;
+  
+  res = set_fields(initMsg, dinput);
+  if (!res){
+    return false;
+  }
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(&errbuf[0], errbuf_len);
+    error_string = "Error encoding E2AP Indication message. Reason = " + error_string;
+    return false;
+  }
+
+  // std::cout <<"Constraint check ok ...." << std::endl;
+  // xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj);
+  
+  retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    return false;
+  }
+
+  else {
+    if(*size < retval.encoded){
+      std::stringstream ss;
+      ss  <<"Error encoding E2AP Indication . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+      error_string = ss.str();
+      return false;
+    }
+  }
+
+  *size = retval.encoded;
+  return true;
+  
+}
+
+bool ric_indication::set_fields(E2N_InitiatingMessage_t *initMsg, ric_indication_helper &dinput){
+  unsigned int ie_index;
+
+  if (initMsg == 0){
+    error_string = "Invalid reference for E2AP Indication message in set_fields";
+    return false;
+  }
+  
+  
+  E2N_RICindication_t * ric_indication = &(initMsg->value.choice.RICindication);
+  ric_indication->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  
+  E2N_RICindication_IEs_t *ies_ricreq = &IE_array[ie_index];  
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICindication_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = dinput.req_id;
+  ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+  ie_index = 1;
+  E2N_RICindication_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICindication_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = dinput.func_id;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+
+  ie_index = 2;
+  E2N_RICindication_IEs_t *ies_actid = &IE_array[ie_index];
+  ies_actid->criticality = E2N_Criticality_reject;
+  ies_actid->id = E2N_ProtocolIE_ID_id_RICactionID;
+  ies_actid->value.present = E2N_RICindication_IEs__value_PR_RICactionID;
+  E2N_RICactionID_t *ricaction_ie = &ies_actid->value.choice.RICactionID;
+  *ricaction_ie = dinput.action_id;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+
+  ie_index = 3;
+  E2N_RICindication_IEs_t *ies_ricsn = &IE_array[ie_index];
+  ies_ricsn->criticality = E2N_Criticality_reject;
+  ies_ricsn->id = E2N_ProtocolIE_ID_id_RICindicationSN;
+  ies_ricsn->value.present = E2N_RICindication_IEs__value_PR_RICindicationSN;
+  E2N_RICindicationSN_t *ricsn_ie = &ies_ricsn->value.choice.RICindicationSN;
+  *ricsn_ie = dinput.indication_sn;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+
+
+  ie_index = 4;
+  E2N_RICindication_IEs_t *ies_indtyp = &IE_array[ie_index];
+  ies_indtyp->criticality = E2N_Criticality_reject;
+  ies_indtyp->id = E2N_ProtocolIE_ID_id_RICindicationType;
+  ies_indtyp->value.present = E2N_RICindication_IEs__value_PR_RICindicationType;
+  E2N_RICindicationType_t *rictype_ie = &ies_indtyp->value.choice.RICindicationType;
+  *rictype_ie = dinput.indication_type;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+
+  ie_index = 5;
+  E2N_RICindication_IEs_t *ies_richead = &IE_array[ie_index];
+  ies_richead->criticality = E2N_Criticality_reject;
+  ies_richead->id = E2N_ProtocolIE_ID_id_RICindicationHeader;
+  ies_richead->value.present = E2N_RICindication_IEs__value_PR_RICindicationHeader;
+  E2N_RICindicationHeader_t *richeader_ie = &ies_richead->value.choice.RICindicationHeader;
+  richeader_ie->buf = dinput.indication_header;
+  richeader_ie->size = dinput.indication_header_size;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+  
+  ie_index = 6;
+  E2N_RICindication_IEs_t *ies_indmsg = &IE_array[ie_index];
+  ies_indmsg->criticality = E2N_Criticality_reject;
+  ies_indmsg->id = E2N_ProtocolIE_ID_id_RICindicationMessage;
+  ies_indmsg->value.present = E2N_RICindication_IEs__value_PR_RICindicationMessage;
+  E2N_RICindicationMessage_t *ricmsg_ie = &ies_indmsg->value.choice.RICindicationMessage;
+  ricmsg_ie->buf = dinput.indication_msg;
+  ricmsg_ie->size = dinput.indication_msg_size;
+  ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+
+
+  // optional call process id ..
+  if (dinput.call_process_id_size > 0){
+    ie_index = 7;
+    E2N_RICindication_IEs_t *ies_ind_callprocessid = &IE_array[ie_index];
+    ies_ind_callprocessid->criticality = E2N_Criticality_reject;
+    ies_ind_callprocessid->id = E2N_ProtocolIE_ID_id_RICcallProcessID;
+    ies_ind_callprocessid->value.present = E2N_RICindication_IEs__value_PR_RICcallProcessID;
+    E2N_RICcallProcessID_t *riccallprocessid_ie = &ies_ind_callprocessid->value.choice.RICcallProcessID;
+    riccallprocessid_ie->buf = dinput.indication_msg;
+    riccallprocessid_ie->size = dinput.indication_msg_size;
+    ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index]));
+  }
+  
+  return true;
+
+};
+
+  
+
+
+bool ric_indication:: get_fields(E2N_InitiatingMessage_t * init_msg,  ric_indication_helper &dout)
+{
+  if (init_msg == 0){
+    error_string = "Invalid reference for E2AP Indication message in get_fields";
+    return false;
+  }
+  
+  for(int edx = 0; edx < init_msg->value.choice.RICindication.protocolIEs.list.count; edx++) {
+    E2N_RICindication_IEs_t *memb_ptr = init_msg->value.choice.RICindication.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICindicationHeader):
+       dout.indication_header = memb_ptr->value.choice.RICindicationHeader.buf;
+       dout.indication_header_size = memb_ptr->value.choice.RICindicationHeader.size;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICindicationMessage):
+       dout.indication_msg =  memb_ptr->value.choice.RICindicationMessage.buf;
+       dout.indication_msg_size = memb_ptr->value.choice.RICindicationMessage.size;
+       break;
+           
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID;
+       dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       dout.func_id = memb_ptr->value.choice.RANfunctionID;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICindicationSN):
+       dout.indication_sn = memb_ptr->value.choice.RICindicationSN;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICindicationType):
+       dout.indication_type = memb_ptr->value.choice.RICindicationType;
+       break;
+       
+      case (E2N_ProtocolIE_ID_id_RICactionID):
+       dout.action_id = memb_ptr->value.choice.RICactionID;
+       break;
+
+      case (E2N_ProtocolIE_ID_id_RICcallProcessID):
+       dout.call_process_id = memb_ptr->value.choice.RICcallProcessID.buf;
+       dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size;
+       
+      default:
+       break;
+      }
+    
+  }
+  
+  return true;
+
+}
+
+E2N_InitiatingMessage_t * ric_indication::get_message(void)  {
+    return initMsg;
+}
diff --git a/src/xapp-formats/e2ap/e2ap_indication.hpp b/src/xapp-formats/e2ap/e2ap_indication.hpp
new file mode 100644 (file)
index 0000000..af43086
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_indication.h
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+#ifndef E2AP_RIC_INDICATION_H_
+#define E2AP_RIC_INDICATION_H_
+
+  
+#include <iostream>
+#include <errno.h>
+#include <mdclog/mdclog.h>
+#include <sstream>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_InitiatingMessage.h>
+#include <E2N_RICindication.h>
+#include <E2N_ProtocolIE-Field.h>
+#include "e2ap_indication_helper.hpp"
+
+#define NUM_INDICATION_IES 8
+  
+
+
+class ric_indication{
+  
+public:
+  ric_indication(void);
+  ~ric_indication(void);
+  
+  bool encode_e2ap_indication(unsigned char *, size_t *,  ric_indication_helper &);
+  E2N_InitiatingMessage_t * get_message (void) ;
+  bool set_fields(E2N_InitiatingMessage_t *, ric_indication_helper &);
+  bool get_fields(E2N_InitiatingMessage_t *, ric_indication_helper &);
+  std::string get_error(void) const {return error_string ; };
+  
+private:
+  
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+  E2N_InitiatingMessage_t *initMsg;
+  E2N_RICindication_IEs_t *IE_array;
+  std::string error_string;
+  char errbuf[128];
+  size_t errbuf_len = 128;
+};
+
+
+#endif /* E2AP_RIC_INDICATION_H_ */
diff --git a/src/xapp-formats/e2ap/e2ap_indication_helper.hpp b/src/xapp-formats/e2ap/e2ap_indication_helper.hpp
new file mode 100644 (file)
index 0000000..276a2a7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * ric_indication.h
+ *
+ *  Created on: Jul 11, 2019
+ *      Author: sjana, Ashwin Sridharan
+ */
+
+
+#ifndef E2AP_INDICATION_HELPER_
+#define E2AP_INDICATION_HELPER_
+
+typedef struct ric_indication_helper ric_indication_helper;
+
+struct ric_indication_helper{
+  ric_indication_helper(void) : req_id(1), req_seq_no(1), func_id(0), action_id(1), indication_type(0), indication_sn(0), indication_msg(0), indication_msg_size(0), indication_header(0), indication_header_size(0), call_process_id(0), call_process_id_size(0) {};
+  long int req_id, req_seq_no, func_id, action_id, indication_type, indication_sn;
+  
+  unsigned char* indication_msg;
+  size_t indication_msg_size;
+  
+  unsigned char* indication_header;
+  size_t indication_header_size;
+  
+  unsigned char *call_process_id;
+  size_t call_process_id_size;
+  
+};
+
+#endif
diff --git a/src/xapp-formats/e2ap/generic_helpers.hpp b/src/xapp-formats/e2ap/generic_helpers.hpp
new file mode 100644 (file)
index 0000000..32c019a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+
+#pragma once
+#ifndef GENERIC_HELPERS
+#define GENERIC_HELPERS
+
+#include <cstddef>
+
+/* Utilities */
+
+class octet_helper {
+
+public:
+  octet_helper(void):_ref(NULL), _size(0){};
+  octet_helper(const void *ref, int size):_ref(ref), _size(size){};
+  void set_ref(const void *ref){
+    _ref = ref;
+  }
+  
+  void set_size(size_t size){
+    _size = size;
+  }
+  
+  const void * get_ref(void){return _ref ; };
+  size_t get_size(void) const {return _size ; } ;
+
+private:
+  const void *_ref;
+  size_t _size;
+};
+    
+#endif
diff --git a/src/xapp-formats/e2ap/response_helper.hpp b/src/xapp-formats/e2ap/response_helper.hpp
new file mode 100644 (file)
index 0000000..b370ff2
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+#pragma once
+
+#ifndef S_RESPONSE_HELPER_
+#define S_RESPONSE_HELPER_
+
+#include <vector>
+#include <memory>
+
+/* Simple structure to store action for RICaction of the Subscription response based on E2 v0.31 */
+struct ActionResponse {
+public:
+  ActionResponse(int id): _is_admit(true), _id(id), _cause(-1), _sub_cause(-1){};
+  ActionResponse(int id, int cause, int sub_cause): _is_admit(false), _id(id), _cause(cause), _sub_cause(sub_cause){};
+  
+  int get_id() const{
+    return _id;
+  };
+
+  int get_cause() const{
+    return _cause;
+  };
+
+  int get_sub_cause() const{
+    return _sub_cause;
+  };
+
+  bool is_admitted(void){
+    return _is_admit;
+  };
+  
+private:
+
+  bool _is_admit;
+  int _id, _cause, _sub_cause;
+  
+};
+
+
+struct subscription_response_helper {
+  
+public:
+
+  using action_t = std::vector<ActionResponse>;
+  
+  subscription_response_helper(void){
+    _action_admitted_ref = std::make_unique<action_t>();
+    _action_not_admitted_ref = std::make_unique<action_t>();
+    
+  };
+  
+  // copy operator
+  subscription_response_helper(const subscription_response_helper &he ){
+    _action_admitted_ref = std::make_unique<action_t>();
+    _action_not_admitted_ref = std::make_unique<action_t>();
+    
+    _req_id = he.get_request_id();
+    _req_seq_no = he.get_req_seq();
+    _func_id = he.get_function_id();
+    
+    // Take care of the actions
+    for (auto const & e: *(he.get_admitted_list())){
+      add_action(e.get_id());
+    }
+    
+    for(auto const  & e: *(he.get_not_admitted_list())){
+      add_action(e.get_id(), e.get_cause(), e.get_sub_cause());
+    };
+  }
+  
+
+  // assignment operator
+  void operator=(const subscription_response_helper & he){
+    _action_admitted_ref = std::make_unique<action_t>();
+    _action_not_admitted_ref = std::make_unique<action_t>();
+    
+    _req_id = he.get_request_id();
+    _req_seq_no = he.get_req_seq();
+    _func_id = he.get_function_id();
+    
+    
+    // Take care of the actions
+    for (auto  const & e: *(he.get_admitted_list())){
+      add_action(e.get_id());
+    }
+  
+    for(auto const  & e: *(he.get_not_admitted_list())){
+      add_action(e.get_id(), e.get_cause(), e.get_sub_cause());
+    };
+    
+  }
+  
+  action_t * get_admitted_list (void ) const {return _action_admitted_ref.get();};
+  action_t * get_not_admitted_list (void ) const{return _action_not_admitted_ref.get();};
+  
+  void set_request(int id, int seq_no){
+    _req_id = id;
+    _req_seq_no = seq_no;
+    
+  };
+
+  void clear(void){
+    _action_admitted_ref.get()->clear();
+    _action_not_admitted_ref.get()->clear();
+  }
+
+  
+  void set_function_id(int id){
+    _func_id = id;
+  };
+
+  void add_action(int id){
+    ActionResponse a(id) ;
+    _action_admitted_ref.get()->push_back(a);
+  };
+
+  void add_action(int id, int cause, int sub_cause){
+    ActionResponse a (id, cause, sub_cause);
+    _action_not_admitted_ref.get()->push_back(a);
+  };
+
+
+  int  get_request_id(void) const{
+    return _req_id;
+  }
+  
+  int get_req_seq(void) const{
+    return _req_seq_no;
+  }
+
+  int  get_function_id(void) const{
+    return _func_id;
+  }
+  std::string  to_string(void){
+    std::string Info;
+    Info += "Request ID = " + std::to_string(_req_id) + "\n";
+    Info += "Request Sequence No = "  + std::to_string(_req_seq_no) + "\n";
+    Info += "RAN Function ID = " + std::to_string(_func_id) + "\n";
+    Info += "Actions Admitted =\n";
+    int i = 0;
+    for(auto & e: *(_action_admitted_ref)){
+        Info += std::to_string(i)  + ": ID=" + std::to_string(e.get_id()) + "\n";
+        i++;
+    }    
+    Info += "Actions Not Admitted =\n";
+    i = 0;
+    for(auto & e: *(_action_not_admitted_ref)){
+      Info += std::to_string(i)  + ": ID=" + std::to_string(e.get_id()) +  ": Cause =" + std::to_string(e.get_cause()) + ": Sub-Cause=" + std::to_string(e.get_sub_cause()) + "\n";
+      i++;
+    }    
+  
+    return Info;
+  } 
+
+private:
+  int _req_id, _req_seq_no, _func_id;
+  std::unique_ptr<action_t> _action_admitted_ref;
+  std::unique_ptr<action_t> _action_not_admitted_ref;
+  
+};
+  
+
+#endif
diff --git a/src/xapp-formats/e2ap/subscription_delete_request.cc b/src/xapp-formats/e2ap/subscription_delete_request.cc
new file mode 100644 (file)
index 0000000..d103d2e
--- /dev/null
@@ -0,0 +1,180 @@
+
+
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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 "subscription_delete_request.hpp"
+  
+subscription_delete::subscription_delete(void){
+
+  _name = "default";
+  
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t));
+  assert(initMsg != 0);
+  
+  IE_array = (E2N_RICsubscriptionDeleteRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_IES, sizeof(E2N_RICsubscriptionDeleteRequest_IEs_t));
+  assert(IE_array != 0);
+  
+  E2N_RICsubscriptionDeleteRequest_t * subscription_delete = &(initMsg->value.choice.RICsubscriptionDeleteRequest);
+  for(int i = 0; i < NUM_SUBSCRIPTION_DELETE_IES; i++){
+    ASN_SEQUENCE_ADD(&subscription_delete->protocolIEs, &(IE_array[i]));
+  }
+  
+};
+
+
+
+// Clear assigned protocolIE list from RIC indication IE container
+subscription_delete::~subscription_delete(void){
+    
+  mdclog_write(MDCLOG_DEBUG, "Freeing subscription delete request object memory");
+  E2N_RICsubscriptionDeleteRequest_t * subscription_delete = &(initMsg->value.choice.RICsubscriptionDeleteRequest);
+  
+  for(int i = 0; i < subscription_delete->protocolIEs.list.size; i++){
+    subscription_delete->protocolIEs.list.array[i] = 0;
+  }
+
+  if (subscription_delete->protocolIEs.list.size > 0){
+    free(subscription_delete->protocolIEs.list.array);
+    subscription_delete->protocolIEs.list.count = 0;
+    subscription_delete->protocolIEs.list.size = 0;
+    subscription_delete->protocolIEs.list.array = 0;
+  }
+  
+  free(IE_array);
+  free(initMsg);
+  e2ap_pdu_obj->choice.initiatingMessage = 0;
+
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  mdclog_write(MDCLOG_DEBUG, "Freed subscription delete request object memory");
+  
+
+};
+
+
+bool subscription_delete::encode_e2ap_subscription(unsigned char *buf, size_t *size,  subscription_helper &dinput){
+
+  e2ap_pdu_obj->choice.initiatingMessage = initMsg;
+  e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage;
+  set_fields( dinput);
+
+  initMsg->procedureCode = E2N_ProcedureCode_id_ricSubscriptionDelete;
+  initMsg->criticality = E2N_Criticality_reject;
+  initMsg->value.present = E2N_InitiatingMessage__value_PR_RICsubscriptionDeleteRequest;
+
+  //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(errbuf, errbuf_len);
+    error_string = "Constraints failed for encoding subscription delete request. Reason = " + error_string;
+    return false;
+  }
+  
+  asn_enc_rval_t res = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+    
+  if(res.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding Subscription Delete Request. Reason = " + error_string;
+    return false;
+  }
+  else {
+    if(*size < res.encoded){
+      std::stringstream ss;
+      ss  <<"Error encoding Subscription Delete Request . Reason =  encoded pdu size " << res.encoded << " exceeds buffer size " << *size << std::endl;
+      error_string = ss.str();
+      res.encoded = -1;
+      return false;
+    }
+  }
+    
+  *size = res.encoded;
+  return true;
+    
+}
+
+
+bool  subscription_delete::set_fields( subscription_helper &helper){
+  unsigned int ie_index;
+  
+  ie_index = 0;
+  E2N_RICsubscriptionDeleteRequest_IEs_t *ies_ricreq = &IE_array[ie_index];
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICsubscriptionDeleteRequest_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = helper.get_request_id();
+  ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
+
+
+  
+  ie_index = 1;
+  E2N_RICsubscriptionDeleteRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICsubscriptionDeleteRequest_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = helper.get_function_id();
+
+  
+  return true;
+};
+
+
+   
+
+bool  subscription_delete:: get_fields(E2N_InitiatingMessage_t * init_msg,  subscription_helper & dout)
+{
+
+  if (init_msg == 0){
+    error_string = "Invalid reference for initiating message for get string";
+    return false;
+  }
+  
+  E2N_RICrequestID_t *requestid;
+  E2N_RANfunctionID_t * ranfunctionid;
+    
+  for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionDeleteRequest.protocolIEs.list.count; edx++) {
+    E2N_RICsubscriptionDeleteRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionDeleteRequest.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       requestid = &memb_ptr->value.choice.RICrequestID;
+       dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
+       dout.set_function_id(*ranfunctionid);
+       break;
+       
+      }
+    
+  //asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu);
+  }
+
+  return true;
+}
+
+
+
diff --git a/src/xapp-formats/e2ap/subscription_delete_request.hpp b/src/xapp-formats/e2ap/subscription_delete_request.hpp
new file mode 100644 (file)
index 0000000..e3c1d4e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+#pragma once
+
+#ifndef S_DELETE_
+#define S_DELETE_
+
+#include <mdclog/mdclog.h>
+#include <vector>
+#include <sstream>
+#include <mdclog/mdclog.h>
+#include <asn_application.h>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_InitiatingMessage.h>
+#include <E2N_RICsubscriptionDeleteRequest.h>
+#include <E2N_ProtocolIE-Field.h>
+#include "subscription_helper.hpp"
+
+#define NUM_SUBSCRIPTION_DELETE_IES 2
+
+class subscription_delete{   
+public:
+
+  subscription_delete(void);
+  ~subscription_delete(void);
+  
+  bool encode_e2ap_subscription(unsigned char *, size_t *,  subscription_helper &);
+  bool set_fields(subscription_helper &);
+  bool get_fields(E2N_InitiatingMessage_t *, subscription_helper &);
+    
+  std::string get_error(void) const {
+    return error_string ;
+  }
+    
+private:
+    
+  E2N_InitiatingMessage_t *initMsg;
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+
+  E2N_RICsubscriptionDeleteRequest_IEs_t * IE_array;
+
+  
+  char errbuf[128];
+  size_t errbuf_len = 128;
+  std::string _name;
+  std::string error_string;
+};
+
+
+
+#endif
diff --git a/src/xapp-formats/e2ap/subscription_delete_response.cc b/src/xapp-formats/e2ap/subscription_delete_response.cc
new file mode 100644 (file)
index 0000000..c1c166c
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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 "subscription_delete_response.hpp"
+
+/* The xAPP need only worry about the get_fields from a response, since it does
+not generate a response. Generating response however is included to support testing. 
+*/
+
+
+// Primarly for generation
+subscription_delete_response::subscription_delete_response(void){
+
+  e2ap_pdu_obj = 0;
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t *)calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  successMsg = 0;
+  successMsg = (E2N_SuccessfulOutcome_t *)calloc(1, sizeof(E2N_SuccessfulOutcome_t));
+  assert(successMsg != 0);
+
+  unsuccessMsg = 0;
+  unsuccessMsg = (E2N_UnsuccessfulOutcome_t *)calloc(1, sizeof(E2N_UnsuccessfulOutcome_t));
+  assert(unsuccessMsg != 0);
+
+  IE_array = 0;
+  IE_array = (E2N_RICsubscriptionDeleteResponse_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_RESPONSE_IES, sizeof(E2N_RICsubscriptionDeleteResponse_IEs_t));
+  assert(IE_array != 0);
+
+  IE_Failure_array = 0;
+  IE_Failure_array = (E2N_RICsubscriptionDeleteFailure_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_FAILURE_IES, sizeof(E2N_RICsubscriptionDeleteFailure_IEs_t));
+  assert(IE_Failure_array != 0);
+
+  
+   
+};
+
+  
+
+// Clear assigned protocolIE list from E2N_RIC indication IE container
+subscription_delete_response::~subscription_delete_response(void){
+
+  mdclog_write(MDCLOG_DEBUG, "Freeing subscription delete response memory");
+  E2N_RICsubscriptionDeleteResponse_t * ric_subscription_delete_response = &(successMsg->value.choice.RICsubscriptionDeleteResponse);
+  
+  for(unsigned int i = 0; i < ric_subscription_delete_response->protocolIEs.list.size ; i++){
+    ric_subscription_delete_response->protocolIEs.list.array[i] = 0;
+  }
+
+  
+  E2N_RICsubscriptionDeleteFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionDeleteFailure);
+  for(unsigned int i = 0; i < ric_subscription_failure->protocolIEs.list.size; i++){
+    ric_subscription_failure->protocolIEs.list.array[i] = 0;
+  }
+
+  free(IE_array);
+  free(IE_Failure_array);
+
+  ASN_STRUCT_FREE(asn_DEF_E2N_SuccessfulOutcome, successMsg);
+
+  ASN_STRUCT_FREE(asn_DEF_E2N_UnsuccessfulOutcome, unsuccessMsg);
+  
+  e2ap_pdu_obj->choice.successfulOutcome = NULL;
+  e2ap_pdu_obj->choice.unsuccessfulOutcome = NULL;
+
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  mdclog_write(MDCLOG_DEBUG, "Freed subscription delete response memory");
+
+};
+
+
+bool subscription_delete_response::encode_e2ap_subscription_delete_response(unsigned char *buf, size_t *size,  subscription_response_helper &dinput, bool is_success){
+
+  bool res;
+  if(is_success){
+    res = set_fields(successMsg, dinput);
+    if (!res){
+      return false;
+    }
+    e2ap_pdu_obj->present =  E2N_E2AP_PDU_PR_successfulOutcome;
+    e2ap_pdu_obj->choice.successfulOutcome = successMsg;
+  }
+  else{
+    res = set_fields(unsuccessMsg, dinput);
+    if(! res){
+      return false;
+    }
+    e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_unsuccessfulOutcome;
+    e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg;
+  }
+    
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(errbuf, errbuf_len);
+    return false;
+  }
+
+  //xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj);
+  
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+    
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding subcription delete response. Reason = " + error_string;
+    return false;
+  }
+  else {
+    if(*size < retval.encoded){
+      std::stringstream ss;
+      ss  <<"Error encoding Subscription Delete Response . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+      error_string = ss.str();
+      retval.encoded = -1;
+      return false;
+    }
+  }
+    
+  *size = retval.encoded;
+  return true;
+    
+}
+  
+bool  subscription_delete_response::set_fields(E2N_SuccessfulOutcome_t *success, subscription_response_helper &helper){
+
+  if (success == 0){
+    error_string = "Invalid reference to success message in set fields  subscription delete response";
+    return false;
+  }
+  
+  unsigned int ie_index;
+
+  success->procedureCode = E2N_ProcedureCode_id_ricSubscriptionDelete;
+  success->criticality = E2N_Criticality_reject;
+  success->value.present = E2N_SuccessfulOutcome__value_PR_RICsubscriptionDeleteResponse;   
+  E2N_RICsubscriptionDeleteResponse_t * subscription_delete_response = &(success->value.choice.RICsubscriptionDeleteResponse);
+  subscription_delete_response->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  E2N_RICsubscriptionDeleteResponse_IEs_t *ies_ricreq = &IE_array[ie_index];
+  
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICsubscriptionDeleteResponse_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = helper.get_request_id();
+  ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
+  ASN_SEQUENCE_ADD(&subscription_delete_response->protocolIEs, ies_ricreq);
+
+  
+  ie_index = 1;
+  E2N_RICsubscriptionDeleteResponse_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICsubscriptionDeleteResponse_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = helper.get_function_id();
+  ASN_SEQUENCE_ADD(&subscription_delete_response->protocolIEs, ies_ranfunc);
+
+  return true;
+       
+}
+
+bool subscription_delete_response:: get_fields(E2N_SuccessfulOutcome_t * success_msg,  subscription_response_helper & dout)
+{
+
+  if (success_msg == 0){
+    error_string = "Invalid reference to success message inn get fields subscription delete response";
+    return false;
+  }
+  
+  E2N_RICrequestID_t *requestid;
+  E2N_RANfunctionID_t * ranfunctionid;
+  
+  for(int edx = 0; edx < success_msg->value.choice.RICsubscriptionDeleteResponse.protocolIEs.list.count; edx++) {
+    E2N_RICsubscriptionDeleteResponse_IEs_t *memb_ptr = success_msg->value.choice.RICsubscriptionDeleteResponse.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       requestid = &memb_ptr->value.choice.RICrequestID;
+       dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
+       dout.set_function_id(*ranfunctionid);
+       break;
+      }
+    
+  }
+  
+  return true;
+  //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu);
+}
+
+
+bool subscription_delete_response::set_fields(E2N_UnsuccessfulOutcome_t *unsuccess, subscription_response_helper &helper){
+
+  if (unsuccess == 0){
+    error_string = "Invalid reference to unsuccess message in set fields  subscription delete response";
+    return false;
+  }
+  
+  unsigned int ie_index;
+
+  unsuccess->procedureCode = E2N_ProcedureCode_id_ricSubscriptionDelete;
+  unsuccess->criticality = E2N_Criticality_reject;
+  unsuccess->value.present = E2N_UnsuccessfulOutcome__value_PR_RICsubscriptionDeleteFailure;
+
+  E2N_RICsubscriptionDeleteFailure_t * ric_subscription_failure = &(unsuccess->value.choice.RICsubscriptionDeleteFailure);
+  ric_subscription_failure->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  E2N_RICsubscriptionDeleteFailure_IEs_t *ies_ricreq = &IE_Failure_array[ie_index];
+    
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICsubscriptionDeleteFailure_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = helper.get_request_id();
+  ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
+  ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, ies_ricreq);
+  
+  ie_index = 1;
+  E2N_RICsubscriptionDeleteFailure_IEs_t *ies_ranfunc = &IE_Failure_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICsubscriptionDeleteFailure_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = helper.get_function_id();
+  ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, ies_ranfunc);
+    
+
+  return true;
+    
+}
+
+bool  subscription_delete_response:: get_fields(E2N_UnsuccessfulOutcome_t * unsuccess_msg,  subscription_response_helper & dout)
+{
+
+  if (unsuccess_msg == 0){
+    error_string = "Invalid reference to unsuccess message in get fields  subscription delete response";
+    return false;
+  }
+  
+  E2N_RICrequestID_t *requestid;
+  E2N_RANfunctionID_t * ranfunctionid;
+    
+  for(int edx = 0; edx < unsuccess_msg->value.choice.RICsubscriptionDeleteFailure.protocolIEs.list.count; edx++) {
+    E2N_RICsubscriptionDeleteFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICsubscriptionDeleteFailure.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       requestid = &memb_ptr->value.choice.RICrequestID;
+       dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
+       dout.set_function_id(*ranfunctionid);
+       break;
+       
+      }
+    
+  }
+
+  return true;
+  //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu);
+}
+
+
+
diff --git a/src/xapp-formats/e2ap/subscription_delete_response.hpp b/src/xapp-formats/e2ap/subscription_delete_response.hpp
new file mode 100644 (file)
index 0000000..d9581e4
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+#pragma once
+
+#ifndef S_DEL_RESPONSE_
+#define S_DEL_RESPONSE_
+
+#include <mdclog/mdclog.h>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <mdclog/mdclog.h>
+#include <asn_application.h>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_SuccessfulOutcome.h>
+#include <E2N_UnsuccessfulOutcome.h>
+#include <E2N_RICsubscriptionDeleteResponse.h>
+#include <E2N_RICsubscriptionDeleteFailure.h>
+#include <E2N_ProtocolIE-Field.h>
+#include <E2N_ProcedureCode.h>
+#include "response_helper.hpp"
+
+#define NUM_SUBSCRIPTION_DELETE_RESPONSE_IES 2
+#define NUM_SUBSCRIPTION_DELETE_FAILURE_IES 2
+  
+class subscription_delete_response {   
+public:
+    
+  subscription_delete_response(void);
+  ~subscription_delete_response(void);
+    
+  bool encode_e2ap_subscription_delete_response(unsigned char *, size_t *,  subscription_response_helper &, bool);
+  bool set_fields(E2N_SuccessfulOutcome_t *, subscription_response_helper &);
+  bool get_fields(E2N_SuccessfulOutcome_t *, subscription_response_helper &);
+    
+  bool set_fields(E2N_UnsuccessfulOutcome_t *, subscription_response_helper &);
+  bool get_fields(E2N_UnsuccessfulOutcome_t *, subscription_response_helper &);
+  
+  std::string get_error_string(void) const {
+    return error_string;
+  }
+    
+private:
+
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+  E2N_SuccessfulOutcome_t * successMsg;
+  E2N_UnsuccessfulOutcome_t * unsuccessMsg;
+    
+
+  E2N_RICsubscriptionDeleteResponse_IEs_t *IE_array;
+  E2N_RICsubscriptionDeleteFailure_IEs_t *IE_Failure_array;
+  
+  
+  char errbuf[128];
+  size_t errbuf_len = 128;
+  std::string error_string;
+  
+};
+
+
+
+
+#endif
diff --git a/src/xapp-formats/e2ap/subscription_helper.hpp b/src/xapp-formats/e2ap/subscription_helper.hpp
new file mode 100644 (file)
index 0000000..ae0c5a5
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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 SUB_HELPER_
+#define SUB_HELPER_
+
+/* 
+   Simple structure to store action related information based on E2 v0.22
+   Used for subscription request, response etc
+   
+   ricActionID                                 RICactionID,
+   ricActionType                               RICactionType,
+   ricActionDefinition                 RICactionDefinition     OPTIONAL,
+   ricSubsequentAction                 RICsubsequentAction     OPTIONAL,
+   ricCause
+*/
+
+#include <iostream>
+#include <vector>
+#include <memory>
+
+#include "generic_helpers.hpp"
+
+
+// Note : if no action definition specified, octet length of action definition  is NULL
+// If no subsequent action specified, default is subsequent_action = 0, time to wait is 0
+struct Action {
+
+public:
+  
+  Action(int id, int type): _is_def(false), _is_subs_act(false), _id(id), _type(type), _next_action(0), _wait(0){};
+  Action(int id, int type, const void *def, size_t def_size, int next, int wait): _is_def(false), _is_subs_act(false), _id(id), _type(type){
+    
+    if (def_size > 0){
+      _is_def = true;
+      _action_definition.set_ref(def);
+      _action_definition.set_size(def_size);
+    }
+    
+    if(next >= 0 && wait >= 0){
+      _is_subs_act = true;
+      _next_action = next;
+      _wait = wait;
+    }
+  };
+
+  
+  int get_id() const{
+    return _id;
+  }
+
+  int get_type() const {
+    return _type;
+  }
+
+
+  const void * get_definition(void )  {
+    return _action_definition.get_ref();
+  }
+
+  int get_definition_size(void) const {
+    return _action_definition.get_size();
+  };
+  
+
+  int get_subsequent_action() const {
+    return _next_action;
+  };
+
+  int get_wait() const {
+    return _wait;
+  }
+
+  bool is_definition() const{
+
+    return _is_def;
+  }
+
+  bool is_subsequent_action() const{
+    return _is_subs_act;
+  }
+    
+private:
+
+  bool _is_def;
+  bool _is_subs_act;
+  int _id, _type, _next_action, _wait, _cause, _sub_cause;
+  bool _is_admit;
+  octet_helper _action_definition;
+
+};
+
+
+/*
+ Helper class that stores subscription data 
+*/
+
+
+struct subscription_helper {
+
+public:
+
+  using action_t = std::vector<Action>;
+  
+  subscription_helper(){
+    _action_ref = std::make_unique<action_t>();
+    curr_index = 0;    
+  };
+  
+  action_t * get_list() const {return _action_ref.get();};
+
+  void clear(void){
+    _action_ref.get()->clear();
+  }
+  
+  void set_request(int id, int seq_no){
+    _req_id = id;
+    _req_seq_no = seq_no;
+    
+  };
+
+  void set_function_id(int id){
+    _func_id = id;
+  };
+
+  void set_event_def(const void *ref, size_t size){
+    _event_def.set_ref(ref);
+    _event_def.set_size(size);
+   };
+
+  void add_action(int id, int type){
+    Action a(id, type) ;
+    _action_ref.get()->push_back(a);
+  };
+
+  void add_action(int id, int type, std::string action_def, int next_action, int wait_time){
+    Action a (id, type, action_def.c_str(), action_def.length(), next_action, wait_time);
+    _action_ref.get()->push_back(a);
+  };
+
+
+  int  get_request_id(void) const{
+    return _req_id;
+  }
+
+  int  get_req_seq(void) const {
+    return _req_seq_no;
+  }
+
+  int  get_function_id(void) const{
+    return _func_id;
+  }
+  
+  const void * get_event_def(void)  {
+    return _event_def.get_ref();
+  }
+
+  int get_event_def_size(void) const {
+    return _event_def.get_size();
+  }
+
+  void print_sub_info(void){
+    std::cout <<"Request ID = " << _req_id << std::endl;
+    std::cout <<"Request Sequence Number = " << _req_seq_no << std::endl;
+    std::cout <<"RAN Function ID = " << _func_id << std::endl;
+    for(auto const & e: *(_action_ref.get())){
+      std::cout <<"Action ID = " << e.get_id() << " Action Type = " << e.get_type() << std::endl;
+    }
+  };
+  
+private:
+  
+  std::unique_ptr<action_t> _action_ref;
+  int curr_index;
+  int _req_id, _req_seq_no, _func_id;
+  octet_helper _event_def;
+};
+
+#endif
diff --git a/src/xapp-formats/e2ap/subscription_request.cc b/src/xapp-formats/e2ap/subscription_request.cc
new file mode 100644 (file)
index 0000000..9b2f897
--- /dev/null
@@ -0,0 +1,308 @@
+
+
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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 "subscription_request.hpp"
+
+
+// Set up memory allocations for each IE for encoding
+// We are responsible for memory management for each IE for encoding
+// Hence destructor should clear out memory
+// When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called
+// for releasing memory by external calling function)
+subscription_request::subscription_request(void){
+
+  _name = "default";
+
+  e2ap_pdu_obj = 0;
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  initMsg = 0;
+  initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t));
+  assert(initMsg != 0);
+
+  IE_array = 0;
+  IE_array = (E2N_RICsubscriptionRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_REQUEST_IES, sizeof(E2N_RICsubscriptionRequest_IEs_t));
+  assert(IE_array != 0);
+  
+  action_array = 0;
+  action_array = (E2N_RICaction_ToBeSetup_ItemIEs_t *)calloc(INITIAL_REQUEST_LIST_SIZE, sizeof(E2N_RICaction_ToBeSetup_ItemIEs_t));
+  assert(action_array != 0);
+  action_array_size = INITIAL_REQUEST_LIST_SIZE;
+  // also need to add subsequent action and time to wait ..
+  for (unsigned int i = 0; i < action_array_size; i++){
+    action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction = (struct E2N_RICsubsequentAction *)calloc(1, sizeof(struct E2N_RICsubsequentAction));
+    assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction  != 0);
+  }
+  
+  e2ap_pdu_obj->choice.initiatingMessage = initMsg;
+  e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage;
+
+
+  
+};
+
+
+
+// Clear assigned protocolIE list from RIC indication IE container
+subscription_request::~subscription_request(void){
+    
+  mdclog_write(MDCLOG_DEBUG, "Freeing subscription request memory for");;
+  
+  // Sequence of actions to be admitted causes special heart-ache. Free ric subscription element manually and reset the ie pointer  
+  E2N_RICsubscription_t * ricsubscription_ie = &(IE_array[2].value.choice.RICsubscription);
+
+  for(int i = 0; i < ricsubscription_ie->ricAction_ToBeSetup_List.list.size; i++){
+    ricsubscription_ie->ricAction_ToBeSetup_List.list.array[i] = 0;
+  }
+
+  if (ricsubscription_ie->ricAction_ToBeSetup_List.list.size > 0){
+    free(ricsubscription_ie->ricAction_ToBeSetup_List.list.array);
+    ricsubscription_ie->ricAction_ToBeSetup_List.list.size = 0;
+    ricsubscription_ie->ricAction_ToBeSetup_List.list.count = 0;
+    ricsubscription_ie->ricAction_ToBeSetup_List.list.array = 0;
+  }
+
+  // clear subsequent action array
+  for (unsigned int i = 0; i < action_array_size; i++){
+    free(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction );
+  }
+  
+  free(action_array);
+  E2N_RICsubscriptionRequest_t * subscription_request = &(initMsg->value.choice.RICsubscriptionRequest);
+  
+  for(int i = 0; i < subscription_request->protocolIEs.list.size; i++){
+    subscription_request->protocolIEs.list.array[i] = 0;
+  }
+  
+  if( subscription_request->protocolIEs.list.size > 0){
+    free( subscription_request->protocolIEs.list.array);
+    subscription_request->protocolIEs.list.array = 0;
+    subscription_request->protocolIEs.list.size = 0;
+    subscription_request->protocolIEs.list.count = 0;
+  }
+  
+  free(IE_array);
+  free(initMsg);
+  e2ap_pdu_obj->choice.initiatingMessage = 0;
+  
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  mdclog_write(MDCLOG_DEBUG, "Freed subscription request memory ");
+};
+
+
+bool subscription_request::encode_e2ap_subscription(unsigned char *buf, size_t *size,  subscription_helper &dinput){
+
+  bool res;
+
+  initMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription;
+  initMsg->criticality = E2N_Criticality_ignore;
+  initMsg->value.present = E2N_InitiatingMessage__value_PR_RICsubscriptionRequest;
+
+  res = set_fields(initMsg, dinput);
+  if (!res){
+    return false;
+  }
+  
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(errbuf, errbuf_len);
+    error_string = "Constraints failed for encoding subscription request. Reason = " + error_string;
+    return false;
+  }
+
+  //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+  
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+    
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding Subscription  Request. Reason = " + error_string;
+    return false;
+  }
+  else {
+    if(*size < retval.encoded){
+      std::stringstream ss;
+      ss  <<"Error encoding Subscription  Request . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+      error_string = ss.str();
+      retval.encoded = -1;
+      return false;
+    }
+  }
+    
+  *size = retval.encoded;
+  return true;
+    
+}
+
+
+bool subscription_request::set_fields( E2N_InitiatingMessage_t * init_msg, subscription_helper &helper){
+
+  
+  int ie_index;
+  int result = 0;
+
+  if (init_msg == 0){
+    error_string = "Error. Invalid reference when getting fields from subscription request";
+    return false;
+  }
+
+  E2N_RICsubscriptionRequest_t * ric_subscription = &(init_msg->value.choice.RICsubscriptionRequest);
+  ric_subscription->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  E2N_RICsubscriptionRequest_IEs_t *ies_ricreq = &IE_array[ie_index];
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = helper.get_request_id();
+  ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
+  result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]);
+  assert(result == 0);
+     
+  ie_index = 1;
+  E2N_RICsubscriptionRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = helper.get_function_id();
+  result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]);
+  assert(result == 0);
+
+
+  ie_index = 2;
+  E2N_RICsubscriptionRequest_IEs_t *ies_actid = &IE_array[ie_index];
+  ies_actid->criticality = E2N_Criticality_reject;
+  ies_actid->id = E2N_ProtocolIE_ID_id_RICsubscription;
+  ies_actid->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RICsubscription;
+  E2N_RICsubscription_t *ricsubscription_ie = &ies_actid->value.choice.RICsubscription;
+
+  ricsubscription_ie->ricEventTriggerDefinition.buf = (uint8_t *) helper.get_event_def();
+  ricsubscription_ie->ricEventTriggerDefinition.size = helper.get_event_def_size();
+   
+  std::vector<Action> * ref_action_array = helper.get_list();
+  // do we need to resize  ?
+  // we don't care about contents, so just do a free/calloc
+  if(action_array_size < ref_action_array->size()){
+    std::cout <<"re-allocating action array from " << action_array_size << " to " << 2 * ref_action_array->size() <<  std::endl;
+    // free subsequent allocation
+    for (unsigned int i = 0; i < action_array_size; i++){
+      free(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction );
+    }
+    
+    action_array_size = 2 * ref_action_array->size();
+    free(action_array);
+    action_array = (E2N_RICaction_ToBeSetup_ItemIEs_t *)calloc(action_array_size, sizeof(E2N_RICaction_ToBeSetup_ItemIEs_t));
+    assert(action_array != 0);
+
+    // also need to add subsequent action and time to wait ..
+    for (unsigned int i = 0; i < action_array_size; i++){
+      action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction = (struct E2N_RICsubsequentAction *)calloc(1, sizeof(struct E2N_RICsubsequentAction));
+      assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction  != 0);
+    }
+    
+  }
+  
+  // reset the list count on ricAction_ToBeSetup_List;
+  ricsubscription_ie->ricAction_ToBeSetup_List.list.count = 0;
+  
+  for(unsigned int i = 0; i < ref_action_array->size(); i ++){
+    action_array[i].criticality = E2N_Criticality_ignore;
+    action_array[i].id = E2N_ProtocolIE_ID_id_RICaction_ToBeSetup_Item ;
+    action_array[i].value.present = E2N_RICaction_ToBeSetup_ItemIEs__value_PR_RICaction_ToBeSetup_Item;
+    action_array[i].value.choice.RICaction_ToBeSetup_Item.ricActionID = (*ref_action_array)[i].get_id();
+    action_array[i].value.choice.RICaction_ToBeSetup_Item.ricActionType = (*ref_action_array)[i].get_type();
+    action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricSubsequentActionType = (*ref_action_array)[i].get_subsequent_action();
+    action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricTimeToWait = (*ref_action_array)[i].get_wait();
+    
+    result = ASN_SEQUENCE_ADD(&ricsubscription_ie->ricAction_ToBeSetup_List, &(action_array[i]));
+    if (result == -1){
+      error_string = "Erorr : Unable to assign memory to add Action item to set up list";
+      return false;
+    }
+    
+  }
+  
+  result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]);
+  assert(result == 0);
+
+
+    
+  return true;
+};
+
+
+
+bool subscription_request:: get_fields(E2N_InitiatingMessage_t * init_msg,  subscription_helper & dout)
+{
+
+  if (init_msg == 0){
+    error_string = "Error. Invalid reference when getting fields from subscription request";
+    return false;
+  }
+  
+  E2N_RICrequestID_t *requestid;
+  E2N_RANfunctionID_t * ranfunctionid;
+  E2N_RICsubscription_t * ricsubscription;
+    
+  for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.count; edx++) {
+    E2N_RICsubscriptionRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       requestid = &memb_ptr->value.choice.RICrequestID;
+       dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
+       dout.set_function_id(*ranfunctionid);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RICsubscription):
+       ricsubscription = &memb_ptr->value.choice.RICsubscription;
+       dout.set_event_def(ricsubscription->ricEventTriggerDefinition.buf, ricsubscription->ricEventTriggerDefinition.size);
+         
+       for(int index = 0; index < ricsubscription->ricAction_ToBeSetup_List.list.count; index ++){
+         E2N_RICaction_ToBeSetup_ItemIEs_t * item = (E2N_RICaction_ToBeSetup_ItemIEs_t *)ricsubscription->ricAction_ToBeSetup_List.list.array[index];
+         if (item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction == NULL){
+           dout.add_action(item->value.choice.RICaction_ToBeSetup_Item.ricActionID, item->value.choice.RICaction_ToBeSetup_Item.ricActionType);
+         }
+         else{
+           std::string action_def = ""; // for now we are ignoring action definition
+           dout.add_action(item->value.choice.RICaction_ToBeSetup_Item.ricActionID, item->value.choice.RICaction_ToBeSetup_Item.ricActionType, action_def, item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricSubsequentActionType, item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricTimeToWait);
+         }   
+       };
+       
+       break;
+      }
+      
+  }
+    
+  //asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu);
+  return true;
+};
+
+
+
diff --git a/src/xapp-formats/e2ap/subscription_request.hpp b/src/xapp-formats/e2ap/subscription_request.hpp
new file mode 100644 (file)
index 0000000..28f419a
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+#pragma once
+
+#ifndef S_REQUEST_
+#define S_REQUEST_
+
+#include <mdclog/mdclog.h>
+#include <vector>
+#include <sstream>
+
+#include <asn_application.h>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_InitiatingMessage.h>
+#include <E2N_RICsubscriptionRequest.h>
+#include <E2N_RICsubscription.h>
+#include <E2N_ProtocolIE-Field.h>
+#include <E2N_ProtocolIE-Single-Container.h>
+#include <E2N_RICactions-ToBeSetup-List.h>
+#include <E2N_RICsubsequentAction.h>
+#include "subscription_helper.hpp"
+
+#define NUM_SUBSCRIPTION_REQUEST_IES 3
+#define INITIAL_REQUEST_LIST_SIZE 4
+  
+class subscription_request{   
+public:
+
+  subscription_request(std::string name);
+  subscription_request(void);
+  ~subscription_request(void);
+  
+  bool encode_e2ap_subscription(unsigned char *, size_t *,  subscription_helper &);
+  bool set_fields(E2N_InitiatingMessage_t *, subscription_helper &);
+  bool get_fields(E2N_InitiatingMessage_t *, subscription_helper &);
+    
+  std::string get_error(void) const{
+    return error_string;
+  }
+    
+private:
+    
+  E2N_InitiatingMessage_t *initMsg;
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+
+  E2N_RICsubscriptionRequest_IEs_t * IE_array;
+  E2N_RICaction_ToBeSetup_ItemIEs_t * action_array;
+  unsigned int action_array_size;  
+  char errbuf[128];
+  size_t errbuf_len = 128;
+  std::string _name;
+  std::string error_string;
+};
+
+
+
+#endif
diff --git a/src/xapp-formats/e2ap/subscription_response.cc b/src/xapp-formats/e2ap/subscription_response.cc
new file mode 100644 (file)
index 0000000..5308e81
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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 "subscription_response.hpp"
+
+/* The xAPP need only worry about the get_fields from a response, since it does
+not generate a response. Generating response however is included to support testing. 
+*/
+
+
+// Primarly for generation
+subscription_response::subscription_response(void){
+
+  e2ap_pdu_obj = 0;
+  e2ap_pdu_obj = (E2N_E2AP_PDU_t *)calloc(1, sizeof(E2N_E2AP_PDU_t));
+  assert(e2ap_pdu_obj != 0);
+
+  successMsg = 0;
+  successMsg = (E2N_SuccessfulOutcome_t *)calloc(1, sizeof(E2N_SuccessfulOutcome_t));
+  assert(successMsg != 0);
+
+  unsuccessMsg = 0;
+  unsuccessMsg = (E2N_UnsuccessfulOutcome_t *)calloc(1, sizeof(E2N_UnsuccessfulOutcome_t));
+  assert(unsuccessMsg != 0);
+
+  IE_array = 0;
+  IE_array = (E2N_RICsubscriptionResponse_IEs_t *)calloc(NUM_SUBSCRIPTION_RESPONSE_IES, sizeof(E2N_RICsubscriptionResponse_IEs_t));
+  assert(IE_array != 0);
+
+  IE_Failure_array = 0;
+  IE_Failure_array = (E2N_RICsubscriptionFailure_IEs_t *)calloc(NUM_SUBSCRIPTION_FAILURE_IES, sizeof(E2N_RICsubscriptionFailure_IEs_t));
+  assert(IE_Failure_array != 0);
+
+  ie_admitted_list = 0;
+  ie_admitted_list = (E2N_RICaction_Admitted_ItemIEs_t *)calloc(INITIAL_RESPONSE_LIST_SIZE, sizeof(E2N_RICaction_Admitted_ItemIEs_t));
+  assert(ie_admitted_list != 0);
+  ie_admitted_list_size = INITIAL_RESPONSE_LIST_SIZE;
+  
+  ie_not_admitted_list = 0;
+  ie_not_admitted_list = (E2N_RICaction_NotAdmitted_ItemIEs_t *)calloc(INITIAL_RESPONSE_LIST_SIZE, sizeof(E2N_RICaction_NotAdmitted_ItemIEs_t));
+  assert(ie_not_admitted_list != 0);
+  ie_not_admitted_list_size = INITIAL_RESPONSE_LIST_SIZE;
+
+
+
+
+  
+};
+
+  
+
+// Clear assigned protocolIE list from RIC indication IE container
+subscription_response::~subscription_response(void){
+
+  mdclog_write(MDCLOG_DEBUG, "Freeing subscription response memory");
+  E2N_RICaction_Admitted_List_t * response_admitted_list = (E2N_RICaction_Admitted_List_t *) &(IE_array[2].value.choice.RICaction_Admitted_List);
+  
+  for(int i = 0; i < response_admitted_list->list.size; i++){
+    response_admitted_list->list.array[i] = 0;
+  }
+
+  
+  if (response_admitted_list->list.size > 0){
+    free(response_admitted_list->list.array);
+    response_admitted_list->list.array = 0;
+    response_admitted_list->list.size = 0;
+    response_admitted_list->list.count = 0;
+  }
+
+  
+  E2N_RICaction_NotAdmitted_List_t * response_not_admitted_list = &(IE_array[3].value.choice.RICaction_NotAdmitted_List);
+  for(int i = 0; i < response_not_admitted_list->list.size; i++){
+    response_not_admitted_list->list.array[i] = 0;
+  }
+  
+  if (response_not_admitted_list->list.size > 0){
+    free(response_not_admitted_list->list.array);
+    response_not_admitted_list->list.array = 0;
+    response_not_admitted_list->list.size = 0;
+    response_not_admitted_list->list.count = 0;
+  }
+     
+  E2N_RICsubscriptionResponse_t * ric_subscription_response = &(successMsg->value.choice.RICsubscriptionResponse);
+  for(int i = 0; i < ric_subscription_response->protocolIEs.list.size ; i++){
+    ric_subscription_response->protocolIEs.list.array[i] = 0;
+  }
+  
+  if (ric_subscription_response->protocolIEs.list.size > 0){
+    free(ric_subscription_response->protocolIEs.list.array);
+    ric_subscription_response->protocolIEs.list.array = 0;
+    ric_subscription_response->protocolIEs.list.size = 0;
+    ric_subscription_response->protocolIEs.list.count = 0;
+  }
+  
+  
+  E2N_RICaction_NotAdmitted_List_t * failure_not_admitted_list = &(IE_Failure_array[2].value.choice.RICaction_NotAdmitted_List);
+  for(int i = 0; i < failure_not_admitted_list->list.size; i++){
+    failure_not_admitted_list->list.array[i] = 0;
+  }
+
+  if ( failure_not_admitted_list->list.size > 0){
+    free( failure_not_admitted_list->list.array);
+    failure_not_admitted_list->list.array = 0;
+    failure_not_admitted_list->list.size = 0;
+    failure_not_admitted_list->list.count = 0;
+  }
+  
+     
+  E2N_RICsubscriptionFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionFailure);
+  for(int i = 0; i < ric_subscription_failure->protocolIEs.list.size; i++){
+    ric_subscription_failure->protocolIEs.list.array[i] = 0;
+  }
+  
+  if (  ric_subscription_failure->protocolIEs.list.size > 0){
+    free(ric_subscription_failure->protocolIEs.list.array);
+    ric_subscription_failure->protocolIEs.list.array = 0;
+    ric_subscription_failure->protocolIEs.list.size = 0;
+    ric_subscription_failure->protocolIEs.list.count = 0;
+  }
+
+
+  free(ie_admitted_list);  
+  free(ie_not_admitted_list);
+  free(IE_Failure_array);
+  free(IE_array);
+
+  
+  ASN_STRUCT_FREE(asn_DEF_E2N_SuccessfulOutcome, successMsg);
+  ASN_STRUCT_FREE(asn_DEF_E2N_UnsuccessfulOutcome, unsuccessMsg);
+
+  
+  e2ap_pdu_obj->choice.initiatingMessage = NULL;
+  e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_NOTHING;
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
+
+  mdclog_write(MDCLOG_DEBUG, "Freed subscription response memory ");
+
+  
+};
+
+
+bool subscription_response::encode_e2ap_subscription_response(unsigned char *buf, size_t *size, subscription_response_helper &dinput, bool is_success){
+  
+
+  if(is_success){
+    set_fields_success(dinput);
+    e2ap_pdu_obj->present =  E2N_E2AP_PDU_PR_successfulOutcome;
+    e2ap_pdu_obj->choice.successfulOutcome = successMsg;
+
+    successMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription;
+    successMsg->criticality = E2N_Criticality_reject;
+    successMsg->value.present = E2N_SuccessfulOutcome__value_PR_RICsubscriptionResponse;   
+  }
+  else{
+    set_fields_unsuccess(dinput);
+    e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_unsuccessfulOutcome;
+    e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg;
+
+    unsuccessMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription;
+    unsuccessMsg->criticality = E2N_Criticality_reject;
+    unsuccessMsg->value.present = E2N_UnsuccessfulOutcome__value_PR_RICsubscriptionFailure;
+
+  }
+    
+  //xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj);
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(errbuf, errbuf_len);
+    error_string = "Constraints failed for encoding subscription response. Reason = " + error_string;
+    return false;
+  }
+    
+  asn_enc_rval_t res = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
+    
+  if(res.encoded == -1){
+    std::cout <<"Error encoding PDU. Reason =" << strerror(errno) << std::endl;
+    return false;
+  }
+  else {
+    if(*size < res.encoded){
+      fprintf(stderr,  "Buffer assigned too small to encode: %s",(char *)(asn_DEF_E2N_E2AP_PDU.name));
+      res.encoded = -1;
+      return false;
+    }
+  }
+    
+  *size = res.encoded;
+  return true;
+    
+}
+  
+void subscription_response::set_fields_success(subscription_response_helper &helper){
+
+  int ie_index;
+
+  E2N_RICsubscriptionResponse_t * subscription_response = &(successMsg->value.choice.RICsubscriptionResponse);
+  //reset list count ..
+  subscription_response->protocolIEs.list.count = 0;
+    
+  ie_index = 0;
+  E2N_RICsubscriptionResponse_IEs_t *ies_ricreq = &IE_array[ie_index];
+  
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = helper.get_request_id();
+  ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
+  ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index]));  
+
+  
+  ie_index = 1;
+  E2N_RICsubscriptionResponse_IEs_t *ies_ranfunc = &IE_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = helper.get_function_id();
+  ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index]));
+
+  
+  ie_index = 2;
+  E2N_RICsubscriptionResponse_IEs_t *ies_admitted_actid = &IE_array[ie_index];
+  ies_admitted_actid->criticality = E2N_Criticality_reject;
+  ies_admitted_actid->id = E2N_ProtocolIE_ID_id_RICactions_Admitted;
+  E2N_RICaction_Admitted_List_t *ric_admitted_actions_ie = &ies_admitted_actid->value.choice.RICaction_Admitted_List;
+  ric_admitted_actions_ie->list.count = 0;
+  std::vector<ActionResponse> * ref_admitted_action_array = helper.get_admitted_list();  
+
+  if(ref_admitted_action_array->size() ==  0){
+    ies_admitted_actid->value.present =  E2N_RICsubscriptionResponse_IEs__value_PR_NOTHING;
+  }
+  else{  
+    ies_admitted_actid->value.present =  E2N_RICsubscriptionResponse_IEs__value_PR_RICaction_Admitted_List;
+
+    // resize memory ?
+    if (ref_admitted_action_array->size() >= ie_admitted_list_size){
+      ie_admitted_list_size = 2 * ref_admitted_action_array->size();
+      free(ie_admitted_list);
+      ie_admitted_list = (E2N_RICaction_Admitted_ItemIEs_t *)calloc(ie_admitted_list_size, sizeof(E2N_RICaction_Admitted_ItemIEs_t));
+      assert(ie_admitted_list != 0);
+    };
+  
+
+    for(unsigned int i = 0; i < ref_admitted_action_array->size(); i ++){
+      ie_admitted_list[i].criticality = E2N_Criticality_ignore;
+      ie_admitted_list[i].id = E2N_ProtocolIE_ID_id_RICaction_Admitted_Item ;
+      ie_admitted_list[i].value.present = E2N_RICaction_Admitted_ItemIEs__value_PR_RICaction_Admitted_Item;
+      ie_admitted_list[i].value.choice.RICaction_Admitted_Item.ricActionID = (*ref_admitted_action_array)[i].get_id();
+      ASN_SEQUENCE_ADD(ric_admitted_actions_ie, &(ie_admitted_list[i]));
+    }
+  }  
+  ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index]));
+
+  // optional IE : add only if non-zero list 
+  ie_index = 3;
+  std::vector<ActionResponse> * ref_notadmitted_action_array = helper.get_not_admitted_list();
+  if (ref_notadmitted_action_array->size() > 0){
+    
+    E2N_RICsubscriptionResponse_IEs_t *ies_notadmitted_actid = &IE_array[ie_index];
+    ies_notadmitted_actid->criticality = E2N_Criticality_reject;
+    ies_notadmitted_actid->id = E2N_ProtocolIE_ID_id_RICactions_NotAdmitted;
+
+    E2N_RICaction_NotAdmitted_List_t *ric_not_admitted_actions_ie = &ies_notadmitted_actid->value.choice.RICaction_NotAdmitted_List;
+    ric_not_admitted_actions_ie->list.count = 0;
+  
+  
+    ies_notadmitted_actid->value.present =  E2N_RICsubscriptionResponse_IEs__value_PR_RICaction_NotAdmitted_List;
+  
+    // resize memory ?
+    if (ref_notadmitted_action_array->size() >= ie_not_admitted_list_size){
+      ie_not_admitted_list_size = 2 * ref_notadmitted_action_array->size();
+      free(ie_not_admitted_list);
+      ie_not_admitted_list = (E2N_RICaction_NotAdmitted_ItemIEs_t *)calloc(ie_not_admitted_list_size, sizeof(E2N_RICaction_NotAdmitted_ItemIEs_t));
+      assert(ie_not_admitted_list != 0);
+    
+    };
+  
+  
+    for(unsigned int i = 0; i < ref_notadmitted_action_array->size(); i ++){
+      ie_not_admitted_list[i].criticality = E2N_Criticality_ignore;
+      ie_not_admitted_list[i].id = E2N_ProtocolIE_ID_id_RICaction_NotAdmitted_Item ;
+      ie_not_admitted_list[i].value.present = E2N_RICaction_NotAdmitted_ItemIEs__value_PR_RICaction_NotAdmitted_Item;;
+      ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricActionID = (*ref_notadmitted_action_array)[i].get_id();
+
+      int cause = (*ref_notadmitted_action_array)[i].get_cause();
+      switch(cause){
+      case E2N_RICcause_PR_radioNetwork:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_transport:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_protocol:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol= (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_misc:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_ric:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      default:
+       mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Unknown RIC cause %d\n", __FILE__, __LINE__, cause);
+       return;
+      }
+
+      ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.present = (E2N_RICcause_PR)cause;      
+      ASN_SEQUENCE_ADD(ric_not_admitted_actions_ie, &(ie_not_admitted_list[i]));
+    }
+
+    ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index]));
+  }
+  
+}
+
+void subscription_response:: get_fields(E2N_SuccessfulOutcome_t * success_msg,  subscription_response_helper & dout)
+{
+
+  assert(success_msg != NULL);
+  
+  E2N_RICrequestID_t *requestid;
+  E2N_RANfunctionID_t * ranfunctionid;
+  E2N_RICaction_Admitted_List_t  * ric_admitted_action_list;
+  E2N_RICaction_NotAdmitted_List_t * ric_not_admitted_action_list;
+    
+  for(int edx = 0; edx < success_msg->value.choice.RICsubscriptionResponse.protocolIEs.list.count; edx++) {
+    E2N_RICsubscriptionResponse_IEs_t *memb_ptr = success_msg->value.choice.RICsubscriptionResponse.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       requestid = &memb_ptr->value.choice.RICrequestID;
+       dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
+       dout.set_function_id(*ranfunctionid);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RICactions_Admitted):
+       ric_admitted_action_list = &memb_ptr->value.choice.RICaction_Admitted_List;
+         
+       // admitted actions
+       for(int index = 0; index < ric_admitted_action_list->list.count; index ++){
+         E2N_RICaction_Admitted_ItemIEs_t * item = (E2N_RICaction_Admitted_ItemIEs_t *)ric_admitted_action_list->list.array[index];
+         long int id = item->value.choice.RICaction_Admitted_Item.ricActionID;
+         dout.get_admitted_list()->push_back(ActionResponse(id));
+       };
+
+       break;
+
+      case (E2N_ProtocolIE_ID_id_RICactions_NotAdmitted):
+       ric_not_admitted_action_list = &memb_ptr->value.choice.RICaction_NotAdmitted_List;
+         
+       for(int index = 0; index < ric_not_admitted_action_list->list.count; index ++){
+         E2N_RICaction_NotAdmitted_ItemIEs_t * item = (E2N_RICaction_NotAdmitted_ItemIEs_t *)ric_not_admitted_action_list->list.array[index];
+         long int id = item->value.choice.RICaction_NotAdmitted_Item.ricActionID;
+         int cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.present;
+         int sub_cause;
+         switch(cause){
+             
+         case  E2N_RICcause_PR_radioNetwork :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork;
+           break;
+             
+         case E2N_RICcause_PR_transport :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport;
+           break;
+             
+         case  E2N_RICcause_PR_protocol :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol;
+           break;
+             
+         case E2N_RICcause_PR_misc :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc;
+           break;
+             
+         case E2N_RICcause_PR_ric :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric;
+           break;
+             
+         default:
+           std::cout <<"Error ! Illegal cause enum" << cause << std::endl;
+           return;
+         }  
+         dout.get_not_admitted_list()->push_back(ActionResponse(id, cause, sub_cause));
+       }
+       break;
+      }
+      
+  }
+    
+  //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu);
+}
+
+
+void subscription_response::set_fields_unsuccess( subscription_response_helper &helper){
+
+  int ie_index;
+  E2N_RICsubscriptionFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionFailure);
+  // reset list count
+  ric_subscription_failure->protocolIEs.list.count = 0;
+  
+  ie_index = 0;
+  E2N_RICsubscriptionFailure_IEs_t *ies_ricreq = &IE_Failure_array[ie_index];
+  ies_ricreq->criticality = E2N_Criticality_reject;
+  ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
+  ies_ricreq->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_RICrequestID;
+  E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
+  ricrequest_ie->ricRequestorID = helper.get_request_id();
+  ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
+  ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, &(IE_Failure_array[ie_index]));  
+  
+  ie_index = 1;
+  E2N_RICsubscriptionFailure_IEs_t *ies_ranfunc = &IE_Failure_array[ie_index];
+  ies_ranfunc->criticality = E2N_Criticality_reject;
+  ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
+  ies_ranfunc->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_RANfunctionID;
+  E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
+  *ranfunction_ie = helper.get_function_id();
+  ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, &(IE_Failure_array[ie_index]));  
+
+  ie_index = 2;
+  E2N_RICsubscriptionFailure_IEs_t *ies_notadmitted_actid = &IE_Failure_array[ie_index];
+  ies_notadmitted_actid->criticality = E2N_Criticality_reject;
+  ies_notadmitted_actid->id = E2N_ProtocolIE_ID_id_RICactions_NotAdmitted;
+  E2N_RICaction_NotAdmitted_List_t *ric_not_admitted_actions_ie = &ies_notadmitted_actid->value.choice.RICaction_NotAdmitted_List;
+  ric_not_admitted_actions_ie->list.count = 0;   
+  std::vector<ActionResponse> * ref_notadmitted_action_array = helper.get_not_admitted_list();  
+  if(ref_notadmitted_action_array->size() == 0){
+    ies_notadmitted_actid->value.present =  E2N_RICsubscriptionFailure_IEs__value_PR_NOTHING;
+  }
+  else{
+    ies_notadmitted_actid->value.present =  E2N_RICsubscriptionFailure_IEs__value_PR_RICaction_NotAdmitted_List;
+
+    // resize memory  ?
+    if (ref_notadmitted_action_array->size() >= ie_not_admitted_list_size){
+      ie_not_admitted_list_size = 2 * ref_notadmitted_action_array->size();
+      free(ie_not_admitted_list);
+      ie_not_admitted_list = (E2N_RICaction_NotAdmitted_ItemIEs_t *)calloc(ie_not_admitted_list_size, sizeof(E2N_RICaction_NotAdmitted_ItemIEs_t));
+      assert(ie_not_admitted_list != 0);
+    };
+      
+  
+    // reset the list count on ricAction_ToBeSetup_List;
+    for(unsigned int i = 0; i < ref_notadmitted_action_array->size(); i ++){
+      ie_not_admitted_list[i].criticality = E2N_Criticality_ignore;
+      ie_not_admitted_list[i].id = E2N_ProtocolIE_ID_id_RICaction_NotAdmitted_Item ;
+      ie_not_admitted_list[i].value.present = E2N_RICaction_NotAdmitted_ItemIEs__value_PR_RICaction_NotAdmitted_Item;;
+      ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricActionID = (*ref_notadmitted_action_array)[i].get_id();
+
+      int cause = (*ref_notadmitted_action_array)[i].get_cause();
+      switch(cause){
+      case E2N_RICcause_PR_radioNetwork:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_transport:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_protocol:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol= (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_misc:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      case E2N_RICcause_PR_ric:
+       ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric = (*ref_notadmitted_action_array)[i].get_sub_cause();
+       break;
+      default:
+       mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Unknown RIC cause %d\n", __FILE__, __LINE__, cause);
+       return ;
+      }
+
+      ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.present = (E2N_RICcause_PR)cause;
+      
+      ASN_SEQUENCE_ADD(ric_not_admitted_actions_ie, &(ie_not_admitted_list[i]));
+    }
+
+  }
+  ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, &(IE_Failure_array[ie_index]));  
+
+
+  // // criticality diagnostics is not generated/parsed currently since optional
+  // i = 3;
+  // E2N_RICsubscriptionFailure_IEs_t *ies_criticality_diagnostics= &IE_Failure_array[i];
+  // ies_criticality_diagnostics->criticality = E2N_Criticality_ignore;
+  // ies_criticality_diagnostics->id = E2N_ProtocolIE_ID_id_CriticalityDiagnostics ;
+  // ies_criticality_diagnostics->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_NOTHING;
+
+    
+}
+
+void subscription_response:: get_fields(E2N_UnsuccessfulOutcome_t * unsuccess_msg,  subscription_response_helper & dout)
+{
+
+  assert(unsuccess_msg != NULL);
+  
+  E2N_RICrequestID_t *requestid;
+  E2N_RANfunctionID_t * ranfunctionid;
+  E2N_RICaction_NotAdmitted_List_t * ric_not_admitted_action_list;
+    
+  for(int edx = 0; edx < unsuccess_msg->value.choice.RICsubscriptionFailure.protocolIEs.list.count; edx++) {
+    E2N_RICsubscriptionFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICsubscriptionFailure.protocolIEs.list.array[edx];
+    
+    switch(memb_ptr->id)
+      {
+      case (E2N_ProtocolIE_ID_id_RICrequestID):
+       requestid = &memb_ptr->value.choice.RICrequestID;
+       dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
+       break;
+         
+      case (E2N_ProtocolIE_ID_id_RANfunctionID):
+       ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
+       dout.set_function_id(*ranfunctionid);
+       break;
+         
+
+      case (E2N_ProtocolIE_ID_id_RICactions_NotAdmitted):
+       ric_not_admitted_action_list = &memb_ptr->value.choice.RICaction_NotAdmitted_List;
+         
+       for(int index = 0; index < ric_not_admitted_action_list->list.count; index ++){
+         E2N_RICaction_NotAdmitted_ItemIEs_t * item = (E2N_RICaction_NotAdmitted_ItemIEs_t *)ric_not_admitted_action_list->list.array[index];
+         long int id = item->value.choice.RICaction_NotAdmitted_Item.ricActionID;
+         int cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.present;
+         int sub_cause;
+         switch(cause){
+             
+         case  E2N_RICcause_PR_radioNetwork :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork;
+           break;
+             
+         case E2N_RICcause_PR_transport :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport;
+           break;
+             
+         case  E2N_RICcause_PR_protocol :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol;
+           break;
+             
+         case E2N_RICcause_PR_misc :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc;
+           break;
+             
+         case E2N_RICcause_PR_ric :
+           sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric;
+           break;
+             
+         default:
+           mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Unknown RIC cause %d\n", __FILE__, __LINE__, cause);
+           return;
+         }  
+         dout.get_not_admitted_list()->push_back(ActionResponse(id, cause, sub_cause));
+       }
+       break;
+      }
+      
+  }
+    
+  //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu);
+}
+
+
+
diff --git a/src/xapp-formats/e2ap/subscription_response.hpp b/src/xapp-formats/e2ap/subscription_response.hpp
new file mode 100644 (file)
index 0000000..28fad4e
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+==================================================================================
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+#pragma once
+
+#ifndef S_RESPONSE_
+#define S_RESPONSE_
+
+#include <mdclog/mdclog.h>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <asn_application.h>
+#include <E2N_E2AP-PDU.h>
+#include <E2N_SuccessfulOutcome.h>
+#include <E2N_UnsuccessfulOutcome.h>
+#include <E2N_ProtocolIE-Field.h>
+#include <E2N_ProtocolIE-Single-Container.h>
+#include <E2N_ProcedureCode.h>
+#include "response_helper.hpp"
+
+#define NUM_SUBSCRIPTION_RESPONSE_IES 4
+#define NUM_SUBSCRIPTION_FAILURE_IES 3
+#define INITIAL_RESPONSE_LIST_SIZE 4
+  
+class subscription_response{   
+public:
+    
+  subscription_response(void);
+  ~subscription_response(void);
+    
+  bool encode_e2ap_subscription_response(unsigned char *, size_t *,  subscription_response_helper &, bool);
+  void get_fields(E2N_SuccessfulOutcome_t *, subscription_response_helper &);    
+  void get_fields(E2N_UnsuccessfulOutcome_t *, subscription_response_helper &);
+  
+  std::string get_error(void) const{
+    return error_string;
+  }
+    
+private:
+
+  void set_fields_success( subscription_response_helper &);
+  void set_fields_unsuccess( subscription_response_helper &);
+
+  E2N_E2AP_PDU_t * e2ap_pdu_obj;
+  E2N_SuccessfulOutcome_t * successMsg;
+  E2N_UnsuccessfulOutcome_t * unsuccessMsg;
+    
+
+  E2N_RICsubscriptionResponse_IEs_t *IE_array;
+  E2N_RICsubscriptionFailure_IEs_t *IE_Failure_array;
+  
+
+  E2N_RICaction_Admitted_ItemIEs_t * ie_admitted_list;
+  E2N_RICaction_NotAdmitted_ItemIEs_t * ie_not_admitted_list;
+  unsigned int ie_admitted_list_size, ie_not_admitted_list_size;
+  
+  char errbuf[128];
+  size_t errbuf_len = 128;
+  std::string error_string;
+};
+
+
+
+
+#endif
diff --git a/src/xapp-formats/e2sm/e2sm.cc b/src/xapp-formats/e2sm/e2sm.cc
new file mode 100644 (file)
index 0000000..c476c83
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+  ==================================================================================
+
+  Copyright (c) 2018-2019 AT&T Intellectual Property.
+  
+  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, softwares
+  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.
+  ==================================================================================
+*/
+
+/* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */
+
+#include "e2sm.hpp"
+
+
+
+  //initialize
+  e2sm_event_trigger::e2sm_event_trigger(void){
+
+    memset(&gNodeB_ID, 0, sizeof(E2N_GlobalGNB_ID_t));
+
+    event_trigger = 0;
+    event_trigger = ( E2N_E2SM_gNB_X2_eventTriggerDefinition_t *)calloc(1, sizeof( E2N_E2SM_gNB_X2_eventTriggerDefinition_t));
+    assert(event_trigger != 0);
+    
+    // allocate space for gNodeB id  (used for encoding)
+    gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0;
+    gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
+    assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
+    
+    // allocate space for plmn identity  (used for encoding)
+    gNodeB_ID.pLMN_Identity.buf = 0;
+    gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
+    assert(gNodeB_ID.pLMN_Identity.buf != 0);
+
+    ie_list = 0;
+    ie_list = ( struct E2N_InterfaceProtocolIE_Item *) calloc(INITIAL_LIST_SIZE, sizeof( struct E2N_InterfaceProtocolIE_Item));
+    assert(ie_list != 0);
+    ie_list_size = INITIAL_LIST_SIZE;
+
+    condition_list = 0;
+    condition_list = (E2N_E2SM_gNB_X2_eventTriggerDefinition::E2N_E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List *) calloc(1, sizeof(E2N_E2SM_gNB_X2_eventTriggerDefinition::E2N_E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List ));
+    assert(condition_list != 0);
+
+    
+  };
+  
+e2sm_event_trigger::~e2sm_event_trigger(void){
+
+  mdclog_write(MDCLOG_DEBUG, "Freeing event trigger object memory");
+  for(int i = 0; i < condition_list->list.size; i++){
+    condition_list->list.array[i] = 0;
+  }
+
+  if (condition_list->list.size > 0){
+    free(condition_list->list.array);
+    condition_list->list.array = 0;
+    condition_list->list.size = 0;
+    condition_list->list.count = 0;
+  }
+
+  free(condition_list);
+  condition_list = 0;
+  
+  free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
+  gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0;
+  
+  free(gNodeB_ID.pLMN_Identity.buf);
+  gNodeB_ID.pLMN_Identity.buf = 0;
+  
+  free(ie_list);
+  ie_list = 0;
+  
+  event_trigger->interface_ID.choice.global_gNB_ID = 0;
+  event_trigger->interfaceProtocolIE_List = 0;
+  
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger);
+  mdclog_write(MDCLOG_DEBUG, "Freed event trigger object memory");
+
+};
+
+bool e2sm_event_trigger::encode_event_trigger(unsigned char *buf, size_t *size, e2sm_event_trigger_helper &helper){
+  
+  bool res;
+  res = set_fields(event_trigger, helper);
+  if (!res){
+    return false;
+  }
+  
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(&errbuf[0], errbuf_len);
+    return false;
+  }
+
+  //xer_fprint(stdout, &asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger);
+  
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, buf, *size);
+  
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    return false;
+  }
+  else if (retval.encoded > *size){
+    std::stringstream ss;
+    ss  <<"Error encoding event trigger definition. Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+    error_string = ss.str();
+    return false;
+  }
+  else{
+    *size = retval.encoded;
+  }
+  
+  return true;
+}
+
+
+bool e2sm_event_trigger::set_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){
+  if(ref_event_trigger == 0){
+    error_string = "Invalid reference for Event Trigger Definition set fields";
+    return false;
+  }
+      
+  // set the message type
+  ref_event_trigger->interfaceMessageType.procedureCode = helper.procedure_code;
+  ref_event_trigger->interfaceMessageType.typeOfMessage = helper.message_type;
+  
+  ref_event_trigger->interfaceDirection = helper.interface_direction; 
+  ref_event_trigger->interface_ID.present = E2N_Interface_ID_PR_global_gNB_ID;
+  
+  ref_event_trigger->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
+
+  // to do : need to put correct code here for upding plmn id and gNodeB
+  // for now just place holders :
+  //================================================================
+  memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
+  gNodeB_ID.pLMN_Identity.size = 3;
+  
+  memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
+  gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
+  
+  // we only do global gNodeB id for now, not eNodeB
+  gNodeB_ID.gNB_ID.present = E2N_GNB_ID_PR_gNB_ID;
+  //================================================================
+  
+  
+  // Add in any requested IE items
+  std::vector<Item> * ref_ie_array = helper.get_list();
+
+  if (ref_ie_array->size() == 0){
+    ref_event_trigger->interfaceProtocolIE_List = 0;
+    
+  }
+  else{
+    ref_event_trigger->interfaceProtocolIE_List = condition_list;
+    
+    //resize memory ? 
+    if(ref_ie_array->size() > ie_list_size){
+      ie_list_size = 2 * ref_ie_array->size();
+      free(ie_list);
+      ie_list = (struct E2N_InterfaceProtocolIE_Item *)calloc(ie_list_size, sizeof(struct E2N_InterfaceProtocolIE_Item));
+      assert(ie_list != 0);
+    }
+    
+    // reset the count so that adds start from the beginning
+    ref_event_trigger->interfaceProtocolIE_List->list.count = 0;
+    
+    for(unsigned int i = 0; i < ref_ie_array->size(); i++){
+
+      ie_list[i].interfaceProtocolIE_ID = (*ref_ie_array)[i].interface_id;
+      ie_list[i].interfaceProtocolIE_Test = (*ref_ie_array)[i].test;
+      
+      //switch(ie_list[i].interfaceProtocolIE_Value.present){
+      switch((*ref_ie_array)[i].val_type){
+       
+      case (E2N_InterfaceProtocolIE_Value_PR_valueInt):
+       ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueInt;
+       ie_list[i].interfaceProtocolIE_Value.choice.valueInt = (*ref_ie_array)[i].value_n;
+       break;
+       
+      case (E2N_InterfaceProtocolIE_Value_PR_valueEnum):
+       ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueEnum;
+       ie_list[i].interfaceProtocolIE_Value.choice.valueEnum = (*ref_ie_array)[i].value_n;
+       break;
+       
+      case (E2N_InterfaceProtocolIE_Value_PR_valueBool):
+       ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueBool;
+       ie_list[i].interfaceProtocolIE_Value.choice.valueBool = (*ref_ie_array)[i].value_n;
+       break;
+       
+      case (E2N_InterfaceProtocolIE_Value_PR_valueBitS):
+       ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueBitS;
+       ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.buf = (uint8_t *)(*ref_ie_array)[i].value_s.c_str();
+       ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.size = (*ref_ie_array)[i].value_s.length();
+       break;
+
+      case (E2N_InterfaceProtocolIE_Value_PR_valueOctS):
+       ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueOctS;
+       ie_list[i].interfaceProtocolIE_Value.choice.valueOctS.buf = (uint8_t *)(*ref_ie_array)[i].value_s.c_str();
+       ie_list[i].interfaceProtocolIE_Value.choice.valueOctS.size = (*ref_ie_array)[i].value_s.length();
+       break;
+
+      default:
+       {
+         std::stringstream ss;
+         ss <<"Error ! " << __FILE__ << "," << __LINE__ << " illegal enum " << (*ref_ie_array)[i].val_type << " for interface Protocol IE value" << std::endl;
+         std::string error_string = ss.str();
+         return false;
+       }
+      }
+      
+      ASN_SEQUENCE_ADD(ref_event_trigger->interfaceProtocolIE_List, &ie_list[i]);
+    }
+  }
+
+  return true;
+};
+  
+
+bool e2sm_event_trigger::get_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){
+
+  if (ref_event_trigger == 0){
+    error_string = "Invalid reference for Event Trigger definition get fields";
+    return false;
+  }
+  
+  helper.procedure_code = ref_event_trigger->interfaceMessageType.procedureCode;
+  helper.message_type   = ref_event_trigger->interfaceMessageType.typeOfMessage;
+  helper.interface_direction = ref_event_trigger->interfaceDirection;
+  
+  helper.plmn_id.assign((const char *)ref_event_trigger->interface_ID.choice.global_gNB_ID->pLMN_Identity.buf, ref_event_trigger->interface_ID.choice.global_gNB_ID->pLMN_Identity.size);
+  helper.egNB_id.assign((const char *)ref_event_trigger->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.buf, ref_event_trigger->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.size);
+  for(int i = 0; i < ref_event_trigger->interfaceProtocolIE_List->list.count; i++){
+    struct E2N_InterfaceProtocolIE_Item * ie_item = ref_event_trigger->interfaceProtocolIE_List->list.array[i];
+    switch(ie_item->interfaceProtocolIE_Value.present){
+    case (E2N_InterfaceProtocolIE_Value_PR_valueInt):
+      helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, ie_item->interfaceProtocolIE_Value.choice.valueInt);
+      break;
+    case (E2N_InterfaceProtocolIE_Value_PR_valueEnum):
+      helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, ie_item->interfaceProtocolIE_Value.choice.valueEnum);
+      break;
+    case (E2N_InterfaceProtocolIE_Value_PR_valueBool):
+      helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, ie_item->interfaceProtocolIE_Value.choice.valueBool);            
+      break;
+    case (E2N_InterfaceProtocolIE_Value_PR_valueBitS):
+      helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, std::string((const char *)ie_item->interfaceProtocolIE_Value.choice.valueBitS.buf,ie_item->interfaceProtocolIE_Value.choice.valueBitS.size) );
+      break;
+    case (E2N_InterfaceProtocolIE_Value_PR_valueOctS):
+      helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, std::string((const char *)ie_item->interfaceProtocolIE_Value.choice.valueOctS.buf,ie_item->interfaceProtocolIE_Value.choice.valueOctS.size) );
+      break;
+    default:
+      mdclog_write(MDCLOG_ERR, "Error : %s, %d: Unkown interface protocol IE type %d in event trigger definition\n", __FILE__, __LINE__, ie_item->interfaceProtocolIE_Value.present);
+      return false;
+    }
+  }
+  
+  return true;
+};
+    
+
+  
+   
+// initialize
+e2sm_indication::e2sm_indication(void) {
+  
+  memset(&gNodeB_ID, 0, sizeof(E2N_GlobalGNB_ID_t));
+    
+  // allocate space for gNodeB id  (used for encoding)
+  gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
+  assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
+    
+  // allocate space for plmn identity  (used for encoding)
+  gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
+  assert(gNodeB_ID.pLMN_Identity.buf != 0);
+
+  header = 0;
+  header = (E2N_E2SM_gNB_X2_indicationHeader_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_indicationHeader_t));
+  assert(header != 0);
+
+  message = 0;
+  message = (E2N_E2SM_gNB_X2_indicationMessage_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_indicationMessage_t));
+  assert(message != 0);
+}
+  
+e2sm_indication::~e2sm_indication(void){
+  mdclog_write(MDCLOG_DEBUG, "Freeing E2N_E2SM Indication  object memory");
+
+  free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
+  free(gNodeB_ID.pLMN_Identity.buf);
+  
+  header->interface_ID.choice.global_gNB_ID = 0;
+
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_indicationHeader, header);
+
+  message->interfaceMessage.buf = 0;
+  message->interfaceMessage.size = 0;
+
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_indicationMessage, message);
+  mdclog_write(MDCLOG_DEBUG, "Freed E2SM Indication  object memory");
+    
+}
+  
+  
+
+bool e2sm_indication::encode_indication_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){
+    
+  bool res;
+  res = set_header_fields(header, helper);
+  if (!res){
+    return false;
+  }
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_indicationHeader, header, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(&errbuf[0], errbuf_len);
+    error_string = "E2SM Indication Header Constraint failed : " + error_string;
+
+    return false;
+  }
+
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_indicationHeader, header, buf, *size);
+
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding E2N_E2SM Indication Header. Reason = " + error_string;
+    return false;
+  }
+  else if (retval.encoded > *size){
+    std::stringstream ss;
+    ss  <<"Error encoding E2SM Indication Header . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+    error_string = ss.str();
+    return false;
+  }
+  else{
+    *size = retval.encoded;
+  }
+    
+  return true;
+}
+
+
+bool e2sm_indication::encode_indication_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){
+
+  set_message_fields(message, helper); 
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_indicationMessage, message, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(&errbuf[0], errbuf_len);
+    error_string = "E2SM Indication Message Constraint failed : " + error_string;
+    return false;
+  }
+
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_indicationMessage, message, buf, *size);
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding E2SM Indication Header. Reason = " + error_string;
+    return false;
+  }
+  else if (retval.encoded > *size){
+    std::stringstream ss;
+    ss  <<"Error encoding E2N_E2SM Indication Message . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+    error_string = ss.str();
+    
+    return false;
+  }
+  else{
+    *size = retval.encoded;
+  }
+  
+  return true;
+}
+
+
+
+// Used when generating an indication header 
+bool e2sm_indication::set_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *header,  e2sm_header_helper &helper){
+
+  if (header == 0){
+    error_string = "Invalid reference for E2SM Indication Header set fields";
+    return false;
+  }
+  
+  
+  header->interfaceDirection = helper.interface_direction;
+  header->interface_ID.present = E2N_Interface_ID_PR_global_gNB_ID;
+  header->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
+
+
+  // to do : need to put correct code here for upding plmn id and gNodeB
+  // for now just place holders :
+  memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
+  gNodeB_ID.pLMN_Identity.size = 3;
+  
+  memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
+  gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
+  
+  // we only do global gNodeB id for now, not eNodeB
+  gNodeB_ID.gNB_ID.present = E2N_GNB_ID_PR_gNB_ID;
+
+  return true;
+  
+};
+
+
+// used when decoding an indication header
+bool e2sm_indication::get_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *header,  e2sm_header_helper &helper){
+
+  if (header == 0){
+    error_string = "Invalid reference for E2SM Indication header get fields";
+    return false;
+  }
+  
+  helper.interface_direction = header->interfaceDirection;
+  helper.plmn_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->pLMN_Identity.buf, header->interface_ID.choice.global_gNB_ID->pLMN_Identity.size);
+  helper.egNB_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.buf, header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.size);
+  
+  // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing)
+
+  return true;
+}
+
+
+
+// Used when generating an indication message 
+bool   e2sm_indication::set_message_fields(E2N_E2SM_gNB_X2_indicationMessage_t *interface_message,  e2sm_message_helper &helper){
+
+  if(interface_message == 0){
+    error_string = "Invalid reference for E2SM Indication Message set fields";
+    return false;
+  }
+
+  // interface-message is an octet string. just point it to the buffer
+  interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]);
+  interface_message->interfaceMessage.size = helper.x2ap_pdu_size;
+
+  return true;
+  
+};
+
+// used when decoding an indication message
+bool e2sm_indication::get_message_fields( E2N_E2SM_gNB_X2_indicationMessage_t *interface_message, e2sm_message_helper &helper){
+
+  
+  if(interface_message == 0){
+    error_string = "Invalid reference for E2SM Indication Message get fields";
+    return false;
+  }
+
+  // interface message is an octet string
+  helper.x2ap_pdu = interface_message->interfaceMessage.buf;;
+  helper.x2ap_pdu_size = interface_message->interfaceMessage.size;
+
+  return true;
+  
+}
+  
+
+   
+// initialize
+e2sm_control::e2sm_control(void) {
+  
+  memset(&gNodeB_ID, 0, sizeof(E2N_GlobalGNB_ID_t));
+    
+  // allocate space for gNodeB id  (used for encoding)
+  gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
+  assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
+    
+  // allocate space for plmn identity  (used for encoding)
+  gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
+  assert(gNodeB_ID.pLMN_Identity.buf != 0);
+
+  header = 0;
+  header = (E2N_E2SM_gNB_X2_controlHeader_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_controlHeader_t));
+  assert(header != 0);
+
+  message = 0;
+  message = (E2N_E2SM_gNB_X2_controlMessage_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_controlMessage_t));
+  assert(message != 0);
+}
+  
+e2sm_control::~e2sm_control(void){
+  mdclog_write(MDCLOG_DEBUG, "Freeing E2SM Control  object memory");
+
+  free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
+  free(gNodeB_ID.pLMN_Identity.buf);
+  header->interface_ID.choice.global_gNB_ID = 0;
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_controlHeader, header);
+
+  message->interfaceMessage.buf = 0;
+  ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_controlMessage, message);
+
+  mdclog_write(MDCLOG_DEBUG, "Freed E2SM Control  object memory");
+    
+}
+  
+  
+
+bool e2sm_control::encode_control_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){
+    
+  bool res;
+  res = set_header_fields(header, helper);
+  if (!res){
+    return false;
+  }
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_controlHeader, header, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(&errbuf[0], errbuf_len);
+    error_string = "E2SM Control Header Constraint failed : " + error_string;
+
+    return false;
+  }
+
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_controlHeader, header, buf, *size);
+
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding E2SM Control Header. Reason = " + error_string;
+    return false;
+  }
+  else if (retval.encoded > *size){
+    std::stringstream ss;
+    ss  <<"Error encoding E2N_E2SM Control Header . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+    error_string = ss.str();
+    return false;
+  }
+  else{
+    *size = retval.encoded;
+  }
+    
+  return true;
+}
+
+
+bool e2sm_control::encode_control_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){
+
+  set_message_fields(message, helper); 
+
+  int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_controlMessage, message, errbuf, &errbuf_len);
+  if(ret_constr){
+    error_string.assign(&errbuf[0], errbuf_len);
+    error_string = "E2SM Control Message Constraint failed : " + error_string;
+    return false;
+  }
+
+  asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_controlMessage, message, buf, *size);
+  if(retval.encoded == -1){
+    error_string.assign(strerror(errno));
+    error_string = "Error encoding E2SM Control Message. Reason = " + error_string;
+    return false;
+  }
+  else if (retval.encoded > *size){
+    std::stringstream ss;
+    ss  <<"Error encoding E2SM Control Message . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
+    error_string = ss.str();
+    
+    return false;
+  }
+  else{
+    *size = retval.encoded;
+  }
+  
+  return true;
+}
+
+
+
+// Used when generating an indication header 
+bool e2sm_control::set_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *header,  e2sm_header_helper &helper){
+
+  if (header == 0){
+    error_string = "Invalid reference for E2SM Control Header set fields";
+    return false;
+  }
+  
+  
+  header->interfaceDirection = helper.interface_direction;
+  header->interface_ID.present = E2N_Interface_ID_PR_global_gNB_ID;
+  header->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
+
+
+  // to do : need to put correct code here for upding plmn id and gNodeB
+  // for now just place holders :
+  memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
+  gNodeB_ID.pLMN_Identity.size = 3;
+  
+  memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
+  gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
+  
+  // we only do global gNodeB id for now, not eNodeB
+  gNodeB_ID.gNB_ID.present = E2N_GNB_ID_PR_gNB_ID;
+
+  return true;
+  
+};
+
+
+// used when decoding an indication header
+bool e2sm_control::get_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *header,  e2sm_header_helper &helper){
+
+  if (header == 0){
+    error_string = "Invalid reference for E2SM Control header get fields";
+    return false;
+  }
+  
+  helper.interface_direction = header->interfaceDirection;
+  helper.plmn_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->pLMN_Identity.buf, header->interface_ID.choice.global_gNB_ID->pLMN_Identity.size);
+  helper.egNB_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.buf, header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.size);
+  
+  // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing)
+
+  return true;
+}
+
+
+
+// Used when generating an indication message 
+bool   e2sm_control::set_message_fields(E2N_E2SM_gNB_X2_controlMessage_t *interface_message,  e2sm_message_helper &helper){
+
+  if(interface_message == 0){
+    error_string = "Invalid reference for E2SM Control Message set fields";
+    return false;
+  }
+
+  // interface-message is an octet string. just point it to the buffer
+  interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]);
+  interface_message->interfaceMessage.size = helper.x2ap_pdu_size;
+
+  return true;
+  
+};
+
+// used when decoding an indication message
+bool e2sm_control::get_message_fields( E2N_E2SM_gNB_X2_controlMessage_t *interface_message, e2sm_message_helper &helper){
+
+  
+  if(interface_message == 0){
+    error_string = "Invalid reference for E2SM Control Message get fields";
+    return false;
+  }
+
+  // interface message is an octet string
+  helper.x2ap_pdu = interface_message->interfaceMessage.buf;;
+  helper.x2ap_pdu_size = interface_message->interfaceMessage.size;
+
+  return true;
+  
+}
+  
diff --git a/src/xapp-formats/e2sm/e2sm.hpp b/src/xapp-formats/e2sm/e2sm.hpp
new file mode 100644 (file)
index 0000000..a16d95c
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+
+/* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */
+
+#ifndef E2SM_
+#define E2SM_
+
+
+#include <sstream>
+#include <mdclog/mdclog.h>
+#include <E2N_E2SM-gNB-X2-indicationHeader.h>
+#include <E2N_E2SM-gNB-X2-indicationMessage.h>
+#include <E2N_E2SM-gNB-X2-controlHeader.h>
+#include <E2N_E2SM-gNB-X2-controlMessage.h>
+#include <E2N_E2SM-gNB-X2-eventTriggerDefinition.h>
+
+#include <E2N_GlobalGNB-ID.h>
+#include <E2N_TypeOfMessage.h>
+#include <E2N_InterfaceProtocolIE-Item.h>
+
+#include<E2N_InterfaceProtocolIE-ID.h>
+#include<E2N_InterfaceProtocolIE-Value.h>
+#include<E2N_InterfaceProtocolIE-Test.h>
+#include "../../xapp-formats/e2sm/e2sm_helpers.hpp"
+
+#define INITIAL_LIST_SIZE 4
+
+  
+
+  
+/* builder class for E2SM event trigger definition */
+
+class e2sm_event_trigger {
+public:
+  e2sm_event_trigger(void);
+  ~e2sm_event_trigger(void);
+    
+  bool set_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t *, e2sm_event_trigger_helper &);
+  bool get_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t *, e2sm_event_trigger_helper &);
+  bool encode_event_trigger(unsigned char *, size_t *, e2sm_event_trigger_helper &);
+
+  std::string  get_error (void) const {return error_string ;};
+  
+private:
+
+  E2N_E2SM_gNB_X2_eventTriggerDefinition_t * event_trigger; // used for encoding
+  E2N_GlobalGNB_ID_t gNodeB_ID;
+  struct E2N_InterfaceProtocolIE_Item * ie_list;
+  unsigned int ie_list_size;
+    
+  //std::vector<struct InterfaceProtocolIE_Item> ie_list;
+  E2N_E2SM_gNB_X2_eventTriggerDefinition::E2N_E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List *condition_list;
+    
+  char errbuf[128];
+  size_t errbuf_len;
+  std::string error_string;
+};
+  
+    
+/* builder class for E2SM indication  using ASN1c */
+  
+class e2sm_indication {
+public:
+    
+  e2sm_indication(void);
+  ~e2sm_indication(void);
+    
+  E2N_E2SM_gNB_X2_indicationHeader_t * get_header(void);
+  E2N_E2SM_gNB_X2_indicationMessage_t * get_message(void);
+
+  bool set_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *, e2sm_header_helper &);
+  bool get_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *, e2sm_header_helper &);
+    
+  bool set_message_fields(E2N_E2SM_gNB_X2_indicationMessage_t *, e2sm_message_helper &);
+  bool get_message_fields(E2N_E2SM_gNB_X2_indicationMessage_t *, e2sm_message_helper &);
+
+  bool encode_indication_header(unsigned char * , size_t * , e2sm_header_helper &); 
+  bool encode_indication_message(unsigned char *, size_t *, e2sm_message_helper &);
+  std::string  get_error (void) const {return error_string ; };
+    
+private:
+  
+  E2N_E2SM_gNB_X2_indicationHeader_t *header; // used for encoding
+  E2N_E2SM_gNB_X2_indicationMessage_t *message; // used for encoding
+    
+  char errbuf[128];
+  size_t errbuf_len;
+  E2N_GlobalGNB_ID_t gNodeB_ID;
+  std::string error_string;
+
+  
+};
+
+/* builder class for E2SM control  using ASN1c */
+  
+class e2sm_control {
+public:
+    
+  e2sm_control(void);
+  ~e2sm_control(void);
+    
+  E2N_E2SM_gNB_X2_controlHeader_t * get_header(void);
+  E2N_E2SM_gNB_X2_controlMessage_t * get_message(void);
+
+  bool set_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *, e2sm_header_helper &);
+  bool get_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *, e2sm_header_helper &);
+    
+  bool set_message_fields(E2N_E2SM_gNB_X2_controlMessage_t *, e2sm_message_helper &);
+  bool get_message_fields(E2N_E2SM_gNB_X2_controlMessage_t *, e2sm_message_helper &);
+
+  bool encode_control_header(unsigned char * , size_t * , e2sm_header_helper &); 
+  bool encode_control_message(unsigned char *, size_t *, e2sm_message_helper &);
+  std::string  get_error (void) const {return error_string ; };
+    
+private:
+  
+  E2N_E2SM_gNB_X2_controlHeader_t *header; // used for encoding
+  E2N_E2SM_gNB_X2_controlMessage_t *message; // used for encoding
+    
+  char errbuf[128];
+  size_t errbuf_len;
+  E2N_GlobalGNB_ID_t gNodeB_ID;
+  std::string error_string;
+
+  
+};
+
+#endif
diff --git a/src/xapp-formats/e2sm/e2sm_helpers.hpp b/src/xapp-formats/e2sm/e2sm_helpers.hpp
new file mode 100644 (file)
index 0000000..95ab8ca
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+  ==================================================================================
+
+  Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+  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, softwares
+  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.
+  ==================================================================================
+*/
+
+/* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */
+
+#ifndef E2SM_HELPER_
+#define E2SM_HELPER_
+
+#include <errno.h>
+#include <iostream>
+#include <vector>
+#include <sstream>
+
+ /* information holder for E2SM indication header */
+typedef struct e2sm_header_helper e2sm_header_helper;
+struct e2sm_header_helper {
+  int egNB_id_type;
+  
+  std::string egNB_id;
+  std::string plmn_id;
+  
+  long int interface_direction;
+  unsigned char* timestamp;
+};
+
+/* information holder for E2SM indication message */
+typedef struct e2sm_message_helper e2sm_message_helper;
+struct e2sm_message_helper {
+  unsigned char * x2ap_pdu;
+  size_t x2ap_pdu_size;
+};
+
+  
+/* information holder for E2SM Action Trigger Definition */
+struct Item
+{
+  Item(long int id, long int test, long int val_type, int value):interface_id(id), test(test), val_type(val_type), value_n(value){};
+  Item(long int id, long int test, long int val_type, std::string value):interface_id(id), test(test), val_type(val_type), value_s(value){};
+    
+  long int interface_id;
+  long int test;
+  long int  val_type;
+  long int value_n;
+  std::string value_s;
+    
+};
+  
+typedef struct e2sm_event_trigger_helper e2sm_event_trigger_helper;
+struct e2sm_event_trigger_helper {
+    
+  int egNB_id_type;
+  std::string egNB_id;
+  std::string plmn_id;
+    
+  long int interface_direction;
+  long int procedure_code;
+    
+  long int message_type;
+
+    
+  std::vector<struct Item> * get_list(void){ return &protocol_ie_list; };
+  void add_protocol_ie_item(long int id, long int test , unsigned int val_type, long int value ){
+    // into list 
+    protocol_ie_list.emplace_back(id, test, val_type, value);
+  };
+  
+  void add_protocol_ie_item(long int id, long int  test, unsigned  int val_type, std::string  value){
+    //  into list 
+    protocol_ie_list.emplace_back(id, test, val_type, value);    
+  };
+   
+  void clear(void){
+    protocol_ie_list.clear();
+  }
+
+  std::string get_string(void) const {
+    std::stringstream ss;
+    ss << "egNB_ID_type = " << egNB_id_type << std::endl;
+    ss << "PLMN Id = " << plmn_id << std::endl;
+    ss << "Procedure Code = " << procedure_code << std::endl;
+    ss << "Message Type = " << message_type << std::endl;
+
+    std::string info;
+    info = ss.str();
+    return info;
+  }
+  
+    
+    
+private:
+    
+  std::vector<struct Item> protocol_ie_list;
+    
+};
+
+  
+
+
+#endif
diff --git a/src/xapp-mgmt/format_helper.hpp b/src/xapp-mgmt/format_helper.hpp
new file mode 100644 (file)
index 0000000..8092173
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+==================================================================================
+
+        Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   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.
+==================================================================================
+*/
+/*
+ * a1_policy.hpp
+ *
+ *  Created on: Mar, 2020
+ *  Author: Shraboni Jana
+ */
+
+#ifndef SRC_XAPP_MGMT_A1MSG_A1_POLICY_HELPER_HPP_
+#define SRC_XAPP_MGMT_A1MSG_A1_POLICY_HELPER_HPP_
+
+#include <rapidjson/document.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/schema.h>
+
+using namespace rapidjson;
+
+typedef struct a1_policy_helper a1_policy_helper;
+
+struct a1_policy_helper{
+
+       std::string operation;
+       std::string policy_type_id;
+       std::string policy_instance_id;
+       std::string handler_id;
+       std::string status;
+
+};
+
+
+#endif /* SRC_XAPP_FORMATS_A1MSG_A1_POLICY_HELPER_HPP_ */
index 3b5223d..067f1bf 100644 (file)
@@ -231,50 +231,121 @@ bool XappMsgHandler::decode_subscription_delete_response_failure(unsigned char*
 
 }
 
-//For processing received messages.
-void XappMsgHandler::operator()(rmr_mbuf_t *message, bool *resend){
+bool  XappMsgHandler::a1_policy_handler(char * message, int *message_len, a1_policy_helper &helper){
 
-  if (message->len > MAX_RMR_RECV_SIZE){
-    mdclog_write(MDCLOG_ERR, "Error : %s, %d, RMR message larger than %d. Ignoring ...", __FILE__, __LINE__, MAX_RMR_RECV_SIZE);
-    return;
+  rapidjson::Document doc;
+  if (doc.Parse(message).HasParseError()){
+    mdclog_write(MDCLOG_ERR, "Error: %s, %d :: Could not decode A1 JSON message %s\n", __FILE__, __LINE__, message);
+    return false;
   }
 
-  switch(message->mtype){
-         //need to fix the health check.
-         case (RIC_HEALTH_CHECK_REQ):
-               message->mtype = RIC_HEALTH_CHECK_RESP;        // if we're here we are running and all is ok
-           message->sub_id = -1;
-               strncpy( (char*)message->payload, "HELLOWORLD OK\n", rmr_payload_size( message) );
-           *resend = true;
-         break;
-
-         case (RIC_SUB_RESP):
-               //Received Subscription Response Message
-               decode_subscription_response(message->payload,message->len);
-         break;
-
-         case (RIC_SUB_DEL_RESP):
-               decode_subscription_delete_response(message->payload,message->len);
-         break;
-
-         case (RIC_SUB_FAILURE):
-               decode_subscription_response_failure(message->payload, message->len);
-      break;
-
-         case (RIC_SUB_DEL_FAILURE):
-               decode_subscription_delete_response_failure(message->payload,message->len);
-         break;
-         //  case A1_POLICY_REQ:
-        // break;
-
-
-  default:
-       *resend = false;
-    mdclog_write(MDCLOG_ERR, "Error :: Unknown message type %d received from RMR", message->mtype);
-
+  //Extract Operation
+  rapidjson::Pointer temp1("/operation");
+    rapidjson::Value * ref1 = temp1.Get(doc);
+    if (ref1 == NULL){
+      mdclog_write(MDCLOG_ERR, "Error : %s, %d:: Could not extract policy type id from %s\n", __FILE__, __LINE__, message);
+      return false;
+    }
+
+   helper.operation = ref1->GetString();
+
+  // Extract policy id type
+  rapidjson::Pointer temp2("/policy_type_id");
+  rapidjson::Value * ref2 = temp2.Get(doc);
+  if (ref2 == NULL){
+    mdclog_write(MDCLOG_ERR, "Error : %s, %d:: Could not extract policy type id from %s\n", __FILE__, __LINE__, message);
+    return false;
   }
+  helper.policy_type_id = ref2->GetString();
+
+  // Extract policy instance id
+    rapidjson::Pointer temp("/policy_instance_id");
+    rapidjson::Value * ref = temp.Get(doc);
+    if (ref == NULL){
+      mdclog_write(MDCLOG_ERR, "Error : %s, %d:: Could not extract policy type id from %s\n", __FILE__, __LINE__, message);
+      return false;
+    }
+    helper.policy_instance_id = ref->GetString();
+
+    if (helper.policy_type_id == "1" && helper.operation == "CREATE"){
+       helper.status = "OK";
+       Document::AllocatorType& alloc = doc.GetAllocator();
+
+       Value handler_id;
+       handler_id.SetString(helper.handler_id.c_str(), helper.handler_id.length(), alloc);
+
+       Value status;
+       status.SetString(helper.status.c_str(), helper.status.length(), alloc);
+
+
+       doc.AddMember("handler_id", handler_id, alloc);
+       doc.AddMember("status",status, alloc);
+       doc.RemoveMember("operation");
+       StringBuffer buffer;
+       Writer<StringBuffer> writer(buffer);
+       doc.Accept(writer);
+       strncpy(message,buffer.GetString(), buffer.GetLength());
+       *message_len = buffer.GetLength();
+       return true;
+    }
+    return false;
+ }
+
+
+//For processing received messages.XappMsgHandler should mention if resend is required or not.
+void XappMsgHandler::operator()(rmr_mbuf_t *message, bool *resend){
+
+       if (message->len > MAX_RMR_RECV_SIZE){
+               mdclog_write(MDCLOG_ERR, "Error : %s, %d, RMR message larger than %d. Ignoring ...", __FILE__, __LINE__, MAX_RMR_RECV_SIZE);
+               return;
+       }
+       a1_policy_helper helper;
+       bool res=false;
+       switch(message->mtype){
+       //need to fix the health check.
+       case (RIC_HEALTH_CHECK_REQ):
+                               message->mtype = RIC_HEALTH_CHECK_RESP;        // if we're here we are running and all is ok
+                               message->sub_id = -1;
+                               strncpy( (char*)message->payload, "HELLOWORLD OK\n", rmr_payload_size( message) );
+                               *resend = true;
+       break;
+
+       case (RIC_SUB_RESP):
+                               //Received Subscription Response Message
+                               decode_subscription_response(message->payload,message->len);
+       break;
+
+       case (RIC_SUB_DEL_RESP):
+                               decode_subscription_delete_response(message->payload,message->len);
+       break;
+
+       case (RIC_SUB_FAILURE):
+                               decode_subscription_response_failure(message->payload, message->len);
+       break;
+
+       case (RIC_SUB_DEL_FAILURE):
+                               decode_subscription_delete_response_failure(message->payload,message->len);
+       break;
+
+       case A1_POLICY_REQ:
+
+               helper.handler_id = xapp_id;
+               res = a1_policy_handler((char*)message->payload, &message->len, helper);
+               if(res){
+                       message->mtype = A1_POLICY_RESP;        // if we're here we are running and all is ok
+                       message->sub_id = -1;
+                       *resend = true;
+               }
+               break;
+
+       default:
+               {
+                       *resend = false;
+                       mdclog_write(MDCLOG_ERR, "Error :: Unknown message type %d received from RMR", message->mtype);
+               }
+       }
 
-  return;
+       return;
 
 };
 
index ed9941f..8637440 100644 (file)
 #include <rmr/RIC_message_types.h>
 #include <mdclog/mdclog.h>
 
-
-#include <subscription_request.hpp>
-#include <subscription_response.hpp>
-#include <subscription_delete_request.hpp>
-#include <subscription_delete_response.hpp>
-#include "subscription_request.hpp"
+#include "e2ap_control.hpp"
+#include "e2ap_control_response.hpp"
+#include "e2ap_indication.hpp"
+#include "subscription_delete_request.hpp"
+#include "subscription_delete_response.hpp"
 #include "subscription_helper.hpp"
+#include "subscription_request.hpp"
+#include "subscription_request.hpp"
+#include "subscription_response.hpp"
 #include "e2sm.hpp"
-#include <e2ap_indication.hpp>
-#include <e2ap_control.hpp>
-#include <e2ap_control_response.hpp>
+#include "format_helper.hpp"
 
 #define MAX_RMR_RECV_SIZE 2<<15
 
 class XappMsgHandler{
 
 private:
-       unsigned char* message_buffer;
-       size_t* message_length;
-
+       std::string xapp_id;
 public:
+       //constructor for xapp_id.
+        XappMsgHandler(std::string xid){xapp_id=xid;};
         void operator() (rmr_mbuf_t *, bool*);
 
         bool encode_subscription_request(unsigned char*, size_t* );
@@ -61,6 +61,7 @@ public:
         bool decode_subscription_response_failure(unsigned char*, size_t );
         bool decode_subscription_delete_response_failure(unsigned char*, size_t );
 
+        bool a1_policy_handler(char *, int* , a1_policy_helper &);
 
 };
 
index af53220..49997b6 100644 (file)
@@ -40,7 +40,6 @@ void SubscriptionHandler::clear(void){
   {
     std::lock_guard<std::mutex> lock(*(_data_lock).get());
     requests_table.clear();
-    subscription_responses.clear();
   }
   
 };
@@ -49,11 +48,6 @@ size_t SubscriptionHandler::num_pending(void) const {
   return requests_table.size();
 }
 
-size_t SubscriptionHandler::num_complete(void) const {
-  return subscription_responses.size();
-}
-
-
 void SubscriptionHandler::set_timeout(unsigned int timeout_seconds){
   _time_out = std::chrono::seconds(timeout_seconds);
 }
@@ -102,44 +96,11 @@ bool SubscriptionHandler::delete_request_entry(subscription_identifier id){
   return false;
 };
   
-bool SubscriptionHandler::add_subscription_entry(subscription_identifier id, subscription_response_helper &he){
-
-  auto search = subscription_responses.find(id);
-  if (search == subscription_responses.end()){
-    subscription_responses[id] = he;
-    return true;
-  }
-
-  return false;
-}
-
-
-bool SubscriptionHandler::delete_subscription_entry(subscription_identifier id){
-
-  auto search = subscription_responses.find(id);
-  if(search == subscription_responses.end()){
-    return false;
-  }
-  else{
-    subscription_responses.erase(search);
-    return true;
-  }
-  
-}
 
-subscription_response_helper *  const SubscriptionHandler::get_subscription(subscription_identifier id){
-  auto search = subscription_responses.find(id);
-  if(search == subscription_responses.end()){
-    return NULL;
-  }
-  else{
-    return &(subscription_responses[id]);
-  }
-};
 
 
 // Handles responses from RMR
-void SubscriptionHandler::Response(int message_type, unsigned char *payload, int payload_length, const char * node_id){
+/*void SubscriptionHandler::Response(int message_type, unsigned char *transaction_id, const char * node_id){
 
   bool res;
   std::string node(node_id);
@@ -323,7 +284,7 @@ void SubscriptionHandler::Response(int message_type, unsigned char *payload, int
   }
   
 }
-
+*/
 
 int const SubscriptionHandler::get_request_status(subscription_identifier id){
   auto search = requests_table.find(id);
@@ -334,13 +295,7 @@ int const SubscriptionHandler::get_request_status(subscription_identifier id){
   return search->second;
 }
                                   
- bool SubscriptionHandler::is_subscription_entry(subscription_identifier id){
-  auto search = subscription_responses.find(id);
-  if (search != subscription_responses.end())
-    return true;
-  else
-    return false;
-}
+
 
 bool SubscriptionHandler::is_request_entry(subscription_identifier id){
   auto search = requests_table.find(id);
@@ -351,8 +306,3 @@ bool SubscriptionHandler::is_request_entry(subscription_identifier id){
 }
 
 
-void SubscriptionHandler::get_subscription_keys(std::vector<subscription_identifier> & key_list){
-  for(auto & e: subscription_responses){
-    key_list.push_back(e.first);
-  }
-}
index 77458d3..3a40fe1 100644 (file)
 #include <chrono>
 #include <tuple>
 
-#include "subscription_delete_request.hpp"
-#include "subscription_delete_response.hpp"
-#include "subscription_request.hpp"
-#include "subscription_response.hpp"
+#include "../xapp-formats/e2ap/subscription_delete_request.hpp"
+#include "../xapp-formats/e2ap/subscription_delete_response.hpp"
+#include "../xapp-formats/e2ap/subscription_request.hpp"
+#include "../xapp-formats/e2ap/subscription_response.hpp"
 
 #define SUBSCR_SUCCESS 0
 #define SUBSCR_ERR_TX 1
@@ -60,13 +60,7 @@ typedef enum {
     request_duplicate
 }Subscription_Status_Types;
 
-using subscription_identifier = std::tuple<std::string , int>;
-
-struct subscription_hasher {
-  size_t operator()(const subscription_identifier & key) const {
-    return  std::hash<std::string>{}(std::get<0>(key) + std::to_string(std::get<1>(key)));
-  }
-};
+using subscription_identifier = std::string; //here subscription_identifier is the rmr transaction id.
 
 class SubscriptionHandler {
                            
@@ -77,10 +71,10 @@ public:
   void init(void);
 
   template <typename Transmitter>
-  int request_subscription(std::string, int ,   Transmitter &&);
+  int request_subscription(std::string, Transmitter &&);
 
   template<typename Transmitter>
-  int request_subscription_delete(subscription_helper  &, subscription_response_helper &, std::string,  int ,  Transmitter &&);
+  int request_subscription_delete(std::string,  int ,  Transmitter &&);
 
   void  Response(int, unsigned char *, int, const char *);
   int const get_request_status(subscription_identifier);
@@ -109,9 +103,8 @@ private:
   bool get_subscription_entry(subscription_identifier);
   bool add_subscription_entry(subscription_identifier, subscription_response_helper &he);
   bool delete_subscription_entry(subscription_identifier);
-  
-  std::unordered_map<subscription_identifier, int, subscription_hasher> requests_table;
-  std::unordered_map<subscription_identifier, subscription_response_helper, subscription_hasher> subscription_responses; // stores list of successful subscriptions
+
+  std::unordered_map<subscription_identifier, int> requests_table;
   
   std::unique_ptr<std::mutex> _data_lock;
   std::unique_ptr<std::condition_variable> _cv;
@@ -123,19 +116,15 @@ private:
 };
 
 template <typename Transmitter>
-int SubscriptionHandler::request_subscription(std::string node_id, int msgcode, Transmitter && tx){
-
-  // generate subscription identifier
-  subscription_identifier sub_id = std::make_tuple (node_id, 0); //0 is the function id which is hardcoded, which should come from rnib
-
-
+int SubscriptionHandler::request_subscription(std::string rmr_trans_id, Transmitter && tx){
   bool res;
+
   // put entry in request table
   {
     std::lock_guard<std::mutex> lock(*(_data_lock.get()));
-    res = add_request_entry(sub_id, request_pending);
+    res = add_request_entry(rmr_trans_id, request_pending);
     if(! res){
-      mdclog_write(MDCLOG_ERR, "%s, %d : Error adding new subscription request %s, %d to queue because request with identical key already present",  __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
+      mdclog_write(MDCLOG_ERR, "%s, %d : Error adding new subscription request %s to queue because request with identical key already present",  __FILE__, __LINE__, rmr_trans_id);
       return SUBSCR_ERR_DUPLICATE;
     }
   }
@@ -143,14 +132,13 @@ int SubscriptionHandler::request_subscription(std::string node_id, int msgcode,
   // acquire lock ...
   std::unique_lock<std::mutex> _local_lock(*(_data_lock.get()));
 
-
   // Send the message
   res = tx();
 
   if (!res){
     // clear state
-    delete_request_entry(sub_id);
-    mdclog_write(MDCLOG_ERR, "%s, %d :: Error transmitting subscription request %s, %d", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id) );
+    delete_request_entry(rmr_trans_id);
+    mdclog_write(MDCLOG_ERR, "%s, %d :: Error transmitting subscription request %s", __FILE__, __LINE__, rmr_trans_id );
     return SUBSCR_ERR_TX;
   };
 
@@ -166,12 +154,12 @@ int SubscriptionHandler::request_subscription(std::string node_id, int msgcode,
     // we have woken and acquired data_lock
     // check status and return appropriate object
 
-    int status = get_request_status(sub_id);
+    int status = get_request_status(rmr_trans_id);
 
     if (status == request_success){
       // retreive  & store the subscription response (why?)
       // response = subscription_responses[sub_id];
-      mdclog_write(MDCLOG_INFO, "Successfully subscribed for request %s, %d", std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
+      mdclog_write(MDCLOG_INFO, "Successfully subscribed for request %s, %d", rmr_trans_id);
       res = SUBSCR_SUCCESS;
       break;
     }
@@ -182,24 +170,24 @@ int SubscriptionHandler::request_subscription(std::string node_id, int msgcode,
       std::chrono::duration<double> f = end - start;
 
       if ( f > _num_retries * _time_out){
-       mdclog_write(MDCLOG_ERR, "%s, %d:: Subscription request %s, %d timed out waiting for response ", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
+       mdclog_write(MDCLOG_ERR, "%s, %d:: Subscription request with transaction id %s timed out waiting for response ", __FILE__, __LINE__, rmr_trans_id);
        res = SUBSCR_ERR_TIMEOUT;
        break;
       }
       else{
-       mdclog_write(MDCLOG_INFO, "Subscription request %s, %d Waiting for response ....", std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
+       mdclog_write(MDCLOG_INFO, "Subscription request with transaction id %s Waiting for response ....", rmr_trans_id);
        continue;
       }
     }
 
     if(status == request_failed){
-      mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request %s, %d  got failure response .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
+      mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request with transaction id %s  got failure response .. \n", __FILE__, __LINE__, rmr_trans_id);
       res = SUBSCR_ERR_FAIL;
       break;
     }
 
     if (status == request_duplicate){
-      mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request %s, %d is duplicate : subscription already present in table .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
+      mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request with transaction id %s is duplicate : subscription already present in table .. \n", __FILE__, __LINE__, rmr_trans_id);
       res = SUBSCR_ERR_DUPLICATE;
       break;
 
@@ -207,128 +195,17 @@ int SubscriptionHandler::request_subscription(std::string node_id, int msgcode,
 
     // if we are here, some spurious
     // status obtained or request failed . we return appropriate error code
-    mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Spurious time out caused by invalid state of request %s, %d -- state = %d. Deleting request entry and failing .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id), status);
+    mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Spurious time out caused by invalid state of request %s, %d -- state = %d. Deleting request entry and failing .. \n", __FILE__, __LINE__, rmr_trans_id, status);
     res = SUBSCR_ERR_UNKNOWN;
     break;
   };
 
-  delete_request_entry(sub_id);
+  delete_request_entry(rmr_trans_id);
 
   // release data lock
   _local_lock.unlock();
-  std::cout <<"Returning  res = " << res << " for request = " << std::get<0>(sub_id).c_str() << "," <<  std::get<1>(sub_id) << std::endl;
+  std::cout <<"Returning  res = " << res << " for request = " << rmr_trans_id  << std::endl;
   return res;
 };
 
-
-/*template <typename Transmitter>
-int  SubscriptionHandler::request_subscription_delete(subscription_helper &he, subscription_response_helper &response, std::string node_id,  int TxCode, Transmitter && tx){
-
-  int res;
-  // generate subscription identifier
-  subscription_identifier sub_id = std::make_tuple (node_id, he.get_function_id());
-
-  // First check if we have this subscription
-  if(! is_subscription_entry(sub_id)){
-    mdclog_write(MDCLOG_ERR, "subscription with id %s, %d  does not exist. Cannot be deleted",std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-    return SUBSCR_ERR_MISSING;
-  }
-
-  // Also check if such a request is queued
-  if (is_request_entry(sub_id)){
-    mdclog_write(MDCLOG_ERR, "Subscription delete request  with id %s, %d  already in queue",std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-    return SUBSCR_ERR_DUPLICATE;
-  }
-
-  subscription_delete e2ap_sub_req_del;
-
-  // generate the delete request pdu
-  unsigned char buffer[128];
-  size_t buf_len = 128;
-
-  res = e2ap_sub_req_del.encode_e2ap_subscription(&buffer[0], &buf_len, he);
-  if(! res){
-    mdclog_write(MDCLOG_ERR, "%s, %d: Error encoding subscription delete request pdu. Reason = %s", __FILE__, __LINE__, e2ap_sub_req_del.get_error().c_str());
-    return SUBSCR_ERR_ENCODE;
-  }
-
-  // put entry in request table
-  {
-    std::lock_guard<std::mutex> lock(*(_data_lock.get()));
-    res = add_request_entry(sub_id, delete_request_pending);
-    if(!res){
-      mdclog_write(MDCLOG_ERR, "%s, %d: Duplicate  subscription delete request = %s, %d", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id) );
-      return SUBSCR_ERR_DUPLICATE;
-    }
-  }
-
-  std::unique_lock<std::mutex> _local_lock(*(_data_lock.get()));
-
-  // Send the message
-  res = tx(TxCode,  buf_len, buffer);
-
-  if (!res){
-    delete_request_entry(sub_id);
-    mdclog_write(MDCLOG_ERR, "Error transmitting delete subscription request %s, %d", std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-    return SUBSCR_ERR_TX;
-  };
-
-
-  // record time stamp ..
-  auto start = std::chrono::system_clock::now();
-
-  res = SUBSCR_ERR_UNKNOWN;
-  while(1){
-
-    // wait to be woken up
-    _cv.get()->wait_for(_local_lock, _time_out);
-
-    // check status and return appropriate object
-    int status = get_request_status(sub_id);
-    if (status == delete_request_success){
-      mdclog_write(MDCLOG_INFO, "Successfully deleted subscription id %s, %d", std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-      res = SUBSCR_SUCCESS;
-      break;
-    }
-
-    if (status == delete_request_pending){
-      // woken up spuriously or timed out
-      auto end = std::chrono::system_clock::now();
-      std::chrono::duration<double> f = end - start;
-
-      if (f > _num_retries * _time_out){
-       mdclog_write(MDCLOG_ERR, "Subscription delete request %s, %d timed out waiting for response ", std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-       res = SUBSCR_ERR_TIMEOUT;
-       break;
-      }
-      else{
-       mdclog_write(MDCLOG_INFO, "Subscription delete request %s, %d Waiting for response ....", std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-      }
-
-      continue;
-    }
-
-    if(status == delete_request_failed){
-      mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Delete Request %s, %d  got failure response .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id));
-      res = SUBSCR_ERR_FAIL;
-      break;
-    }
-
-    // if we are here, some spurious
-    // status obtained. we return false
-
-    mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Spurious time out caused by invalid state of  delete request %s, %d -- state = %d. Deleting request entry and failing .. \n", __FILE__, __LINE__,std::get<0>(sub_id).c_str(), std::get<1>(sub_id), status);
-    res =  SUBSCR_ERR_UNKNOWN;
-    break;
-
-  };
-
-  delete_request_entry(sub_id);
-
-  // release data lock
-  _local_lock.unlock();
-  std::cout <<"Returning  res = " << res << " for " << std::get<0>(sub_id) << "," << std::get<1>(sub_id) << std::endl;
-  return res;
-};*/
-
 #endif
index c822e55..d03de88 100755 (executable)
@@ -33,7 +33,6 @@ XappRmr::XappRmr(std::string port, int rmrattempts){
 };
 
 XappRmr::~XappRmr(void){
-
        // free memory
        if(_xapp_received_buff)
                rmr_free_msg(_xapp_received_buff);
@@ -44,6 +43,7 @@ XappRmr::~XappRmr(void){
        if (_xapp_rmr_ctx){
                rmr_close(_xapp_rmr_ctx);
        }
+
 };
 
 //Get RMR Context.
@@ -65,25 +65,20 @@ void XappRmr::xapp_rmr_init(){
        return;
 
 }
-//RMR Returning to the sender.
-bool XappRmr::xapp_rmr_rts()
-{
-       mdclog_write(MDCLOG_INFO,"RMR Return to sender, file= %s, line=%d",__FILE__,__LINE__);
-       if ( _xapp_rmr_ctx == NULL){
-                       mdclog_write(MDCLOG_ERR,"Error Initializing RMR, file= %s, line=%d",__FILE__,__LINE__);
-       }
-       while( ! rmr_ready(_xapp_rmr_ctx) ) {
-                       mdclog_write(MDCLOG_INFO,">>> waiting for RMR, file= %s, line=%d",__FILE__,__LINE__);
-                       sleep(1);
-       }
-       rmr_rts_msg(_xapp_rmr_ctx, _xapp_received_buff );
-       sleep(1);
-       return true;
-}
+
 
 //RMR Send with payload and header.
 bool XappRmr::xapp_rmr_send(xapp_rmr_header *hdr, void *payload){
 
+       // Get the thread id
+       std::thread::id my_id = std::this_thread::get_id();
+       std::stringstream thread_id;
+       std::stringstream ss;
+
+       thread_id << my_id;
+       mdclog_write(MDCLOG_INFO, "Sending thread %s",  thread_id.str().c_str());
+
+
        int rmr_attempts = _nattempts;
 
        if( _xapp_send_buff == NULL ) {
@@ -114,7 +109,9 @@ bool XappRmr::xapp_rmr_send(xapp_rmr_header *hdr, void *payload){
                else
                {
                        mdclog_write(MDCLOG_INFO,"Need to retry RMR: state=%d, attempt=%d, file=%s, line=%d",_xapp_send_buff->state, rmr_attempts,__FILE__,__LINE__);
-                       rmr_attempts--;
+                       if(_xapp_send_buff->state == RMR_ERR_RETRY){
+                               usleep(1);                      }
+                               rmr_attempts--;
                }
                sleep(1);
        }
index 30aea8c..ab3e77a 100755 (executable)
@@ -77,7 +77,6 @@ public:
        template <class MessageProcessor>
        void xapp_rmr_receive(MessageProcessor&&, XappRmr *parent);
        bool xapp_rmr_send(xapp_rmr_header*, void*);
-       bool xapp_rmr_rts();
 
        void set_listen(bool);
        bool get_listen(void);
@@ -112,7 +111,7 @@ void XappRmr::xapp_rmr_receive(MsgHandler&& msgproc, XappRmr *parent){
        this->_xapp_received_buff = rmr_alloc_msg(rmr_context, RMR_DEF_SIZE);
        assert(this->_xapp_received_buff != NULL);
 
-       mdclog_write(MDCLOG_INFO, "Starting thread %s",  thread_id.str().c_str());
+       mdclog_write(MDCLOG_INFO, "Starting receiver thread %s",  thread_id.str().c_str());
 
        while(parent->get_listen()) {
                mdclog_write(MDCLOG_INFO, "Listening at Thread: %s",  thread_id.str().c_str());
@@ -132,6 +131,8 @@ void XappRmr::xapp_rmr_receive(MsgHandler&& msgproc, XappRmr *parent){
                        //in case message handler returns true, need to resend the message.
                        msgproc(this->_xapp_received_buff, resend);
                        if(*resend){
+                               //mdclog_write(MDCLOG_INFO,"RMR Return to Sender Message of Type: %d",this->_xapp_received_buff->mtype);
+                               //mdclog_write(MDCLOG_INFO,"RMR Return to Sender Message: %s",(char*)this->_xapp_received_buff->payload);
                                rmr_rts_msg(rmr_context, this->_xapp_received_buff );
                                sleep(1);
                                *resend = false;
index 4101699..54b75fd 100644 (file)
@@ -20,7 +20,6 @@
  * xapp.cc
  *
  *  Created on: Mar, 2020
- *  Author: Shraboni Jana
  */
 
 #include "xapp.hpp"
@@ -36,15 +35,27 @@ Xapp::~Xapp(void){
 
        //Joining the threads
        int threadcnt = xapp_rcv_thread.size();
-       for(int i=0; i<threadcnt; i++){
-               if(xapp_rcv_thread[i].joinable())
-                       xapp_rcv_thread[i].join();
+               for(int i=0; i<threadcnt; i++){
+                       if(xapp_rcv_thread[i].joinable())
+                               xapp_rcv_thread[i].join();
        }
+       xapp_rcv_thread.clear();
 
-       delete xapp_mutex;
-
+       if(xapp_mutex!=NULL){
+               xapp_mutex->~mutex();
+               delete xapp_mutex;
+       }
 };
 
+//stop the xapp.
+void Xapp::stop(void){
+  // Get the mutex lock
+       std::lock_guard<std::mutex> guard(*xapp_mutex);
+       rmr_ref->set_listen(false);
+       rmr_ref->~XappRmr();
+
+}
+
 void Xapp::init() {
 
        //get rnib information
@@ -61,7 +72,7 @@ void Xapp::startup() {
 
 void Xapp::start_xapp_receiver(XappMsgHandler& mp_handler){
        //start a receiver thread. Can be multiple receiver threads for more than 1 listening port.
-
+       rmr_ref->set_listen(true);
        xapp_mutex = new std::mutex();
 
        mdclog_write(MDCLOG_INFO,"Receiver Thread file= %s, line=%d",__FILE__,__LINE__);
@@ -88,13 +99,13 @@ void Xapp::shutdown(){
 void Xapp::startup_subscribe_requests(void ){
    size_t data_size = ASN_BUFF_MAX_SIZE;
    unsigned char       data[data_size];
-
+   std::string xapp_id = config_ref->operator [](XappSettings::SettingName::XAPP_ID);
    for(auto &it: rnib_gnblist){
      int attempt = 0;
-        XappMsgHandler msg;
+        XappMsgHandler msg = XappMsgHandler(xapp_id);
 
/*     bool res_encode = msg.encode_subscription_request(data, &data_size);
-        if(!res_encode) exit(0);*/
       //bool res_encode = msg.encode_subscription_request(data, &data_size);
+        //if(!res_encode) exit(0);
        char *strMsg = "HelloWorld\0";
        strncpy((char *)data,strMsg,strlen(strMsg));
        data_size = sizeof(data);
@@ -106,6 +117,8 @@ void Xapp::startup_subscribe_requests(void ){
 
                 auto transmitter = std::bind(&XappRmr::xapp_rmr_send,rmr_ref, &rmr_header, (void*)data);
                 transmitter(); //this will go to subscription manager.
+                //rmr_ref->xapp_rmr_call(&rmr_header,(char*)strMsg);
+
                 break;
      }
    }
@@ -141,8 +154,11 @@ void Xapp::set_rnib_gnblist(void) {
            Document doc;
            doc.Parse((char*)result);
            assert(doc.HasMember("gnb_list"));
+
+
            const Value& gnblist = doc["gnb_list"];
            assert(gnblist.IsArray());
+
            for (SizeType i = 0; i < gnblist.Size(); i++) // Uses SizeType instead of size_t
            {
                assert(gnblist[i].IsObject());
@@ -153,7 +169,8 @@ void Xapp::set_rnib_gnblist(void) {
 
            }
            closeSdl();
-           free(result);
+
+           //delete result;
            return;
 
 }
index 680db1b..7f44c57 100644 (file)
@@ -42,7 +42,7 @@
 #include "subs_mgmt.hpp"
 #include "xapp_config.hpp"
 extern "C" {
-#include "rnib/rnibreader.h"
+#include "rnib/rnibreader_old.h"
 }
 using namespace std;
 using namespace std::placeholders;
@@ -55,7 +55,7 @@ public:
 
   Xapp(XappSettings &, XappRmr &);
   ~Xapp(void);
-
+  void stop(void);
   void startup();
   void shutdown(void);
   void init(void);