SIM-118: Enable to set RAN function id via environment variable
[sim/e2-interface.git] / e2sim / src / messagerouting / e2ap_message_handler.cpp
1 \r
2 \r
3 /*****************************************************************************\r
4 #                                                                            *\r
5 # Copyright 2020 AT&T Intellectual Property                                  *\r
6 # Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.      *\r
7 #                                                                            *\r
8 # Licensed under the Apache License, Version 2.0 (the "License");            *\r
9 # you may not use this file except in compliance with the License.           *\r
10 # You may obtain a copy of the License at                                    *\r
11 #                                                                            *\r
12 #      http://www.apache.org/licenses/LICENSE-2.0                            *\r
13 #                                                                            *\r
14 # Unless required by applicable law or agreed to in writing, software        *\r
15 # distributed under the License is distributed on an "AS IS" BASIS,          *\r
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *\r
17 # See the License for the specific language governing permissions and        *\r
18 # limitations under the License.                                             *\r
19 #                                                                            *\r
20 ******************************************************************************/\r
21 #include "e2ap_message_handler.hpp"\r
22 \r
23 //#include <iostream>\r
24 //#include <vector>\r
25 #include <stdexcept>\r
26 #include <unistd.h>\r
27 \r
28 #include "encode_e2apv1.hpp"\r
29 \r
30 void e2ap_handle_sctp_data(int& socket_fd, sctp_buffer_t& data, bool xmlenc, E2Sim* e2sim) {\r
31   E2AP_PDU_t* pdu = (E2AP_PDU_t*)calloc(1, sizeof(E2AP_PDU));\r
32   ASN_STRUCT_RESET(asn_DEF_E2AP_PDU, pdu);\r
33 \r
34   asn_transfer_syntax syntax;\r
35 \r
36   syntax = ATS_ALIGNED_BASIC_PER;\r
37   auto rval = asn_decode(nullptr, syntax, &asn_DEF_E2AP_PDU, (void**)&pdu, data.buffer, data.len);\r
38 \r
39   switch (rval.code) {\r
40     case RC_WMORE:\r
41     case RC_FAIL:\r
42       LOG_E("Failed to decode E2AP data from SCTP connection");\r
43       ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);\r
44       exit(1);\r
45     default:\r
46       break;\r
47   }\r
48 \r
49   int procedureCode = e2ap_asn1c_get_procedureCode(pdu);
50   int index = (int)pdu->present;
51
52   LOG_D("Unpacked E2AP-PDU: index = %d, procedureCode = %d", index, procedureCode);
53
54   switch (procedureCode) {
55     case ProcedureCode_id_E2setup:
56       LOG_I("Received a message of E2 setup procedure");\r
57       switch (index) {\r
58         case E2AP_PDU_PR_initiatingMessage:\r
59           e2ap_handle_E2SetupRequest(pdu, socket_fd);\r
60           LOG_I("Received SETUP-REQUEST");\r
61           break;\r
62 \r
63         case E2AP_PDU_PR_successfulOutcome:\r
64           LOG_I("Received SETUP-RESPONSE-SUCCESS");\r
65           break;\r
66 \r
67         case E2AP_PDU_PR_unsuccessfulOutcome:\r
68           LOG_I("Received SETUP-RESPONSE-FAILURE");\r
69           break;\r
70 \r
71         default:\r
72           LOG_E("Invalid message index=%d in E2AP-PDU", index);\r
73           break;\r
74       }\r
75       break;\r
76 \r
77     case ProcedureCode_id_Reset:  // reset = 7\r
78       LOG_I("Received a message of Reset procedure");\r
79       switch (index) {\r
80         case E2AP_PDU_PR_initiatingMessage:\r
81           LOG_I("Received RESET-REQUEST");\r
82           break;\r
83 \r
84         case E2AP_PDU_PR_successfulOutcome:\r
85           break;\r
86 \r
87         case E2AP_PDU_PR_unsuccessfulOutcome:\r
88           break;\r
89 \r
90         default:\r
91           LOG_E("Invalid message index=%d in E2AP-PDU", index);\r
92           break;\r
93       }\r
94       break;\r
95 \r
96     case ProcedureCode_id_RICsubscription:  // RIC SUBSCRIPTION = 201\r
97       LOG_I("Received a message of RIC subscription procedure");
98       switch (index) {
99         case E2AP_PDU_PR_initiatingMessage: {  // initiatingMessage
100           long func_id = encoding::get_function_id_from_subscription(pdu);
101           LOG_I("Received RIC subscription request for function with ID %d", func_id);
102
103           try {
104             SubscriptionCallback cb;
105             cb = e2sim->get_subscription_callback(func_id);
106             LOG_I("Calling callback subscription function to handle subscription request to function with ID %d", func_id);
107             cb(pdu);
108           } catch (const std::out_of_range& e) {
109             LOG_E("No RAN Function with this ID exists\n");
110           }
111
112           break;
113         }
114
115         case E2AP_PDU_PR_successfulOutcome:
116           LOG_I("Received RIC-SUBSCRIPTION-RESPONSE");
117           break;\r
118 \r
119         case E2AP_PDU_PR_unsuccessfulOutcome:\r
120           LOG_I("Received RIC-SUBSCRIPTION-FAILURE");\r
121           break;\r
122 \r
123         default:\r
124           LOG_E("Invalid message index=%d in E2AP-PDU", index);\r
125           break;\r
126       }\r
127       break;\r
128 \r
129     case ProcedureCode_id_RICindication:  // 205\r
130       LOG_I("Received a message of RIC indication procedure");\r
131       switch (index) {\r
132         case E2AP_PDU_PR_initiatingMessage:  // initiatingMessage\r
133           LOG_I("Received RIC-INDICATION-REQUEST");\r
134           // e2ap_handle_RICSubscriptionRequest(pdu, socket_fd);\r
135           break;\r
136         case E2AP_PDU_PR_successfulOutcome:\r
137           LOG_I("Received RIC-INDICATION-RESPONSE");\r
138           break;\r
139 \r
140         case E2AP_PDU_PR_unsuccessfulOutcome:\r
141           LOG_I("Received RIC-INDICATION-FAILURE");\r
142           break;\r
143 \r
144         default:\r
145           LOG_E("Invalid message index=%d in E2AP-PDU %d", index, (int)ProcedureCode_id_RICindication);\r
146           break;\r
147       }\r
148       break;\r
149 \r
150     case ProcedureCode_id_RICserviceQuery:\r
151       LOG_I("Received a message of RIC service query procedure");\r
152       switch (index) {\r
153         case E2AP_PDU_PR_initiatingMessage:\r
154           LOG_I("Received RIC-Service-Query")\r
155           e2ap_handle_E2SeviceRequest(pdu, socket_fd, e2sim);\r
156           break;\r
157 \r
158         default:\r
159           LOG_E("Invalid message index=%d in E2AP-PDU %d", index, (int)ProcedureCode_id_RICserviceQuery);\r
160           break;\r
161       }\r
162       break;\r
163 \r
164     case ProcedureCode_id_E2nodeConfigurationUpdate:\r
165       LOG_I("Received a message of E2 node configuration update procedure");\r
166       switch (index) {\r
167         case E2AP_PDU_PR_successfulOutcome:\r
168           LOG_I("Received E2nodeConfigurationUpdate")\r
169           break;\r
170 \r
171         default:\r
172           LOG_E("Invalid message index=%d in E2AP-PDU %d", index, (int)ProcedureCode_id_E2nodeConfigurationUpdate);\r
173           break;\r
174       }\r
175       break;\r
176 \r
177     case ProcedureCode_id_RICserviceUpdate:\r
178       LOG_I("Received a message of RIC service update procedure");\r
179       switch (index) {\r
180         case E2AP_PDU_PR_successfulOutcome:\r
181           LOG_I("Received RIC-SERVICE-UPDATE-SUCCESS")\r
182           break;\r
183 \r
184         case E2AP_PDU_PR_unsuccessfulOutcome:\r
185           LOG_I("Received RIC-SERVICE-UPDATE-FAILURE")\r
186           break;\r
187 \r
188         default:\r
189           LOG_E("Invalid message index=%d in E2AP-PDU %d", index, (int)ProcedureCode_id_RICserviceUpdate);\r
190           break;\r
191       }\r
192       break;\r
193 \r
194     default:\r
195       LOG_E("No available handler for procedureCode=%d", procedureCode);\r
196       break;\r
197   }\r
198   ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);\r
199 }\r
200 \r
201 void e2ap_handle_E2SeviceRequest(E2AP_PDU_t* pdu, int& socket_fd, E2Sim* e2sim) {\r
202   auto buffer_size = MAX_SCTP_BUFFER;\r
203   unsigned char buffer[MAX_SCTP_BUFFER];\r
204   E2AP_PDU_t* res_pdu = (E2AP_PDU_t*)calloc(1, sizeof(E2AP_PDU));\r
205 \r
206   // prepare ran function defination\r
207   std::vector<encoding::ran_func_info> all_funcs;\r
208 \r
209   // Loop through RAN function definitions that are registered\r
210 \r
211   for (std::pair<long, OCTET_STRING_t*> elem : e2sim->getRegistered_ran_functions()) {\r
212     printf("looping through ran func\n");\r
213     encoding::ran_func_info next_func;\r
214 \r
215     next_func.ranFunctionId = elem.first;\r
216     next_func.ranFunctionDesc = elem.second;\r
217     next_func.ranFunctionRev = (long)3;\r
218     all_funcs.push_back(next_func);\r
219   }\r
220 \r
221   printf("about to call service update encode\n");\r
222 \r
223   encoding::generate_e2apv1_service_update(res_pdu, all_funcs);\r
224 \r
225   LOG_D("Created E2-SERVICE-UPDATE");\r
226 \r
227   e2ap_asn1c_print_pdu(res_pdu);\r
228 \r
229   sctp_buffer_t data;\r
230 \r
231   char error_buf[300] = {\r
232       0,\r
233   };\r
234   size_t errlen = 0;\r
235 \r
236   asn_check_constraints(&asn_DEF_E2AP_PDU, res_pdu, error_buf, &errlen);\r
237   printf("error length %d\n", errlen);\r
238   printf("error buf %s\n", error_buf);\r
239 \r
240   auto er = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, res_pdu, buffer, buffer_size);\r
241   \r
242   if (er.encoded == -1) {\r
243     LOG_E("Failed to serialize message. Detail: %s.\n", asn_DEF_E2AP_PDU.name);\r
244     exit(1);\r
245   } else if (er.encoded > buffer_size) {\r
246     LOG_E("Buffer of size %zu is too small for %s, need %zu\n", buffer_size, asn_DEF_E2AP_PDU.name, er.encoded);\r
247     exit(1);\r
248   }\r
249 \r
250   data.len = er.encoded;\r
251 \r
252   memcpy(data.buffer, buffer, er.encoded);\r
253 \r
254   // send response data over sctp\r
255   if (sctp_send_data(socket_fd, data) > 0) {\r
256     LOG_I("Sent E2-SERVICE-UPDATE");\r
257   } else {\r
258     LOG_E("Unable to send E2-SERVICE-UPDATE to peer");\r
259   }\r
260 }\r
261 \r
262 void e2ap_send_e2nodeConfigUpdate(int& socket_fd) {\r
263   auto buffer_size = MAX_SCTP_BUFFER;\r
264   unsigned char buffer[MAX_SCTP_BUFFER];\r
265   E2AP_PDU_t* pdu = (E2AP_PDU_t*)calloc(1, sizeof(E2AP_PDU));\r
266 \r
267   LOG_I("Generating E2 node configure update");\r
268 \r
269   encoding::generate_e2apv2_config_update(pdu);\r
270 \r
271   e2ap_asn1c_print_pdu(pdu);\r
272 \r
273   sctp_buffer_t data;\r
274 \r
275   char error_buf[300] = {\r
276       0,\r
277   };\r
278   size_t errlen = 0;\r
279 \r
280   asn_check_constraints(&asn_DEF_E2AP_PDU, pdu, error_buf, &errlen);\r
281 \r
282   auto er = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu, buffer, buffer_size);\r
283 \r
284   if (er.encoded == -1) {\r
285     LOG_E("Failed to serialize message. Detail: %s.\n", asn_DEF_E2AP_PDU.name);\r
286     exit(1);\r
287   } else if (er.encoded > buffer_size) {\r
288     LOG_E("Buffer of size %zu is too small for %s, need %zu\n", buffer_size, asn_DEF_E2AP_PDU.name, er.encoded);\r
289     exit(1);\r
290   }\r
291 \r
292   data.len = er.encoded;\r
293 \r
294   memcpy(data.buffer, buffer, er.encoded);\r
295 \r
296   // send response data over sctp\r
297   if (sctp_send_data(socket_fd, data) > 0) {\r
298     LOG_I("Sent E2nodeConfigUpdate");\r
299   } else {\r
300     LOG_E("[SCTP] Unable to send E2nodeConfigUpdate to peer");\r
301   }\r
302 }\r
303 \r
304 void e2ap_handle_E2SetupRequest(E2AP_PDU_t* pdu, int& socket_fd) {\r
305   E2AP_PDU_t* res_pdu = (E2AP_PDU_t*)calloc(1, sizeof(E2AP_PDU));\r
306   encoding::generate_e2apv1_setup_response(res_pdu);\r
307 \r
308   LOG_D("Created E2-SETUP-RESPONSE");\r
309 \r
310   e2ap_asn1c_print_pdu(res_pdu);\r
311 \r
312   auto buffer_size = MAX_SCTP_BUFFER;\r
313   unsigned char buffer[MAX_SCTP_BUFFER];\r
314 \r
315   sctp_buffer_t data;\r
316   auto er = asn_encode_to_buffer(nullptr, ATS_BASIC_XER, &asn_DEF_E2AP_PDU, res_pdu, buffer, buffer_size);\r
317 \r
318   if (er.encoded == -1) {\r
319     LOG_E("Failed to serialize message. Detail: %s.\n", asn_DEF_E2AP_PDU.name);\r
320     exit(1);\r
321   } else if (er.encoded > buffer_size) {\r
322     LOG_E("Buffer of size %zu is too small for %s, need %zu\n", buffer_size, asn_DEF_E2AP_PDU.name, er.encoded);\r
323     exit(1);\r
324   }\r
325 \r
326   data.len = er.encoded;\r
327   \r
328   memcpy(data.buffer, buffer, er.encoded);\r
329 \r
330   // send response data over sctp\r
331   if (sctp_send_data(socket_fd, data) > 0) {\r
332     LOG_I("Sent E2-SETUP-RESPONSE");\r
333   } else {\r
334     LOG_E("[SCTP] Unable to send E2-SETUP-RESPONSE to peer");\r
335   }\r
336 \r
337   sleep(5);\r
338 \r
339   // Sending Subscription Request\r
340 \r
341   E2AP_PDU_t* pdu_sub = (E2AP_PDU_t*)calloc(1, sizeof(E2AP_PDU));\r
342 \r
343   encoding::generate_e2apv1_subscription_request(pdu_sub);\r
344 \r
345   xer_fprint(stderr, &asn_DEF_E2AP_PDU, pdu_sub);\r
346 \r
347   auto buffer_size2 = MAX_SCTP_BUFFER;\r
348   unsigned char buffer2[MAX_SCTP_BUFFER];\r
349 \r
350   sctp_buffer_t data2;\r
351 \r
352   auto er2 = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu_sub, buffer2, buffer_size2);\r
353 \r
354   if (er2.encoded == -1) {\r
355     LOG_E("Failed to serialize message. Detail: %s.\n", asn_DEF_E2AP_PDU.name);\r
356     exit(1);\r
357   } else if (er2.encoded > buffer_size2) {\r
358     LOG_E("Buffer of size %zu is too small for %s, need %zu\n", buffer_size2, asn_DEF_E2AP_PDU.name, er2.encoded);\r
359     exit(1);\r
360   }\r
361 \r
362   data2.len = er2.encoded;\r
363   memcpy(data2.buffer, buffer2, er2.encoded);\r
364 \r
365   if (sctp_send_data(socket_fd, data2) > 0) {\r
366     LOG_I("Sent E2-SUBSCRIPTION-REQUEST");\r
367   } else {\r
368     LOG_E("[SCTP] Unable to send E2-SUBSCRIPTION-REQUEST to peer");\r
369   }\r
370 }\r
371 \r
372 /*\r
373 void e2ap_handle_RICSubscriptionRequest(E2AP_PDU_t* pdu, int &socket_fd)\r
374 {\r
375 \r
376   //Send back Subscription Success Response\r
377 \r
378   E2AP_PDU_t* pdu_resp = (E2AP_PDU_t*)calloc(1,sizeof(E2AP_PDU));\r
379 \r
380   generate_e2apv1_subscription_response(pdu_resp, pdu);\r
381 \r
382   fprintf(stderr, "Subscription Response\n");\r
383 \r
384   xer_fprint(stderr, &asn_DEF_E2AP_PDU, pdu_resp);\r
385 \r
386   auto buffer_size2 = MAX_SCTP_BUFFER;\r
387   unsigned char buffer2[MAX_SCTP_BUFFER];\r
388 \r
389   sctp_buffer_t data2;\r
390 \r
391   auto er2 = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu_resp, buffer2, buffer_size2);\r
392   data2.len = er2.encoded;\r
393 \r
394   fprintf(stderr, "er encded is %d\n", er2.encoded);\r
395 \r
396   memcpy(data2.buffer, buffer2, er2.encoded);\r
397 \r
398   if(sctp_send_data(socket_fd, data2) > 0) {\r
399     LOG_I("Sent RIC-SUBSCRIPTION-RESPONSE");\r
400   } else {\r
401     LOG_E("[SCTP] Unable to send RIC-SUBSCRIPTION-RESPONSE to peer");\r
402   }\r
403 \r
404 \r
405   //Send back an Indication\r
406 \r
407   E2AP_PDU_t* pdu_ind = (E2AP_PDU_t*)calloc(1,sizeof(E2AP_PDU));\r
408 \r
409   generate_e2apv1_indication_request(pdu_ind);\r
410 \r
411   xer_fprint(stderr, &asn_DEF_E2AP_PDU, pdu_ind);\r
412 \r
413   auto buffer_size = MAX_SCTP_BUFFER;\r
414   unsigned char buffer[MAX_SCTP_BUFFER];\r
415 \r
416   sctp_buffer_t data;\r
417 \r
418   auto er = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu_ind, buffer, buffer_size);\r
419   data.len = er.encoded;\r
420 \r
421   fprintf(stderr, "er encded is %d\n", er.encoded);\r
422 \r
423   memcpy(data.buffer, buffer, er.encoded);\r
424 \r
425   if(sctp_send_data(socket_fd, data) > 0) {\r
426     LOG_I("Sent RIC-INDICATION-REQUEST");\r
427   } else {\r
428     LOG_E("[SCTP] Unable to send RIC-INDICATION-REQUEST to peer");\r
429   }\r
430 \r
431 }\r
432 */\r