Adding Bouncer code for RIC-Benchmarking
[ric-app/bouncer.git] / Bouncer / src / xapp-formats / e2ap / subscription_request.cc
1
2
3 /*
4 ==================================================================================
5         Copyright (c) 2018-2019 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21
22 #include "subscription_request.hpp"
23
24
25 // Set up memory allocations for each IE for encoding
26 // We are responsible for memory management for each IE for encoding
27 // Hence destructor should clear out memory
28 // When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called
29 // for releasing memory by external calling function)
30 subscription_request::subscription_request(void){
31
32   _name = "default";
33
34   e2ap_pdu_obj = 0;
35   e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t));
36   assert(e2ap_pdu_obj != 0);
37
38   initMsg = 0;
39   initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t));
40   assert(initMsg != 0);
41
42   IE_array = 0;
43   IE_array = (E2N_RICsubscriptionRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_REQUEST_IES, sizeof(E2N_RICsubscriptionRequest_IEs_t));
44   assert(IE_array != 0);
45   
46   action_array = 0;
47   action_array = (E2N_RICaction_ToBeSetup_ItemIEs_t *)calloc(INITIAL_REQUEST_LIST_SIZE, sizeof(E2N_RICaction_ToBeSetup_ItemIEs_t));
48   assert(action_array != 0);
49   action_array_size = INITIAL_REQUEST_LIST_SIZE;
50   // also need to add subsequent action and time to wait ..
51   for (unsigned int i = 0; i < action_array_size; i++){
52     action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction = (struct E2N_RICsubsequentAction *)calloc(1, sizeof(struct E2N_RICsubsequentAction));
53     assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction  != 0);
54   }
55   
56   e2ap_pdu_obj->choice.initiatingMessage = initMsg;
57   e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage;
58
59
60   
61 };
62
63
64
65 // Clear assigned protocolIE list from RIC indication IE container
66 subscription_request::~subscription_request(void){
67     
68   mdclog_write(MDCLOG_DEBUG, "Freeing subscription request memory for");;
69   
70   // Sequence of actions to be admitted causes special heart-ache. Free ric subscription element manually and reset the ie pointer  
71   E2N_RICsubscription_t * ricsubscription_ie = &(IE_array[2].value.choice.RICsubscription);
72
73   for(int i = 0; i < ricsubscription_ie->ricAction_ToBeSetup_List.list.size; i++){
74     ricsubscription_ie->ricAction_ToBeSetup_List.list.array[i] = 0;
75   }
76
77   if (ricsubscription_ie->ricAction_ToBeSetup_List.list.size > 0){
78     free(ricsubscription_ie->ricAction_ToBeSetup_List.list.array);
79     ricsubscription_ie->ricAction_ToBeSetup_List.list.size = 0;
80     ricsubscription_ie->ricAction_ToBeSetup_List.list.count = 0;
81     ricsubscription_ie->ricAction_ToBeSetup_List.list.array = 0;
82   }
83
84   // clear subsequent action array
85   for (unsigned int i = 0; i < action_array_size; i++){
86     free(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction );
87   }
88   
89   free(action_array);
90   E2N_RICsubscriptionRequest_t * subscription_request = &(initMsg->value.choice.RICsubscriptionRequest);
91   
92   for(int i = 0; i < subscription_request->protocolIEs.list.size; i++){
93     subscription_request->protocolIEs.list.array[i] = 0;
94   }
95   
96   if( subscription_request->protocolIEs.list.size > 0){
97     free( subscription_request->protocolIEs.list.array);
98     subscription_request->protocolIEs.list.array = 0;
99     subscription_request->protocolIEs.list.size = 0;
100     subscription_request->protocolIEs.list.count = 0;
101   }
102   
103   free(IE_array);
104   free(initMsg);
105   e2ap_pdu_obj->choice.initiatingMessage = 0;
106   
107   ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
108   mdclog_write(MDCLOG_DEBUG, "Freed subscription request memory ");
109 };
110
111
112 bool subscription_request::encode_e2ap_subscription(unsigned char *buf, size_t *size,  subscription_helper &dinput){
113
114   bool res;
115
116   initMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription;
117   initMsg->criticality = E2N_Criticality_ignore;
118   initMsg->value.present = E2N_InitiatingMessage__value_PR_RICsubscriptionRequest;
119
120   res = set_fields(initMsg, dinput);
121   if (!res){
122     return false;
123   }
124   
125   int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len);
126   if(ret_constr){
127     error_string.assign(errbuf, errbuf_len);
128     error_string = "Constraints failed for encoding subscription request. Reason = " + error_string;
129     return false;
130   }
131
132   //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj);
133   
134   asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size);
135     
136   if(retval.encoded == -1){
137     error_string.assign(strerror(errno));
138     error_string = "Error encoding Subscription  Request. Reason = " + error_string;
139     return false;
140   }
141   else {
142     if(*size < retval.encoded){
143       std::stringstream ss;
144       ss  <<"Error encoding Subscription  Request . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
145       error_string = ss.str();
146       retval.encoded = -1;
147       return false;
148     }
149   }
150     
151   *size = retval.encoded;
152   return true;
153     
154 }
155
156
157 bool subscription_request::set_fields( E2N_InitiatingMessage_t * init_msg, subscription_helper &helper){
158
159   
160   int ie_index;
161   int result = 0;
162
163   if (init_msg == 0){
164     error_string = "Error. Invalid reference when getting fields from subscription request";
165     return false;
166   }
167
168   E2N_RICsubscriptionRequest_t * ric_subscription = &(init_msg->value.choice.RICsubscriptionRequest);
169   ric_subscription->protocolIEs.list.count = 0;
170   
171   ie_index = 0;
172   E2N_RICsubscriptionRequest_IEs_t *ies_ricreq = &IE_array[ie_index];
173   ies_ricreq->criticality = E2N_Criticality_reject;
174   ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID;
175   ies_ricreq->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RICrequestID;
176   E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID;
177   ricrequest_ie->ricRequestorID = helper.get_request_id();
178   ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq();
179   result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]);
180   assert(result == 0);
181      
182   ie_index = 1;
183   E2N_RICsubscriptionRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
184   ies_ranfunc->criticality = E2N_Criticality_reject;
185   ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID;
186   ies_ranfunc->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RANfunctionID;
187   E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
188   *ranfunction_ie = helper.get_function_id();
189   result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]);
190   assert(result == 0);
191
192
193   ie_index = 2;
194   E2N_RICsubscriptionRequest_IEs_t *ies_actid = &IE_array[ie_index];
195   ies_actid->criticality = E2N_Criticality_reject;
196   ies_actid->id = E2N_ProtocolIE_ID_id_RICsubscription;
197   ies_actid->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RICsubscription;
198   E2N_RICsubscription_t *ricsubscription_ie = &ies_actid->value.choice.RICsubscription;
199
200   ricsubscription_ie->ricEventTriggerDefinition.buf = (uint8_t *) helper.get_event_def();
201   ricsubscription_ie->ricEventTriggerDefinition.size = helper.get_event_def_size();
202    
203   std::vector<Action> * ref_action_array = helper.get_list();
204   // do we need to resize  ?
205   // we don't care about contents, so just do a free/calloc
206   if(action_array_size < ref_action_array->size()){
207     std::cout <<"re-allocating action array from " << action_array_size << " to " << 2 * ref_action_array->size() <<  std::endl;
208     // free subsequent allocation
209     for (unsigned int i = 0; i < action_array_size; i++){
210       free(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction );
211     }
212     
213     action_array_size = 2 * ref_action_array->size();
214     free(action_array);
215     action_array = (E2N_RICaction_ToBeSetup_ItemIEs_t *)calloc(action_array_size, sizeof(E2N_RICaction_ToBeSetup_ItemIEs_t));
216     assert(action_array != 0);
217
218     // also need to add subsequent action and time to wait ..
219     for (unsigned int i = 0; i < action_array_size; i++){
220       action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction = (struct E2N_RICsubsequentAction *)calloc(1, sizeof(struct E2N_RICsubsequentAction));
221       assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction  != 0);
222     }
223     
224   }
225   
226   // reset the list count on ricAction_ToBeSetup_List;
227   ricsubscription_ie->ricAction_ToBeSetup_List.list.count = 0;
228   
229   for(unsigned int i = 0; i < ref_action_array->size(); i ++){
230     action_array[i].criticality = E2N_Criticality_ignore;
231     action_array[i].id = E2N_ProtocolIE_ID_id_RICaction_ToBeSetup_Item ;
232     action_array[i].value.present = E2N_RICaction_ToBeSetup_ItemIEs__value_PR_RICaction_ToBeSetup_Item;
233     action_array[i].value.choice.RICaction_ToBeSetup_Item.ricActionID = (*ref_action_array)[i].get_id();
234     action_array[i].value.choice.RICaction_ToBeSetup_Item.ricActionType = (*ref_action_array)[i].get_type();
235     action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricSubsequentActionType = (*ref_action_array)[i].get_subsequent_action();
236     action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricTimeToWait = (*ref_action_array)[i].get_wait();
237     
238     result = ASN_SEQUENCE_ADD(&ricsubscription_ie->ricAction_ToBeSetup_List, &(action_array[i]));
239     if (result == -1){
240       error_string = "Erorr : Unable to assign memory to add Action item to set up list";
241       return false;
242     }
243     
244   }
245   
246   result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]);
247   assert(result == 0);
248
249
250     
251   return true;
252 };
253
254
255
256 bool subscription_request:: get_fields(E2N_InitiatingMessage_t * init_msg,  subscription_helper & dout)
257 {
258
259   if (init_msg == 0){
260     error_string = "Error. Invalid reference when getting fields from subscription request";
261     return false;
262   }
263   
264   E2N_RICrequestID_t *requestid;
265   E2N_RANfunctionID_t * ranfunctionid;
266   E2N_RICsubscription_t * ricsubscription;
267     
268   for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.count; edx++) {
269     E2N_RICsubscriptionRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.array[edx];
270     
271     switch(memb_ptr->id)
272       {
273       case (E2N_ProtocolIE_ID_id_RICrequestID):
274         requestid = &memb_ptr->value.choice.RICrequestID;
275         dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
276         break;
277           
278       case (E2N_ProtocolIE_ID_id_RANfunctionID):
279         ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
280         dout.set_function_id(*ranfunctionid);
281         break;
282           
283       case (E2N_ProtocolIE_ID_id_RICsubscription):
284         ricsubscription = &memb_ptr->value.choice.RICsubscription;
285         dout.set_event_def(ricsubscription->ricEventTriggerDefinition.buf, ricsubscription->ricEventTriggerDefinition.size);
286           
287         for(int index = 0; index < ricsubscription->ricAction_ToBeSetup_List.list.count; index ++){
288           E2N_RICaction_ToBeSetup_ItemIEs_t * item = (E2N_RICaction_ToBeSetup_ItemIEs_t *)ricsubscription->ricAction_ToBeSetup_List.list.array[index];
289           if (item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction == NULL){
290             dout.add_action(item->value.choice.RICaction_ToBeSetup_Item.ricActionID, item->value.choice.RICaction_ToBeSetup_Item.ricActionType);
291           }
292           else{
293             std::string action_def = ""; // for now we are ignoring action definition
294             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);
295           }   
296         };
297         
298         break;
299       }
300       
301   }
302     
303   //asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu);
304   return true;
305 };
306
307
308