069ac1c3399581ec50957d2169884064b61ea8f9
[ric-app/admin.git] / src / E2SM / e2sm.cc
1 /*
2   ==================================================================================
3
4   Copyright (c) 2018-2019 AT&T Intellectual Property.
5   
6   Licensed under the Apache License, Version 2.0 (the "License");
7   you may not use this file except in compliance with the License.
8   You may obtain a copy of the License at
9   
10   http://www.apache.org/licenses/LICENSE-2.0
11   
12   Unless required by applicable law or agreed to in writing, softwares
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   See the License for the specific language governing permissions and
16   limitations under the License.
17   ==================================================================================
18 */
19
20 /* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */
21
22 #include "e2sm.hpp"
23
24
25
26   //initialize
27   e2sm_event_trigger::e2sm_event_trigger(void){
28
29     memset(&gNodeB_ID, 0, sizeof(GlobalGNB_ID_t));
30
31     event_trigger = 0;
32     event_trigger = ( E2SM_gNB_X2_eventTriggerDefinition_t *)calloc(1, sizeof( E2SM_gNB_X2_eventTriggerDefinition_t));
33     assert(event_trigger != 0);
34     
35     // allocate space for gNodeB id  (used for encoding)
36     gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0;
37     gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
38     assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
39     
40     // allocate space for plmn identity  (used for encoding)
41     gNodeB_ID.pLMN_Identity.buf = 0;
42     gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
43     assert(gNodeB_ID.pLMN_Identity.buf != 0);
44
45     ie_list = 0;
46     ie_list = ( struct InterfaceProtocolIE_Item *) calloc(INITIAL_LIST_SIZE, sizeof( struct InterfaceProtocolIE_Item));
47     assert(ie_list != 0);
48     ie_list_size = INITIAL_LIST_SIZE;
49
50     condition_list = 0;
51     condition_list = (E2SM_gNB_X2_eventTriggerDefinition::E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List *) calloc(1, sizeof(E2SM_gNB_X2_eventTriggerDefinition::E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List ));
52     assert(condition_list != 0);
53
54  
55     
56   };
57   
58 e2sm_event_trigger::~e2sm_event_trigger(void){
59
60   mdclog_write(MDCLOG_INFO, "Freeing event trigger object memory");
61   for(int i = 0; i < condition_list->list.size; i++){
62     condition_list->list.array[i] = 0;
63   }
64
65   if (condition_list->list.size > 0){
66     free(condition_list->list.array);
67     condition_list->list.array = 0;
68     condition_list->list.size = 0;
69     condition_list->list.count = 0;
70   }
71
72   free(condition_list);
73   condition_list = 0;
74   
75   free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
76   gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0;
77   
78   free(gNodeB_ID.pLMN_Identity.buf);
79   gNodeB_ID.pLMN_Identity.buf = 0;
80   
81   free(ie_list);
82   ie_list = 0;
83   
84   event_trigger->interface_ID.choice.global_gNB_ID = 0;
85   event_trigger->interfaceProtocolIE_List = 0;
86   
87   ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger);
88   mdclog_write(MDCLOG_INFO, "Freed event trigger object memory");
89
90  
91 };
92
93 bool e2sm_event_trigger::encode_event_trigger(unsigned char *buf, size_t *size, e2sm_event_trigger_helper &helper){
94   
95   bool res;
96   res = set_fields(event_trigger, helper);
97   if (!res){
98     return false;
99   }
100   
101   int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, errbuf, &errbuf_len);
102   if(ret_constr){
103     error_string.assign(&errbuf[0], errbuf_len);
104     return false;
105   }
106
107   //xer_fprint(stdout, &asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger);
108   
109   asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, buf, *size);
110   
111   if(retval.encoded == -1){
112     error_string.assign(strerror(errno));
113     return false;
114   }
115   else if (retval.encoded > *size){
116     std::stringstream ss;
117     ss  <<"Error encoding event trigger definition. Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
118     error_string = ss.str();
119     return false;
120   }
121   else{
122     *size = retval.encoded;
123   }
124   
125   return true;
126 }
127
128
129 bool e2sm_event_trigger::set_fields(E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){
130   if(ref_event_trigger == 0){
131     error_string = "Invalid reference for Event Trigger Definition set fields";
132     return false;
133   }
134       
135   // set the message type
136   ref_event_trigger->interfaceMessageType.procedureCode = helper.procedure_code;
137   ref_event_trigger->interfaceMessageType.typeOfMessage = helper.message_type;
138   
139   ref_event_trigger->interfaceDirection = helper.interface_direction; 
140   ref_event_trigger->interface_ID.present = Interface_ID_PR_global_gNB_ID;
141   
142   ref_event_trigger->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
143
144   // to do : need to put correct code here for upding plmn id and gNodeB
145   // for now just place holders :
146   //================================================================
147   memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
148   gNodeB_ID.pLMN_Identity.size = 3;
149   
150   memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
151   gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
152   
153   // we only do global gNodeB id for now, not eNodeB
154   gNodeB_ID.gNB_ID.present = GNB_ID_PR_gNB_ID;
155   //================================================================
156   
157   
158   // Add in any requested IE items
159   std::vector<Item> * ref_ie_array = helper.get_list();
160
161   if (ref_ie_array->size() == 0){
162     event_trigger->interfaceProtocolIE_List = 0;
163     
164   }
165   else{
166     event_trigger->interfaceProtocolIE_List = condition_list;
167     
168     //reallocate ? 
169     if(ref_ie_array->size() > ie_list_size){
170       struct InterfaceProtocolIE_Item *new_ref = 0;
171       ie_list_size = 2 * ref_ie_array->size();
172       new_ref = (struct InterfaceProtocolIE_Item *)realloc(ie_list, ie_list_size);
173       assert(new_ref != 0);
174       ie_list = new_ref;
175     }
176     
177     // reset the count so that adds start from the beginning
178     ref_event_trigger->interfaceProtocolIE_List->list.count = 0;
179     
180     for(unsigned int i = 0; i < ref_ie_array->size(); i++){
181
182       ie_list[i].interfaceProtocolIE_ID = (*ref_ie_array)[i].interface_id;
183       ie_list[i].interfaceProtocolIE_Test = (*ref_ie_array)[i].test;
184       
185       //switch(ie_list[i].interfaceProtocolIE_Value.present){
186       switch((*ref_ie_array)[i].val_type){
187         
188       case (InterfaceProtocolIE_Value_PR_valueInt):
189         ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueInt;
190         ie_list[i].interfaceProtocolIE_Value.choice.valueInt = (*ref_ie_array)[i].value_n;
191         break;
192         
193       case (InterfaceProtocolIE_Value_PR_valueEnum):
194         ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueEnum;
195         ie_list[i].interfaceProtocolIE_Value.choice.valueEnum = (*ref_ie_array)[i].value_n;
196         break;
197         
198       case (InterfaceProtocolIE_Value_PR_valueBool):
199         ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueBool;
200         ie_list[i].interfaceProtocolIE_Value.choice.valueBool = (*ref_ie_array)[i].value_n;
201         break;
202         
203       case (InterfaceProtocolIE_Value_PR_valueBitS):
204         ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueBitS;
205         ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.buf = (uint8_t *)(*ref_ie_array)[i].value_s.c_str();
206         ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.size = (*ref_ie_array)[i].value_s.length();
207         break;
208         
209       default:
210         {
211           std::stringstream ss;
212           ss <<"Error ! " << __FILE__ << "," << __LINE__ << " illegal enum " << (*ref_ie_array)[i].val_type << " for interface Protocol IE value" << std::endl;
213           std::string error_string = ss.str();
214           return false;
215         }
216       }
217       
218       ASN_SEQUENCE_ADD(ref_event_trigger->interfaceProtocolIE_List, &ie_list[i]);
219     }
220   }
221
222   return true;
223 };
224   
225
226 bool e2sm_event_trigger::get_fields(E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){
227
228   if (ref_event_trigger == 0){
229     error_string = "Invalid reference for Event Trigger definition get fields";
230     return false;
231   }
232   
233   helper.procedure_code = ref_event_trigger->interfaceMessageType.procedureCode;
234   helper.message_type   = ref_event_trigger->interfaceMessageType.typeOfMessage;
235   helper.interface_direction = ref_event_trigger->interfaceDirection;
236   
237   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);
238   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);
239
240   return true;
241 };
242     
243
244   
245    
246 // initialize
247 e2sm_indication::e2sm_indication(void) {
248   
249   memset(&gNodeB_ID, 0, sizeof(GlobalGNB_ID_t));
250     
251   // allocate space for gNodeB id  (used for encoding)
252   gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
253   assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
254     
255   // allocate space for plmn identity  (used for encoding)
256   gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
257   assert(gNodeB_ID.pLMN_Identity.buf != 0);
258
259   header = 0;
260   header = (E2SM_gNB_X2_indicationHeader_t *)calloc(1, sizeof(E2SM_gNB_X2_indicationHeader_t));
261   assert(header != 0);
262
263   message = 0;
264   message = (E2SM_gNB_X2_indicationMessage_t *)calloc(1, sizeof(E2SM_gNB_X2_indicationMessage_t));
265   assert(message != 0);
266 }
267   
268 e2sm_indication::~e2sm_indication(void){
269   mdclog_write(MDCLOG_INFO, "Freeing E2SM Indication  object memory");
270
271   free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
272   free(gNodeB_ID.pLMN_Identity.buf);
273   
274   header->interface_ID.choice.global_gNB_ID = 0;
275
276   ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_indicationHeader, header);
277
278   message->interfaceMessage.buf = 0;
279   message->interfaceMessage.size = 0;
280
281   ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_indicationMessage, message);
282   mdclog_write(MDCLOG_INFO, "Freed E2SM Indication  object memory");
283     
284 }
285   
286   
287
288 bool e2sm_indication::encode_indication_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){
289     
290   bool res;
291   res = set_header_fields(header, helper);
292   if (!res){
293     return false;
294   }
295
296   int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_indicationHeader, header, errbuf, &errbuf_len);
297   if(ret_constr){
298     error_string.assign(&errbuf[0], errbuf_len);
299     error_string = "E2SM Indication Header Constraint failed : " + error_string;
300
301     return false;
302   }
303
304   asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_indicationHeader, header, buf, *size);
305
306   if(retval.encoded == -1){
307     error_string.assign(strerror(errno));
308     error_string = "Error encoding E2SM Indication Header. Reason = " + error_string;
309     return false;
310   }
311   else if (retval.encoded > *size){
312     std::stringstream ss;
313     ss  <<"Error encoding E2SM Indication Header . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
314     error_string = ss.str();
315     return false;
316   }
317   else{
318     *size = retval.encoded;
319   }
320     
321   return true;
322 }
323
324
325 bool e2sm_indication::encode_indication_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){
326
327   set_message_fields(message, helper); 
328
329   int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_indicationMessage, message, errbuf, &errbuf_len);
330   if(ret_constr){
331     error_string.assign(&errbuf[0], errbuf_len);
332     error_string = "E2SM Indication Message Constraint failed : " + error_string;
333     return false;
334   }
335
336   asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_indicationMessage, message, buf, *size);
337   if(retval.encoded == -1){
338     error_string.assign(strerror(errno));
339     error_string = "Error encoding E2SM Indication Header. Reason = " + error_string;
340     return false;
341   }
342   else if (retval.encoded > *size){
343     std::stringstream ss;
344     ss  <<"Error encoding E2SM Indication Message . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
345     error_string = ss.str();
346     
347     return false;
348   }
349   else{
350     *size = retval.encoded;
351   }
352   
353   return true;
354 }
355
356
357
358 // Used when generating an indication header 
359 bool e2sm_indication::set_header_fields(E2SM_gNB_X2_indicationHeader_t *header,  e2sm_header_helper &helper){
360
361   if (header == 0){
362     error_string = "Invalid reference for E2SM Indication Header set fields";
363     return false;
364   }
365   
366   
367   header->interfaceDirection = helper.interface_direction;
368   header->interface_ID.present = Interface_ID_PR_global_gNB_ID;
369   header->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
370
371
372   // to do : need to put correct code here for upding plmn id and gNodeB
373   // for now just place holders :
374   memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
375   gNodeB_ID.pLMN_Identity.size = 3;
376   
377   memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
378   gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
379   
380   // we only do global gNodeB id for now, not eNodeB
381   gNodeB_ID.gNB_ID.present = GNB_ID_PR_gNB_ID;
382
383   return true;
384   
385 };
386
387
388 // used when decoding an indication header
389 bool e2sm_indication::get_header_fields(E2SM_gNB_X2_indicationHeader_t *header,  e2sm_header_helper &helper){
390
391   if (header == 0){
392     error_string = "Invalid reference for E2SM Indication header get fields";
393     return false;
394   }
395   
396   helper.interface_direction = header->interfaceDirection;
397   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);
398   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);
399   
400   // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing)
401
402   return true;
403 }
404
405
406
407 // Used when generating an indication message 
408 bool   e2sm_indication::set_message_fields(E2SM_gNB_X2_indicationMessage_t *interface_message,  e2sm_message_helper &helper){
409
410   if(interface_message == 0){
411     error_string = "Invalid reference for E2SM Indication Message set fields";
412     return false;
413   }
414
415   // interface-message is an octet string. just point it to the buffer
416   interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]);
417   interface_message->interfaceMessage.size = helper.x2ap_pdu_size;
418
419   return true;
420   
421 };
422
423 // used when decoding an indication message
424 bool e2sm_indication::get_message_fields( E2SM_gNB_X2_indicationMessage_t *interface_message, e2sm_message_helper &helper){
425
426   
427   if(interface_message == 0){
428     error_string = "Invalid reference for E2SM Indication Message get fields";
429     return false;
430   }
431
432   // interface message is an octet string
433   helper.x2ap_pdu = interface_message->interfaceMessage.buf;;
434   helper.x2ap_pdu_size = interface_message->interfaceMessage.size;
435
436   return true;
437   
438 }
439   
440
441    
442 // initialize
443 e2sm_control::e2sm_control(void) {
444   
445   memset(&gNodeB_ID, 0, sizeof(GlobalGNB_ID_t));
446     
447   // allocate space for gNodeB id  (used for encoding)
448   gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
449   assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
450     
451   // allocate space for plmn identity  (used for encoding)
452   gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
453   assert(gNodeB_ID.pLMN_Identity.buf != 0);
454
455   header = 0;
456   header = (E2SM_gNB_X2_controlHeader_t *)calloc(1, sizeof(E2SM_gNB_X2_controlHeader_t));
457   assert(header != 0);
458
459   message = 0;
460   message = (E2SM_gNB_X2_controlMessage_t *)calloc(1, sizeof(E2SM_gNB_X2_controlMessage_t));
461   assert(message != 0);
462 }
463   
464 e2sm_control::~e2sm_control(void){
465   mdclog_write(MDCLOG_INFO, "Freeing E2SM Control  object memory");
466
467   free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
468   free(gNodeB_ID.pLMN_Identity.buf);
469   header->interface_ID.choice.global_gNB_ID = 0;
470   ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_controlHeader, header);
471
472   message->interfaceMessage.buf = 0;
473   ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_controlMessage, message);
474
475   mdclog_write(MDCLOG_INFO, "Freed E2SM Control  object memory");
476     
477 }
478   
479   
480
481 bool e2sm_control::encode_control_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){
482     
483   bool res;
484   res = set_header_fields(header, helper);
485   if (!res){
486     return false;
487   }
488
489   int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_controlHeader, header, errbuf, &errbuf_len);
490   if(ret_constr){
491     error_string.assign(&errbuf[0], errbuf_len);
492     error_string = "E2SM Control Header Constraint failed : " + error_string;
493
494     return false;
495   }
496
497   asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_controlHeader, header, buf, *size);
498
499   if(retval.encoded == -1){
500     error_string.assign(strerror(errno));
501     error_string = "Error encoding E2SM Control Header. Reason = " + error_string;
502     return false;
503   }
504   else if (retval.encoded > *size){
505     std::stringstream ss;
506     ss  <<"Error encoding E2SM Control Header . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
507     error_string = ss.str();
508     return false;
509   }
510   else{
511     *size = retval.encoded;
512   }
513     
514   return true;
515 }
516
517
518 bool e2sm_control::encode_control_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){
519
520   set_message_fields(message, helper); 
521
522   int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_controlMessage, message, errbuf, &errbuf_len);
523   if(ret_constr){
524     error_string.assign(&errbuf[0], errbuf_len);
525     error_string = "E2SM Control Message Constraint failed : " + error_string;
526     return false;
527   }
528
529   asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_controlMessage, message, buf, *size);
530   if(retval.encoded == -1){
531     error_string.assign(strerror(errno));
532     error_string = "Error encoding E2SM Control Message. Reason = " + error_string;
533     return false;
534   }
535   else if (retval.encoded > *size){
536     std::stringstream ss;
537     ss  <<"Error encoding E2SM Control Message . Reason =  encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
538     error_string = ss.str();
539     
540     return false;
541   }
542   else{
543     *size = retval.encoded;
544   }
545   
546   return true;
547 }
548
549
550
551 // Used when generating an indication header 
552 bool e2sm_control::set_header_fields(E2SM_gNB_X2_controlHeader_t *header,  e2sm_header_helper &helper){
553
554   if (header == 0){
555     error_string = "Invalid reference for E2SM Control Header set fields";
556     return false;
557   }
558   
559   
560   header->interfaceDirection = helper.interface_direction;
561   header->interface_ID.present = Interface_ID_PR_global_gNB_ID;
562   header->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
563
564
565   // to do : need to put correct code here for upding plmn id and gNodeB
566   // for now just place holders :
567   memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
568   gNodeB_ID.pLMN_Identity.size = 3;
569   
570   memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
571   gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
572   
573   // we only do global gNodeB id for now, not eNodeB
574   gNodeB_ID.gNB_ID.present = GNB_ID_PR_gNB_ID;
575
576   return true;
577   
578 };
579
580
581 // used when decoding an indication header
582 bool e2sm_control::get_header_fields(E2SM_gNB_X2_controlHeader_t *header,  e2sm_header_helper &helper){
583
584   if (header == 0){
585     error_string = "Invalid reference for E2SM Control header get fields";
586     return false;
587   }
588   
589   helper.interface_direction = header->interfaceDirection;
590   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);
591   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);
592   
593   // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing)
594
595   return true;
596 }
597
598
599
600 // Used when generating an indication message 
601 bool   e2sm_control::set_message_fields(E2SM_gNB_X2_controlMessage_t *interface_message,  e2sm_message_helper &helper){
602
603   if(interface_message == 0){
604     error_string = "Invalid reference for E2SM Control Message set fields";
605     return false;
606   }
607
608   // interface-message is an octet string. just point it to the buffer
609   interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]);
610   interface_message->interfaceMessage.size = helper.x2ap_pdu_size;
611
612   return true;
613   
614 };
615
616 // used when decoding an indication message
617 bool e2sm_control::get_message_fields( E2SM_gNB_X2_controlMessage_t *interface_message, e2sm_message_helper &helper){
618
619   
620   if(interface_message == 0){
621     error_string = "Invalid reference for E2SM Control Message get fields";
622     return false;
623   }
624
625   // interface message is an octet string
626   helper.x2ap_pdu = interface_message->interfaceMessage.buf;;
627   helper.x2ap_pdu_size = interface_message->interfaceMessage.size;
628
629   return true;
630   
631 }
632