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