0300ff95218165011ae75e99ad89e534201f578a
[sim/o1-interface.git] / ntsimulator / src / utils / utils.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 "utils.h"
19
20 #include <math.h>
21 #include <time.h>
22 #include <sys/time.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 void set_curl_common_info_ves(CURL *curl)
27 {
28         struct curl_slist *chunk = NULL;
29         chunk = curl_slist_append(chunk, "Content-Type: application/json");
30         chunk = curl_slist_append(chunk, "Accept: application/json");
31
32     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
33
34     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
35     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); //seconds timeout for an operation
36
37     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
38 }
39
40 void getCurrentDateAndTime(char *date_and_time)
41 {
42         time_t t = time(NULL);
43         struct tm tm = *localtime(&t);
44         struct timeval tv;
45         int millisec;
46
47         gettimeofday(&tv, NULL);
48         millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
49         if (millisec>=1000)
50         { // Allow for rounding up to nearest second
51                 millisec -=1000;
52                 tv.tv_sec++;
53                 millisec /= 100;
54         }
55         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
56         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
57         tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
58
59         return;
60 }
61
62 void    generateRandomMacAddress(char *mac_address)
63 {
64         long rand1, rand2, rand3, rand4, rand5, rand6;
65         rand1 = random_at_most(255);
66         rand2 = random_at_most(255);
67         rand3 = random_at_most(255);
68         rand4 = random_at_most(255);
69         rand5 = random_at_most(255);
70         rand6 = random_at_most(255);
71
72         sprintf(mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", rand1, rand2, rand3, rand4, rand5, rand6);
73
74         return;
75 }
76
77 long random_at_most(long max) {
78   unsigned long
79     // max <= RAND_MAX < ULONG_MAX, so this is okay.
80     num_bins = (unsigned long) max + 1,
81     num_rand = (unsigned long) RAND_MAX + 1,
82     bin_size = num_rand / num_bins,
83     defect   = num_rand % num_bins;
84
85   long x;
86   do {
87    x = random();
88   }
89   // This is carefully written not to overflow
90   while (num_rand - defect <= (unsigned long)x);
91
92   // Truncated division is intentional
93   return x/bin_size;
94 }
95
96 int getSecondsFromLastQuarterInterval(void)
97 {
98         time_t t = time(NULL);
99         time_t t_past = time(NULL);
100         struct tm tm = *localtime(&t);
101         struct tm tm_15_min_ago = tm;
102
103         //round to the last quarter hour
104         tm_15_min_ago.tm_min -= (tm_15_min_ago.tm_min % 15);
105         tm_15_min_ago.tm_sec = 0;
106
107         t=mktime(&tm_15_min_ago);
108         t_past=mktime(&tm);
109
110         double seconds = difftime(t_past, t);
111
112         return (int)seconds;
113 }
114
115 int getSecondsFromLastDayInterval(void)
116 {
117         time_t t = time(NULL);
118         time_t t_past = time(NULL);
119         struct tm tm = *localtime(&t);
120         struct tm tm_day_ago = tm;
121
122         //round to the last quarter hour
123         tm_day_ago.tm_hour = 0;
124         tm_day_ago.tm_min = 0;
125         tm_day_ago.tm_sec = 0;
126
127         t=mktime(&tm_day_ago);
128         t_past=mktime(&tm);
129
130         double seconds = difftime(t_past, t);
131
132         return (int)seconds;
133 }
134
135 void getPreviousQuarterInterval(int number_of_intervals, char *date_and_time)
136 {
137         time_t t = time(NULL);
138         t -= 15 * 60 * number_of_intervals;
139         struct tm tm = *localtime(&t);
140
141         tm.tm_min -= (tm.tm_min % 15);
142         tm.tm_sec = 0;
143
144         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
145         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
146         tm.tm_hour, tm.tm_min, tm.tm_sec);
147
148         return;
149 }
150
151 void getPreviousDayPmTimestamp(int number_of_intervals, char *date_and_time)
152 {
153         time_t t = time(NULL);
154         t -= 24 * 60 * 60 * number_of_intervals;
155         struct tm tm = *localtime(&t);
156
157         tm.tm_hour = 0;
158         tm.tm_min = 0;
159         tm.tm_sec = 0;
160
161         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
162         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
163         tm.tm_hour, tm.tm_min, tm.tm_sec);
164
165         return;
166 }
167
168 long int getMicrosecondsSinceEpoch(void)
169 {
170         time_t t = time(NULL);
171         struct timeval tv;
172         long int useconds;
173
174         gettimeofday(&tv, NULL);
175         useconds = t*1000 + tv.tv_usec; //add the microseconds to the seconds
176
177         return useconds;
178 }
179
180 //TODO need to implement other authentication methods as well, not only no-auth
181 void prepare_ves_message_curl(CURL *curl)
182 {
183         curl_easy_reset(curl);
184         set_curl_common_info_ves(curl);
185
186         char *ves_ip = getVesIpFromConfigJson();
187         int ves_port = getVesPortFromConfigJson();
188
189         char url[100];
190         sprintf(url, "http://%s:%d/eventListener/v7", ves_ip, ves_port);
191         curl_easy_setopt(curl, CURLOPT_URL, url);
192
193         free(ves_ip);
194
195         return;
196 }
197
198 /*
199  * Dynamically allocated memory;
200  * Caller needs to free the memory after it uses the value.
201  *
202 */
203 cJSON*  vesCreateCommonEventHeader(char *domain, char *event_type, char *source_name, int seq_id)
204 {
205         char dateAndTime[50];
206         getCurrentDateAndTime(dateAndTime);
207
208         long useconds = getMicrosecondsSinceEpoch();
209
210         cJSON *commonEventHeader = cJSON_CreateObject();
211         if (commonEventHeader == NULL)
212         {
213                 printf("Could not create JSON object: commonEventHeader\n");
214                 return NULL;
215         }
216
217         if (cJSON_AddStringToObject(commonEventHeader, "domain", domain) == NULL)
218         {
219                 printf("Could not create JSON object: domain\n");
220                 cJSON_Delete(commonEventHeader);
221                 return NULL;
222         }
223
224         char eventId[200];
225         sprintf(eventId, "%s_%s", source_name, dateAndTime);
226
227         if (cJSON_AddStringToObject(commonEventHeader, "eventId", eventId) == NULL)
228         {
229                 printf("Could not create JSON object: eventId\n");
230                 cJSON_Delete(commonEventHeader);
231                 return NULL;
232         }
233
234         char event_name[200];
235         sprintf(event_name, "%s_%s", domain, event_type);
236
237         if (cJSON_AddStringToObject(commonEventHeader, "eventName", event_name) == NULL)
238         {
239                 printf("Could not create JSON object: eventName\n");
240                 cJSON_Delete(commonEventHeader);
241                 return NULL;
242         }
243
244         if (cJSON_AddStringToObject(commonEventHeader, "eventType", event_type) == NULL)
245         {
246                 printf("Could not create JSON object: eventType\n");
247                 cJSON_Delete(commonEventHeader);
248                 return NULL;
249         }
250
251         if (cJSON_AddNumberToObject(commonEventHeader, "sequence", (double)(seq_id)) == NULL)
252         {
253                 printf("Could not create JSON object: sequence\n");
254                 cJSON_Delete(commonEventHeader);
255                 return NULL;
256         }
257
258         if (cJSON_AddStringToObject(commonEventHeader, "priority", "Low") == NULL)
259         {
260                 printf("Could not create JSON object: priority\n");
261                 cJSON_Delete(commonEventHeader);
262                 return NULL;
263         }
264
265         if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityId", "") == NULL)
266         {
267                 printf("Could not create JSON object: reportingEntityId\n");
268                 cJSON_Delete(commonEventHeader);
269                 return NULL;
270         }
271
272         if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityName", source_name) == NULL)
273         {
274                 printf("Could not create JSON object: reportingEntityName\n");
275                 cJSON_Delete(commonEventHeader);
276                 return NULL;
277         }
278
279         if (cJSON_AddStringToObject(commonEventHeader, "sourceId", "") == NULL)
280         {
281                 printf("Could not create JSON object: sourceId\n");
282                 cJSON_Delete(commonEventHeader);
283                 return NULL;
284         }
285
286         if (cJSON_AddStringToObject(commonEventHeader, "sourceName", source_name) == NULL)
287         {
288                 printf("Could not create JSON object: sourceName\n");
289                 cJSON_Delete(commonEventHeader);
290                 return NULL;
291         }
292
293         if (cJSON_AddNumberToObject(commonEventHeader, "startEpochMicrosec", (double)(useconds)) == NULL)
294         {
295                 printf("Could not create JSON object: startEpochMicrosec\n");
296                 cJSON_Delete(commonEventHeader);
297                 return NULL;
298         }
299
300         if (cJSON_AddNumberToObject(commonEventHeader, "lastEpochMicrosec", (double)(useconds)) == NULL)
301         {
302                 printf("Could not create JSON object: lastEpochMicrosec\n");
303                 cJSON_Delete(commonEventHeader);
304                 return NULL;
305         }
306
307         if (cJSON_AddStringToObject(commonEventHeader, "nfNamingCode", "sdn controller") == NULL)
308         {
309                 printf("Could not create JSON object: nfNamingCode\n");
310                 cJSON_Delete(commonEventHeader);
311                 return NULL;
312         }
313
314         if (cJSON_AddStringToObject(commonEventHeader, "nfVendorName", "sdn") == NULL)
315         {
316                 printf("Could not create JSON object: nfVendorName\n");
317                 cJSON_Delete(commonEventHeader);
318                 return NULL;
319         }
320
321         if (cJSON_AddStringToObject(commonEventHeader, "timeZoneOffset", "+00:00") == NULL)
322         {
323                 printf("Could not create JSON object: timeZoneOffset\n");
324                 cJSON_Delete(commonEventHeader);
325                 return NULL;
326         }
327
328         if (cJSON_AddStringToObject(commonEventHeader, "version", "4.0.1") == NULL)
329         {
330                 printf("Could not create JSON object: version\n");
331                 cJSON_Delete(commonEventHeader);
332                 return NULL;
333         }
334
335         if (cJSON_AddStringToObject(commonEventHeader, "vesEventListenerVersion", "7.0.1") == NULL)
336         {
337                 printf("Could not create JSON object: vesEventListenerVersion\n");
338                 cJSON_Delete(commonEventHeader);
339                 return NULL;
340         }
341
342         return commonEventHeader;
343 }
344
345 /*
346  * Dynamically allocated memory;
347  * Caller needs to free the memory after it uses the value.
348  *
349 */
350 cJSON*  vesCreateHeartbeatFields(int heartbeat_interval)
351 {
352         char dateAndTime[50];
353         getCurrentDateAndTime(dateAndTime);
354
355         cJSON *heartbeatFields = cJSON_CreateObject();
356         if (heartbeatFields == NULL)
357         {
358                 printf("Could not create JSON object: heartbeatFields\n");
359                 return NULL;
360         }
361
362         if (cJSON_AddStringToObject(heartbeatFields, "heartbeatFieldsVersion", "3.0") == NULL)
363         {
364                 printf("Could not create JSON object: heartbeatFieldsVersion\n");
365                 cJSON_Delete(heartbeatFields);
366                 return NULL;
367         }
368
369         if (cJSON_AddNumberToObject(heartbeatFields, "heartbeatInterval", (double)(heartbeat_interval)) == NULL)
370         {
371                 printf("Could not create JSON object: heartbeatInterval\n");
372                 cJSON_Delete(heartbeatFields);
373                 return NULL;
374         }
375
376         cJSON *additionalFields = cJSON_CreateObject();
377         if (additionalFields == NULL)
378         {
379                 printf("Could not create JSON object: additionalFields\n");
380                 cJSON_Delete(heartbeatFields);
381                 return NULL;
382         }
383         cJSON_AddItemToObject(heartbeatFields, "additionalFields", additionalFields);
384
385         if (cJSON_AddStringToObject(additionalFields, "eventTime", dateAndTime) == NULL)
386         {
387                 printf("Could not create JSON object: eventTime\n");
388                 cJSON_Delete(heartbeatFields);
389                 return NULL;
390         }
391
392         return heartbeatFields;
393 }
394
395 /*
396  * Dynamically allocated memory;
397  * Caller needs to free the memory after it uses the value.
398  *
399 */
400 char*   readConfigFileInString(void)
401 {
402         char * buffer = 0;
403         long length;
404         char config_file[200];
405         sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
406         FILE * f = fopen (config_file, "rb");
407
408         if (f)
409         {
410           fseek (f, 0, SEEK_END);
411           length = ftell (f);
412           fseek (f, 0, SEEK_SET);
413           buffer = malloc (length + 1);
414           if (buffer)
415           {
416             fread (buffer, 1, length, f);
417           }
418           fclose (f);
419           buffer[length] = '\0';
420         }
421
422         if (buffer)
423         {
424           return buffer;
425         }
426
427         return NULL;
428 }
429
430 void    writeConfigFile(char *config)
431 {
432         char config_file[200];
433         sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
434         FILE * f = fopen (config_file, "w");
435
436         if (f)
437         {
438                 fputs(config, f);
439                 fclose(f);
440         }
441         else
442         {
443                 printf("Could not write configuration file");
444         }
445 }
446
447 int     getFaultNotificationDelayPeriodFromConfigJson(void)
448 {
449         char *stringConfig = readConfigFileInString();
450         int notificationDelay = 0;
451
452         if (stringConfig == NULL)
453         {
454                 printf("Could not read JSON configuration file in string.");
455                 return 0;
456         }
457
458         cJSON *jsonConfig = cJSON_Parse(stringConfig);
459         if (jsonConfig == NULL)
460         {
461                 free(stringConfig);
462                 const char *error_ptr = cJSON_GetErrorPtr();
463                 if (error_ptr != NULL)
464                 {
465                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
466                 }
467                 return SR_ERR_OPERATION_FAILED;
468         }
469         //we don't need the string anymore
470         free(stringConfig);
471         stringConfig = NULL;
472
473         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
474         if (!cJSON_IsObject(notifConfig))
475         {
476                 printf("Configuration JSON is not as expected: notification-config is not an object");
477                 cJSON_Delete(jsonConfig);
478                 return SR_ERR_OPERATION_FAILED;
479         }
480
481         cJSON *faultNotifDelay = cJSON_GetObjectItemCaseSensitive(notifConfig, "fault-notification-delay-period");
482         if (!cJSON_IsNumber(faultNotifDelay))
483         {
484                 printf("Configuration JSON is not as expected: fault-notification-delay-period is not a number");
485                 cJSON_Delete(jsonConfig);
486                 return SR_ERR_OPERATION_FAILED;
487         }
488
489         notificationDelay = (int)(faultNotifDelay->valuedouble);
490
491         cJSON_Delete(jsonConfig);
492
493         return notificationDelay;
494 }
495
496 int     getVesHeartbeatPeriodFromConfigJson(void)
497 {
498         char *stringConfig = readConfigFileInString();
499         int vesHeartbeat = 0;
500
501         if (stringConfig == NULL)
502         {
503                 printf("Could not read JSON configuration file in string.");
504                 return 0;
505         }
506
507         cJSON *jsonConfig = cJSON_Parse(stringConfig);
508         if (jsonConfig == NULL)
509         {
510                 free(stringConfig);
511                 const char *error_ptr = cJSON_GetErrorPtr();
512                 if (error_ptr != NULL)
513                 {
514                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
515                 }
516                 return SR_ERR_OPERATION_FAILED;
517         }
518         //we don't need the string anymore
519         free(stringConfig);
520         stringConfig = NULL;
521
522         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
523         if (!cJSON_IsObject(notifConfig))
524         {
525                 printf("Configuration JSON is not as expected: notification-config is not an object");
526                 cJSON_Delete(jsonConfig);
527                 return SR_ERR_OPERATION_FAILED;
528         }
529
530         cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
531         if (!cJSON_IsNumber(vesHeartbeatPeriod))
532         {
533                 printf("Configuration JSON is not as expected: ves-heartbeat-period is not a number");
534                 cJSON_Delete(jsonConfig);
535                 return SR_ERR_OPERATION_FAILED;
536         }
537
538         vesHeartbeat = (int)(vesHeartbeatPeriod->valuedouble);
539
540         cJSON_Delete(jsonConfig);
541
542         return vesHeartbeat;
543 }
544
545
546 /*
547  * Dynamically allocated memory;
548  * Caller needs to free the memory after it uses the value.
549  *
550 */
551 char*   getVesAuthMethodFromConfigJson(void)
552 {
553         char *stringConfig = readConfigFileInString();
554
555         if (stringConfig == NULL)
556         {
557                 printf("Could not read JSON configuration file in string.");
558                 return 0;
559         }
560
561         cJSON *jsonConfig = cJSON_Parse(stringConfig);
562         if (jsonConfig == NULL)
563         {
564                 free(stringConfig);
565                 const char *error_ptr = cJSON_GetErrorPtr();
566                 if (error_ptr != NULL)
567                 {
568                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
569                 }
570                 return NULL;
571         }
572         //we don't need the string anymore
573         free(stringConfig);
574         stringConfig = NULL;
575
576         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
577         if (!cJSON_IsObject(vesDetails))
578         {
579                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
580                 cJSON_Delete(jsonConfig);
581                 return NULL;
582         }
583
584         cJSON *vesAuthMethod = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-auth-method");
585         if (!cJSON_IsString(vesAuthMethod))
586         {
587                 printf("Configuration JSON is not as expected: ves-endpoint-auth-method is not an object");
588                 cJSON_Delete(jsonConfig);
589                 return NULL;
590         }
591
592         char *auth_method_string = strdup(cJSON_GetStringValue(vesAuthMethod));
593
594         cJSON_Delete(jsonConfig);
595
596         return auth_method_string;
597 }
598
599 /*
600  * Dynamically allocated memory;
601  * Caller needs to free the memory after it uses the value.
602  *
603 */
604 char*   getVesIpFromConfigJson(void)
605 {
606         char *stringConfig = readConfigFileInString();
607
608         if (stringConfig == NULL)
609         {
610                 printf("Could not read JSON configuration file in string.");
611                 return 0;
612         }
613
614         cJSON *jsonConfig = cJSON_Parse(stringConfig);
615         if (jsonConfig == NULL)
616         {
617                 free(stringConfig);
618                 const char *error_ptr = cJSON_GetErrorPtr();
619                 if (error_ptr != NULL)
620                 {
621                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
622                 }
623                 return NULL;
624         }
625         //we don't need the string anymore
626         free(stringConfig);
627         stringConfig = NULL;
628
629         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
630         if (!cJSON_IsObject(vesDetails))
631         {
632                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
633                 cJSON_Delete(jsonConfig);
634                 return NULL;
635         }
636
637         cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
638         if (!cJSON_IsString(vesIp))
639         {
640                 printf("Configuration JSON is not as expected: ves-endpoint-ip is not an object");
641                 cJSON_Delete(jsonConfig);
642                 return NULL;
643         }
644
645         char *ves_ip = strdup(cJSON_GetStringValue(vesIp));
646
647         cJSON_Delete(jsonConfig);
648
649         return ves_ip;
650 }
651
652 int     getVesPortFromConfigJson(void)
653 {
654         char *stringConfig = readConfigFileInString();
655
656         if (stringConfig == NULL)
657         {
658                 printf("Could not read JSON configuration file in string.");
659                 return 0;
660         }
661
662         cJSON *jsonConfig = cJSON_Parse(stringConfig);
663         if (jsonConfig == NULL)
664         {
665                 free(stringConfig);
666                 const char *error_ptr = cJSON_GetErrorPtr();
667                 if (error_ptr != NULL)
668                 {
669                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
670                 }
671                 return SR_ERR_OPERATION_FAILED;
672         }
673         //we don't need the string anymore
674         free(stringConfig);
675         stringConfig = NULL;
676
677         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
678         if (!cJSON_IsObject(vesDetails))
679         {
680                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
681                 cJSON_Delete(jsonConfig);
682                 return SR_ERR_OPERATION_FAILED;
683         }
684
685         cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
686         if (!cJSON_IsNumber(vesPort))
687         {
688                 printf("Configuration JSON is not as expected: ves-endpoint-port is not an object");
689                 cJSON_Delete(jsonConfig);
690                 return SR_ERR_OPERATION_FAILED;
691         }
692
693         int port = (int)(vesPort->valuedouble);
694
695         cJSON_Delete(jsonConfig);
696
697         return port;
698 }
699
700 int     getVesRegistrationFromConfigJson(void)
701 {
702         char *stringConfig = readConfigFileInString();
703
704         if (stringConfig == NULL)
705         {
706                 printf("Could not read JSON configuration file in string.");
707                 return 0;
708         }
709
710         cJSON *jsonConfig = cJSON_Parse(stringConfig);
711         if (jsonConfig == NULL)
712         {
713                 free(stringConfig);
714                 const char *error_ptr = cJSON_GetErrorPtr();
715                 if (error_ptr != NULL)
716                 {
717                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
718                 }
719                 return SR_ERR_OPERATION_FAILED;
720         }
721         //we don't need the string anymore
722         free(stringConfig);
723         stringConfig = NULL;
724
725         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
726         if (!cJSON_IsObject(vesDetails))
727         {
728                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
729                 cJSON_Delete(jsonConfig);
730                 return SR_ERR_OPERATION_FAILED;
731         }
732
733         cJSON *vesReg = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
734         if (!cJSON_IsBool(vesReg))
735         {
736                 printf("Configuration JSON is not as expected: ves-registration is not an object");
737                 cJSON_Delete(jsonConfig);
738                 return SR_ERR_OPERATION_FAILED;
739         }
740
741         int is_ves_reg = (cJSON_IsTrue(vesReg)) ? TRUE : FALSE;
742
743         cJSON_Delete(jsonConfig);
744
745         return is_ves_reg;
746 }
747
748 /*
749  * Dynamically allocated memory;
750  * Caller needs to free the memory after it uses the value.
751  *
752 */
753 cJSON*  vesCreatePnfRegistrationFields(int port, bool is_tls)
754 {
755         cJSON *pnfRegistrationFields = cJSON_CreateObject();
756         if (pnfRegistrationFields == NULL)
757         {
758                 printf("Could not create JSON object: pnfRegistrationFields\n");
759                 return NULL;
760         }
761
762         if (cJSON_AddStringToObject(pnfRegistrationFields, "pnfRegistrationFieldsVersion", "2.0") == NULL)
763         {
764                 printf("Could not create JSON object: pnfRegistrationFieldsVersion\n");
765                 cJSON_Delete(pnfRegistrationFields);
766                 return NULL;
767         }
768
769         if (cJSON_AddStringToObject(pnfRegistrationFields, "lastServiceDate", "2019-08-16") == NULL)
770         {
771                 printf("Could not create JSON object: lastServiceDate\n");
772                 cJSON_Delete(pnfRegistrationFields);
773                 return NULL;
774         }
775
776         char mac_addr[40];
777         generateRandomMacAddress(mac_addr);
778
779         if (cJSON_AddStringToObject(pnfRegistrationFields, "macAddress", mac_addr) == NULL)
780         {
781                 printf("Could not create JSON object: macAddress\n");
782                 cJSON_Delete(pnfRegistrationFields);
783                 return NULL;
784         }
785
786         if (cJSON_AddStringToObject(pnfRegistrationFields, "manufactureDate", "2019-08-16") == NULL)
787         {
788                 printf("Could not create JSON object: manufactureDate\n");
789                 cJSON_Delete(pnfRegistrationFields);
790                 return NULL;
791         }
792
793         if (cJSON_AddStringToObject(pnfRegistrationFields, "modelNumber", "Simulated Device Melacon") == NULL)
794         {
795                 printf("Could not create JSON object: manufactureDate\n");
796                 cJSON_Delete(pnfRegistrationFields);
797                 return NULL;
798         }
799
800         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV4IpAddress", getenv("NTS_IP")) == NULL)
801         {
802                 printf("Could not create JSON object: oamV4IpAddress\n");
803                 cJSON_Delete(pnfRegistrationFields);
804                 return NULL;
805         }
806
807         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == NULL)
808         {
809                 printf("Could not create JSON object: oamV6IpAddress\n");
810                 cJSON_Delete(pnfRegistrationFields);
811                 return NULL;
812         }
813
814         char serial_number[100];
815         sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", getenv("HOSTNAME"), getenv("NTS_IP"), port);
816
817         if (cJSON_AddStringToObject(pnfRegistrationFields, "serialNumber", serial_number) == NULL)
818         {
819                 printf("Could not create JSON object: serialNumber\n");
820                 cJSON_Delete(pnfRegistrationFields);
821                 return NULL;
822         }
823
824         if (cJSON_AddStringToObject(pnfRegistrationFields, "softwareVersion", "2.3.5") == NULL)
825         {
826                 printf("Could not create JSON object: softwareVersion\n");
827                 cJSON_Delete(pnfRegistrationFields);
828                 return NULL;
829         }
830
831         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitFamily", "Simulated Device") == NULL)
832         {
833                 printf("Could not create JSON object: unitFamily\n");
834                 cJSON_Delete(pnfRegistrationFields);
835                 return NULL;
836         }
837
838         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitType", "O-RAN-sim") == NULL)
839         {
840                 printf("Could not create JSON object: unitType\n");
841                 cJSON_Delete(pnfRegistrationFields);
842                 return NULL;
843         }
844
845         if (cJSON_AddStringToObject(pnfRegistrationFields, "vendorName", "Melacon") == NULL)
846         {
847                 printf("Could not create JSON object: vendorName\n");
848                 cJSON_Delete(pnfRegistrationFields);
849                 return NULL;
850         }
851
852         cJSON *additionalFields = cJSON_CreateObject();
853         if (additionalFields == NULL)
854         {
855                 printf("Could not create JSON object: additionalFields\n");
856                 cJSON_Delete(pnfRegistrationFields);
857                 return NULL;
858         }
859         cJSON_AddItemToObject(pnfRegistrationFields, "additionalFields", additionalFields);
860
861         char portString[10];
862         sprintf(portString, "%d", port);
863
864         if (cJSON_AddStringToObject(additionalFields, "oamPort", portString) == NULL)
865         {
866                 printf("Could not create JSON object: oamPort\n");
867                 cJSON_Delete(pnfRegistrationFields);
868                 return NULL;
869         }
870
871         if (is_tls)
872         {
873                 //TLS specific configuration
874                 if (cJSON_AddStringToObject(additionalFields, "protocol", "TLS") == NULL)
875                 {
876                         printf("Could not create JSON object: protocol\n");
877                         cJSON_Delete(pnfRegistrationFields);
878                         return NULL;
879                 }
880
881                 //TODO here we have the username from the docker container hardcoded: netconf
882                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
883                 {
884                         printf("Could not create JSON object: username\n");
885                         cJSON_Delete(pnfRegistrationFields);
886                         return NULL;
887                 }
888
889                 if (cJSON_AddStringToObject(additionalFields, "keyId", "device-key") == NULL)
890                 {
891                         printf("Could not create JSON object: keyId\n");
892                         cJSON_Delete(pnfRegistrationFields);
893                         return NULL;
894                 }
895         }
896         else
897         {
898                 //SSH specific configuration
899                 if (cJSON_AddStringToObject(additionalFields, "protocol", "SSH") == NULL)
900                 {
901                         printf("Could not create JSON object: protocol\n");
902                         cJSON_Delete(pnfRegistrationFields);
903                         return NULL;
904                 }
905
906                 //TODO here we have the username from the docker container hardcoded: netconf
907                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
908                 {
909                         printf("Could not create JSON object: username\n");
910                         cJSON_Delete(pnfRegistrationFields);
911                         return NULL;
912                 }
913
914                 //TODO here we have the password from the docker container hardcoded: netconf
915                 if (cJSON_AddStringToObject(additionalFields, "password", "netconf") == NULL)
916                 {
917                         printf("Could not create JSON object: password\n");
918                         cJSON_Delete(pnfRegistrationFields);
919                         return NULL;
920                 }
921         }
922
923         if (cJSON_AddStringToObject(additionalFields, "reconnectOnChangedSchema", "false") == NULL)
924         {
925                 printf("Could not create JSON object: reconnectOnChangedSchema\n");
926                 cJSON_Delete(pnfRegistrationFields);
927                 return NULL;
928         }
929
930         if (cJSON_AddStringToObject(additionalFields, "sleep-factor", "1.5") == NULL)
931         {
932                 printf("Could not create JSON object: sleep-factor\n");
933                 cJSON_Delete(pnfRegistrationFields);
934                 return NULL;
935         }
936
937         if (cJSON_AddStringToObject(additionalFields, "tcpOnly", "false") == NULL)
938         {
939                 printf("Could not create JSON object: tcpOnly\n");
940                 cJSON_Delete(pnfRegistrationFields);
941                 return NULL;
942         }
943
944         if (cJSON_AddStringToObject(additionalFields, "connectionTimeout", "20000") == NULL)
945         {
946                 printf("Could not create JSON object: connectionTimeout\n");
947                 cJSON_Delete(pnfRegistrationFields);
948                 return NULL;
949         }
950
951         if (cJSON_AddStringToObject(additionalFields, "maxConnectionAttempts", "100") == NULL)
952         {
953                 printf("Could not create JSON object: maxConnectionAttempts\n");
954                 cJSON_Delete(pnfRegistrationFields);
955                 return NULL;
956         }
957
958         if (cJSON_AddStringToObject(additionalFields, "betweenAttemptsTimeout", "2000") == NULL)
959         {
960                 printf("Could not create JSON object: betweenAttemptsTimeout\n");
961                 cJSON_Delete(pnfRegistrationFields);
962                 return NULL;
963         }
964
965         if (cJSON_AddStringToObject(additionalFields, "keepaliveDelay", "120") == NULL)
966         {
967                 printf("Could not create JSON object: keepaliveDelay\n");
968                 cJSON_Delete(pnfRegistrationFields);
969                 return NULL;
970         }
971
972         return pnfRegistrationFields;
973 }
974
975 int     getNetconfAvailableFromConfigJson(void)
976 {
977         char *stringConfig = readConfigFileInString();
978
979         if (stringConfig == NULL)
980         {
981                 printf("Could not read JSON configuration file in string.");
982                 return 0;
983         }
984
985         cJSON *jsonConfig = cJSON_Parse(stringConfig);
986         if (jsonConfig == NULL)
987         {
988                 free(stringConfig);
989                 const char *error_ptr = cJSON_GetErrorPtr();
990                 if (error_ptr != NULL)
991                 {
992                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
993                 }
994                 return SR_ERR_OPERATION_FAILED;
995         }
996         //we don't need the string anymore
997         free(stringConfig);
998         stringConfig = NULL;
999
1000         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1001         if (!cJSON_IsObject(notifDetails))
1002         {
1003                 printf("Configuration JSON is not as expected: notification-config is not an object");
1004                 cJSON_Delete(jsonConfig);
1005                 return SR_ERR_OPERATION_FAILED;
1006         }
1007
1008         cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-netconf-available");
1009         if (!cJSON_IsBool(isNetconfAvailable))
1010         {
1011                 printf("Configuration JSON is not as expected: is-netconf-available is not an object");
1012                 cJSON_Delete(jsonConfig);
1013                 return SR_ERR_OPERATION_FAILED;
1014         }
1015
1016         int is_netconf_available = (cJSON_IsTrue(isNetconfAvailable)) ? TRUE : FALSE;
1017
1018         cJSON_Delete(jsonConfig);
1019
1020         return is_netconf_available;
1021 }
1022
1023 int     getVesAvailableFromConfigJson(void)
1024 {
1025         char *stringConfig = readConfigFileInString();
1026
1027         if (stringConfig == NULL)
1028         {
1029                 printf("Could not read JSON configuration file in string.");
1030                 return 0;
1031         }
1032
1033         cJSON *jsonConfig = cJSON_Parse(stringConfig);
1034         if (jsonConfig == NULL)
1035         {
1036                 free(stringConfig);
1037                 const char *error_ptr = cJSON_GetErrorPtr();
1038                 if (error_ptr != NULL)
1039                 {
1040                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1041                 }
1042                 return SR_ERR_OPERATION_FAILED;
1043         }
1044         //we don't need the string anymore
1045         free(stringConfig);
1046         stringConfig = NULL;
1047
1048         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1049         if (!cJSON_IsObject(notifDetails))
1050         {
1051                 printf("Configuration JSON is not as expected: notification-config is not an object");
1052                 cJSON_Delete(jsonConfig);
1053                 return SR_ERR_OPERATION_FAILED;
1054         }
1055
1056         cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-ves-available");
1057         if (!cJSON_IsBool(isVesAvailable))
1058         {
1059                 printf("Configuration JSON is not as expected: is-ves-available is not an object");
1060                 cJSON_Delete(jsonConfig);
1061                 return SR_ERR_OPERATION_FAILED;
1062         }
1063
1064         int is_netconf_available = (cJSON_IsTrue(isVesAvailable)) ? TRUE : FALSE;
1065
1066         cJSON_Delete(jsonConfig);
1067
1068         return is_netconf_available;
1069 }
1070
1071 /*
1072  * Dynamically allocated memory;
1073  * Caller needs to free the memory after it uses the value.
1074  *
1075 */
1076 cJSON*  vesCreateFaultFields(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem)
1077 {
1078         cJSON *faultFields = cJSON_CreateObject();
1079         if (faultFields == NULL)
1080         {
1081                 printf("Could not create JSON object: faultFields\n");
1082                 return NULL;
1083         }
1084
1085         if (cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == NULL)
1086         {
1087                 printf("Could not create JSON object: faultFieldsVersion\n");
1088                 cJSON_Delete(faultFields);
1089                 return NULL;
1090         }
1091
1092         if (cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == NULL)
1093         {
1094                 printf("Could not create JSON object: alarmCondition\n");
1095                 cJSON_Delete(faultFields);
1096                 return NULL;
1097         }
1098
1099         if (cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == NULL)
1100         {
1101                 printf("Could not create JSON object: alarmInterfaceA\n");
1102                 cJSON_Delete(faultFields);
1103                 return NULL;
1104         }
1105
1106         if (cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == NULL)
1107         {
1108                 printf("Could not create JSON object: eventSourceType\n");
1109                 cJSON_Delete(faultFields);
1110                 return NULL;
1111         }
1112
1113         if (cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == NULL)
1114         {
1115                 printf("Could not create JSON object: specificProblem\n");
1116                 cJSON_Delete(faultFields);
1117                 return NULL;
1118         }
1119
1120         if (cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == NULL)
1121         {
1122                 printf("Could not create JSON object: eventSeverity\n");
1123                 cJSON_Delete(faultFields);
1124                 return NULL;
1125         }
1126
1127         if (cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == NULL)
1128         {
1129                 printf("Could not create JSON object: vfStatus\n");
1130                 cJSON_Delete(faultFields);
1131                 return NULL;
1132         }
1133
1134         cJSON *alarmAdditionalInformation = cJSON_CreateObject();
1135         if (alarmAdditionalInformation == NULL)
1136         {
1137                 printf("Could not create JSON object: alarmAdditionalInformation\n");
1138                 cJSON_Delete(faultFields);
1139                 return NULL;
1140         }
1141         cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
1142
1143         if (cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == NULL)
1144         {
1145                 printf("Could not create JSON object: eventTime\n");
1146                 cJSON_Delete(faultFields);
1147                 return NULL;
1148         }
1149
1150         if (cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == NULL)
1151         {
1152                 printf("Could not create JSON object: equipType\n");
1153                 cJSON_Delete(faultFields);
1154                 return NULL;
1155         }
1156
1157         if (cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == NULL)
1158         {
1159                 printf("Could not create JSON object: vendor\n");
1160                 cJSON_Delete(faultFields);
1161                 return NULL;
1162         }
1163
1164         if (cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == NULL)
1165         {
1166                 printf("Could not create JSON object: model\n");
1167                 cJSON_Delete(faultFields);
1168                 return NULL;
1169         }
1170
1171         return faultFields;
1172 }