Add License information in every source file or script.
[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 //static void prepare_ves_message_curl(void)
69 //{
70 //      curl_easy_reset(curl);
71 //      set_curl_common_info();
72 //
73 //      char *ves_ip = getVesIpFromConfigJson();
74 //      int ves_port = getVesPortFromConfigJson();
75 //
76 //      char url[100];
77 //      sprintf(url, "http://%s:%d/eventListener/v7", ves_ip, ves_port);
78 //      curl_easy_setopt(curl, CURLOPT_URL, url);
79 //
80 //      free(ves_ip);
81 //
82 ////    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
83 //
84 //      return;
85 //}
86 /*
87  * Heartbeat payload example
88  *
89  * {
90   "event": {
91     "commonEventHeader": {
92       "domain": "heartbeat",
93       "eventId": "parallels-Parallels-Virtual-Platform_2019-10-24T10:25:25.514Z",
94       "eventName": "heartbeat_Controller",
95       "eventType": "Controller",
96       "sequence": 0,
97       "priority": "Low",
98       "reportingEntityId": "",
99       "reportingEntityName": "parallels-Parallels-Virtual-Platform",
100       "sourceId": "",
101       "sourceName": "parallels-Parallels-Virtual-Platform",
102       "startEpochMicrosec": 1571912725514,
103       "lastEpochMicrosec": 1571912725514,
104       "nfNamingCode": "sdn controller",
105       "nfVendorName": "sdn",
106       "timeZoneOffset": "+00:00",
107       "version": "4.0.1",
108       "vesEventListenerVersion":"7.0.1"
109     },
110     "heartbeatFields": {
111       "heartbeatFieldsVersion": "3.0",
112       "heartbeatInterval": 20,
113       "additionalFields": {
114         "eventTime": "2019-10-24T10:25:25.514Z"
115       }
116     }
117   }
118 }
119 *
120 * */
121
122 static int send_heartbeat(int heartbeat_interval)
123 {
124         CURLcode res;
125         static int sequence_number = 0;
126
127         prepare_ves_message_curl(curl);
128
129         cJSON *postDataJson = cJSON_CreateObject();
130
131         cJSON *event = cJSON_CreateObject();
132         if (event == NULL)
133         {
134                 printf("Could not create JSON object: event\n");
135                 return 1;
136         }
137         cJSON_AddItemToObject(postDataJson, "event", event);
138
139         char hostname[100];
140         sprintf(hostname, "%s", getenv("HOSTNAME"));
141
142         cJSON *commonEventHeader = vesCreateCommonEventHeader("heartbeat", "Controller", hostname, sequence_number++);
143         if (commonEventHeader == NULL)
144         {
145                 printf("Could not create JSON object: commonEventHeader\n");
146                 return 1;
147         }
148         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
149
150         cJSON *heartbeatFields = vesCreateHeartbeatFields(heartbeat_interval);
151         if (heartbeatFields == NULL)
152         {
153                 printf("Could not create JSON object: heartbeatFields\n");
154                 return 1;
155         }
156         cJSON_AddItemToObject(event, "heartbeatFields", heartbeatFields);
157
158     char *post_data_string = NULL;
159
160         post_data_string = cJSON_PrintUnformatted(postDataJson);
161
162         printf("Post data JSON:\n%s\n", post_data_string);
163
164         if (postDataJson != NULL)
165         {
166                 cJSON_Delete(postDataJson);
167         }
168
169         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
170
171         res = curl_easy_perform(curl);
172
173         if (res != CURLE_OK)
174         {
175                 printf("Failed to send cURL...\n");
176                 return SR_ERR_OPERATION_FAILED;
177         }
178
179         return SR_ERR_OK;
180 }
181
182 static void
183 sigint_handler(int signum)
184 {
185     exit_application = 1;
186 }
187
188 static int send_pnf_registration_instance(char *hostname, int port, bool is_tls)
189 {
190         CURLcode res;
191         static int sequence_number = 0;
192
193         prepare_ves_message_curl(curl);
194
195         cJSON *postDataJson = cJSON_CreateObject();
196
197         cJSON *event = cJSON_CreateObject();
198         if (event == NULL)
199         {
200                 printf("Could not create JSON object: event\n");
201                 return 1;
202         }
203         cJSON_AddItemToObject(postDataJson, "event", event);
204
205         char source_name[100];
206         sprintf(source_name, "%s_%d", hostname, port);
207
208         cJSON *commonEventHeader = vesCreateCommonEventHeader("pnfRegistration", "EventType5G", source_name, sequence_number++);
209         if (commonEventHeader == NULL)
210         {
211                 printf("Could not create JSON object: commonEventHeader\n");
212                 return 1;
213         }
214         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
215
216         cJSON *pnfRegistrationFields = vesCreatePnfRegistrationFields(port, is_tls);
217         if (pnfRegistrationFields == NULL)
218         {
219                 printf("Could not create JSON object: pnfRegistrationFields\n");
220                 return 1;
221         }
222         cJSON_AddItemToObject(event, "pnfRegistrationFields", pnfRegistrationFields);
223
224     char *post_data_string = NULL;
225
226         post_data_string = cJSON_PrintUnformatted(postDataJson);
227
228         printf("Post data JSON:\n%s\n", post_data_string);
229
230         if (postDataJson != NULL)
231         {
232                 cJSON_Delete(postDataJson);
233         }
234
235         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
236
237         res = curl_easy_perform(curl);
238
239         if (res != CURLE_OK)
240         {
241                 printf("Failed to send cURL...\n");
242                 return SR_ERR_OPERATION_FAILED;
243         }
244
245         return SR_ERR_OK;
246 }
247
248 static void pnf_registration(void)
249 {
250         // delay the PNF Registration VES message, until anything else is initialized
251         printf("delay the PNF Registration VES message, until anything else is initialized");
252         sleep(SLEEP_BEFORE_PNF_AUTOREG);
253
254         int is_reg = getVesRegistrationFromConfigJson();
255
256         if (!is_reg)
257         {
258                 //ves-registration object is set to False, we do not make an automatic PNF registration
259                 printf("ves-registration object is set to False, we do not make an automatic PNF registration");
260                 return;
261         }
262
263         int rc = SR_ERR_OK, netconf_port_base = 0;
264         char *netconf_base_string = getenv("NETCONF_BASE");
265         char *hostname_string = getenv("HOSTNAME");
266
267         if (netconf_base_string != NULL)
268         {
269                 rc = sscanf(netconf_base_string, "%d", &netconf_port_base);
270                 if (rc != 1)
271                 {
272                         printf("Could not find the NETCONF base port, aborting the PNF registration...\n");
273                         return;
274                 }
275         }
276
277         //TODO This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
278         for (int port = 0; port < NETCONF_CONNECTIONS_PER_DEVICE - 3; ++port)
279         {
280                 pthread_mutex_lock(&lock);
281                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, FALSE);
282                 if (rc != SR_ERR_OK)
283                 {
284                         printf("Could not send PNF Registration SSH message...\n");
285                 }
286                 pthread_mutex_unlock(&lock);
287         }
288         for (int port = NETCONF_CONNECTIONS_PER_DEVICE - 3; port < NETCONF_CONNECTIONS_PER_DEVICE; ++port)
289         {
290                 pthread_mutex_lock(&lock);
291                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, TRUE);
292                 pthread_mutex_unlock(&lock);
293                 if (rc != SR_ERR_OK)
294                 {
295                         printf("Could not send PNF Registration TLS message...\n");
296                 }
297         }
298
299         return;
300 }
301
302 int
303 main(int argc, char **argv)
304 {
305     int rc = SR_ERR_OK;
306
307     int heartbeat_interval = 120; //seconds
308
309     setbuf(stdout, NULL);
310
311     if (pthread_mutex_init(&lock, NULL) != 0)
312         {
313                 printf("Mutex init failed...\n");
314                 goto cleanup;
315         }
316
317     pthread_t pnf_autoregistration_thread;
318         if(pthread_create(&pnf_autoregistration_thread, NULL, pnf_registration, NULL))
319         {
320                 fprintf(stderr, "Could not create thread for pnf auto registration\n");
321                 goto cleanup;
322         }
323
324     rc = _init_curl();
325     if (rc != SR_ERR_OK)
326     {
327         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
328         goto cleanup;
329     }
330
331     /* loop until ctrl-c is pressed / SIGINT is received */
332     signal(SIGINT, sigint_handler);
333     signal(SIGTERM, sigint_handler);
334     signal(SIGPIPE, SIG_IGN);
335
336     while (!exit_application)
337     {
338         heartbeat_interval = getVesHeartbeatPeriodFromConfigJson();
339
340         if (heartbeat_interval > 0)
341         {
342                 pthread_mutex_lock(&lock);
343                         send_heartbeat(heartbeat_interval);
344                         pthread_mutex_unlock(&lock);
345                         sleep(heartbeat_interval);
346         }
347         else
348         {
349                 sleep(1);
350         }
351     }
352
353     printf("Application exit requested, exiting.\n");
354
355 cleanup:
356
357     rc = cleanup_curl();
358
359     return rc;
360 }
361