Bug fix.
[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 *arg)
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 NULL;
257         }
258
259         int rc = SR_ERR_OK, netconf_port_base = 0;
260         char *hostname_string = getenv("HOSTNAME");
261     int port = 0;
262
263     netconf_port_base = getIntFromString(getenv("NETCONF_BASE"), 0);
264
265         //TODO This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
266         for (int i = 0; i < SSH_CONNECTIONS_PER_DEVICE; ++port, ++i)
267         {
268                 pthread_mutex_lock(&lock);
269                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, FALSE);
270                 if (rc != SR_ERR_OK)
271                 {
272                         printf("Could not send PNF Registration SSH message...\n");
273                 }
274                 pthread_mutex_unlock(&lock);
275         }
276         for (int i = 0; i < TLS_CONNECTIONS_PER_DEVICE; ++port, ++i)
277         {
278                 pthread_mutex_lock(&lock);
279                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, TRUE);
280                 pthread_mutex_unlock(&lock);
281                 if (rc != SR_ERR_OK)
282                 {
283                         printf("Could not send PNF Registration TLS message...\n");
284                 }
285         }
286
287         return NULL;
288 }
289
290 int
291 main(int argc, char **argv)
292 {
293     int rc = SR_ERR_OK;
294
295     int heartbeat_interval = 120; //seconds
296
297     setbuf(stdout, NULL);
298
299     if (pthread_mutex_init(&lock, NULL) != 0)
300         {
301                 printf("Mutex init failed...\n");
302                 goto cleanup;
303         }
304
305     pthread_t pnf_autoregistration_thread;
306         if(pthread_create(&pnf_autoregistration_thread, NULL, pnf_registration, NULL))
307         {
308                 fprintf(stderr, "Could not create thread for pnf auto registration\n");
309                 goto cleanup;
310         }
311
312     rc = _init_curl();
313     if (rc != SR_ERR_OK)
314     {
315         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
316         goto cleanup;
317     }
318
319     /* loop until ctrl-c is pressed / SIGINT is received */
320     signal(SIGINT, sigint_handler);
321     signal(SIGTERM, sigint_handler);
322     signal(SIGPIPE, SIG_IGN);
323
324     while (!exit_application)
325     {
326         heartbeat_interval = getVesHeartbeatPeriodFromConfigJson();
327
328         if (heartbeat_interval > 0)
329         {
330                 pthread_mutex_lock(&lock);
331                         send_heartbeat(heartbeat_interval);
332                         pthread_mutex_unlock(&lock);
333                         sleep(heartbeat_interval);
334         }
335         else
336         {
337                 sleep(1);
338         }
339     }
340
341     printf("Application exit requested, exiting.\n");
342
343 cleanup:
344
345     rc = cleanup_curl();
346
347     return rc;
348 }
349