Refactor folder structure.
[sim/o1-interface.git] / ntsimulator / src / ves-messages / heartbeat.c
1 /*************************************************************************
2 *
3 * Copyright 2019 highstreet technologies GmbH and others
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <signal.h>
22 #include <inttypes.h>
23 #include <limits.h>
24 #include <string.h>
25 #include <time.h>
26 #include <math.h>
27 #include <sys/time.h>
28
29 #include <pthread.h>
30
31 #include "heartbeat.h"
32 #include "sysrepo.h"
33 #include "sysrepo/values.h"
34
35 #include "utils.h"
36
37 #define LINE_BUFSIZE 128
38 #define SLEEP_BEFORE_PNF_AUTOREG 60
39
40 volatile int exit_application = 0;
41
42 pthread_mutex_t lock;
43
44 static  CURL *curl;
45
46 int _init_curl()
47 {
48         curl = curl_easy_init();
49
50         if (curl == NULL) {
51                 printf("cURL initialization error! Aborting call!\n");
52                 return SR_ERR_OPERATION_FAILED;
53         }
54
55         return SR_ERR_OK;
56 }
57
58 int cleanup_curl()
59 {
60         if (curl != NULL)
61         {
62                 curl_easy_cleanup(curl);
63         }
64
65         return SR_ERR_OK;
66 }
67
68 /*
69  * Heartbeat payload example
70  *
71  * {
72   "event": {
73     "commonEventHeader": {
74       "domain": "heartbeat",
75       "eventId": "parallels-Parallels-Virtual-Platform_2019-10-24T10:25:25.514Z",
76       "eventName": "heartbeat_Controller",
77       "eventType": "Controller",
78       "sequence": 0,
79       "priority": "Low",
80       "reportingEntityId": "",
81       "reportingEntityName": "parallels-Parallels-Virtual-Platform",
82       "sourceId": "",
83       "sourceName": "parallels-Parallels-Virtual-Platform",
84       "startEpochMicrosec": 1571912725514,
85       "lastEpochMicrosec": 1571912725514,
86       "nfNamingCode": "sdn controller",
87       "nfVendorName": "sdn",
88       "timeZoneOffset": "+00:00",
89       "version": "4.0.1",
90       "vesEventListenerVersion":"7.0.1"
91     },
92     "heartbeatFields": {
93       "heartbeatFieldsVersion": "3.0",
94       "heartbeatInterval": 20,
95       "additionalFields": {
96         "eventTime": "2019-10-24T10:25:25.514Z"
97       }
98     }
99   }
100 }
101 *
102 * */
103
104 static int send_heartbeat(int heartbeat_interval)
105 {
106         CURLcode res;
107         static int sequence_number = 0;
108
109         prepare_ves_message_curl(curl);
110
111         cJSON *postDataJson = cJSON_CreateObject();
112         if (postDataJson == NULL)
113         {
114                 printf("Could not create JSON object: postDataJson\n");
115                 return 1;
116         }
117
118         cJSON *event = cJSON_CreateObject();
119         if (event == NULL)
120         {
121                 printf("Could not create JSON object: event\n");
122                 return 1;
123         }
124         cJSON_AddItemToObject(postDataJson, "event", event);
125
126         char hostname[100];
127         sprintf(hostname, "%s", getenv("HOSTNAME"));
128
129         cJSON *commonEventHeader = vesCreateCommonEventHeader("heartbeat", "Controller", hostname, sequence_number++);
130         if (commonEventHeader == NULL)
131         {
132                 printf("Could not create JSON object: commonEventHeader\n");
133                 cJSON_Delete(postDataJson);
134                 return 1;
135         }
136         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
137
138         cJSON *heartbeatFields = vesCreateHeartbeatFields(heartbeat_interval);
139         if (heartbeatFields == NULL)
140         {
141                 printf("Could not create JSON object: heartbeatFields\n");
142                 cJSON_Delete(postDataJson);
143                 return 1;
144         }
145         cJSON_AddItemToObject(event, "heartbeatFields", heartbeatFields);
146
147     char *post_data_string = NULL;
148
149         post_data_string = cJSON_PrintUnformatted(postDataJson);
150
151         printf("Post data JSON:\n%s\n", post_data_string);
152
153         if (postDataJson != NULL)
154         {
155                 cJSON_Delete(postDataJson);
156         }
157
158         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
159
160         res = curl_easy_perform(curl);
161
162         if (res != CURLE_OK)
163         {
164                 return SR_ERR_OPERATION_FAILED;
165         }
166
167         return SR_ERR_OK;
168 }
169
170 static void
171 sigint_handler(int signum)
172 {
173     exit_application = 1;
174 }
175
176 static int send_pnf_registration_instance(char *hostname, int port, bool is_tls)
177 {
178         CURLcode res;
179         static int sequence_number = 0;
180
181         prepare_ves_message_curl(curl);
182
183         cJSON *postDataJson = cJSON_CreateObject();
184         if (postDataJson == NULL)
185         {
186                 printf("Could not create JSON object: postDataJson\n");
187                 return 1;
188         }
189
190         cJSON *event = cJSON_CreateObject();
191         if (event == NULL)
192         {
193                 printf("Could not create JSON object: event\n");
194                 cJSON_Delete(postDataJson);
195                 return 1;
196         }
197         cJSON_AddItemToObject(postDataJson, "event", event);
198
199         char source_name[100];
200         sprintf(source_name, "%s_%d", hostname, port);
201
202         cJSON *commonEventHeader = vesCreateCommonEventHeader("pnfRegistration", "EventType5G", source_name, sequence_number++);
203         if (commonEventHeader == NULL)
204         {
205                 printf("Could not create JSON object: commonEventHeader\n");
206                 cJSON_Delete(postDataJson);
207                 return 1;
208         }
209         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
210
211         cJSON *pnfRegistrationFields = vesCreatePnfRegistrationFields(port, is_tls);
212         if (pnfRegistrationFields == NULL)
213         {
214                 printf("Could not create JSON object: pnfRegistrationFields\n");
215                 cJSON_Delete(postDataJson);
216                 return 1;
217         }
218         cJSON_AddItemToObject(event, "pnfRegistrationFields", pnfRegistrationFields);
219
220     char *post_data_string = NULL;
221
222         post_data_string = cJSON_PrintUnformatted(postDataJson);
223
224         printf("Post data JSON:\n%s\n", post_data_string);
225
226         if (postDataJson != NULL)
227         {
228                 cJSON_Delete(postDataJson);
229         }
230
231         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
232
233         res = curl_easy_perform(curl);
234
235         if (res != CURLE_OK)
236         {
237                 printf("Failed to send cURL...\n");
238                 return SR_ERR_OPERATION_FAILED;
239         }
240
241         return SR_ERR_OK;
242 }
243
244 static void pnf_registration(void)
245 {
246         // delay the PNF Registration VES message, until anything else is initialized
247         printf("delay the PNF Registration VES message, until anything else is initialized");
248         sleep(SLEEP_BEFORE_PNF_AUTOREG);
249
250         int is_reg = getVesRegistrationFromConfigJson();
251
252         if (!is_reg)
253         {
254                 //ves-registration object is set to False, we do not make an automatic PNF registration
255                 printf("ves-registration object is set to False, we do not make an automatic PNF registration");
256                 return;
257         }
258
259         int rc = SR_ERR_OK, netconf_port_base = 0;
260         char *netconf_base_string = getenv("NETCONF_BASE");
261         char *hostname_string = getenv("HOSTNAME");
262
263         if (netconf_base_string != NULL)
264         {
265                 rc = sscanf(netconf_base_string, "%d", &netconf_port_base);
266                 if (rc != 1)
267                 {
268                         printf("Could not find the NETCONF base port, aborting the PNF registration...\n");
269                         return;
270                 }
271         }
272
273         //TODO This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
274         for (int port = 0; port < NETCONF_CONNECTIONS_PER_DEVICE - 3; ++port)
275         {
276                 pthread_mutex_lock(&lock);
277                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, FALSE);
278                 if (rc != SR_ERR_OK)
279                 {
280                         printf("Could not send PNF Registration SSH message...\n");
281                 }
282                 pthread_mutex_unlock(&lock);
283         }
284         for (int port = NETCONF_CONNECTIONS_PER_DEVICE - 3; port < NETCONF_CONNECTIONS_PER_DEVICE; ++port)
285         {
286                 pthread_mutex_lock(&lock);
287                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, TRUE);
288                 pthread_mutex_unlock(&lock);
289                 if (rc != SR_ERR_OK)
290                 {
291                         printf("Could not send PNF Registration TLS message...\n");
292                 }
293         }
294
295         return;
296 }
297
298 int
299 main(int argc, char **argv)
300 {
301     int rc = SR_ERR_OK;
302
303     int heartbeat_interval = 120; //seconds
304
305     setbuf(stdout, NULL);
306
307     if (pthread_mutex_init(&lock, NULL) != 0)
308         {
309                 printf("Mutex init failed...\n");
310                 goto cleanup;
311         }
312
313     pthread_t pnf_autoregistration_thread;
314         if(pthread_create(&pnf_autoregistration_thread, NULL, pnf_registration, NULL))
315         {
316                 fprintf(stderr, "Could not create thread for pnf auto registration\n");
317                 goto cleanup;
318         }
319
320     rc = _init_curl();
321     if (rc != SR_ERR_OK)
322     {
323         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
324         goto cleanup;
325     }
326
327     /* loop until ctrl-c is pressed / SIGINT is received */
328     signal(SIGINT, sigint_handler);
329     signal(SIGTERM, sigint_handler);
330     signal(SIGPIPE, SIG_IGN);
331
332     while (!exit_application)
333     {
334         heartbeat_interval = getVesHeartbeatPeriodFromConfigJson();
335
336         if (heartbeat_interval > 0)
337         {
338                 pthread_mutex_lock(&lock);
339                         send_heartbeat(heartbeat_interval);
340                         pthread_mutex_unlock(&lock);
341                         sleep(heartbeat_interval);
342         }
343         else
344         {
345                 sleep(1);
346         }
347     }
348
349     printf("Application exit requested, exiting.\n");
350
351 cleanup:
352
353     rc = cleanup_curl();
354
355     return rc;
356 }
357