Configurable HTTP(S) support for VES messaging
[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 {
79     unsigned long
80         // max <= RAND_MAX < ULONG_MAX, so this is okay.
81         num_bins = (unsigned long) max + 1,
82         num_rand = (unsigned long) RAND_MAX + 1,
83         bin_size = num_rand / num_bins,
84         defect   = num_rand % num_bins;
85
86     unsigned int seed;
87     FILE* urandom = fopen("/dev/urandom", "r");
88     fread(&seed, sizeof(int), 1, urandom);
89     fclose(urandom);
90     srandom(seed);
91
92     long x;
93     do 
94     {
95         x = random();
96     }
97     // This is carefully written not to overflow
98     while (num_rand - defect <= (unsigned long)x);
99
100     // Truncated division is intentional
101     return x/bin_size;
102 }
103
104 int getSecondsFromLastQuarterInterval(void)
105 {
106         time_t t = time(NULL);
107         time_t t_past = time(NULL);
108         struct tm tm = *localtime(&t);
109         struct tm tm_15_min_ago = tm;
110
111         //round to the last quarter hour
112         tm_15_min_ago.tm_min -= (tm_15_min_ago.tm_min % 15);
113         tm_15_min_ago.tm_sec = 0;
114
115         t=mktime(&tm_15_min_ago);
116         t_past=mktime(&tm);
117
118         double seconds = difftime(t_past, t);
119
120         return (int)seconds;
121 }
122
123 int getSecondsFromLastDayInterval(void)
124 {
125         time_t t = time(NULL);
126         time_t t_past = time(NULL);
127         struct tm tm = *localtime(&t);
128         struct tm tm_day_ago = tm;
129
130         //round to the last quarter hour
131         tm_day_ago.tm_hour = 0;
132         tm_day_ago.tm_min = 0;
133         tm_day_ago.tm_sec = 0;
134
135         t=mktime(&tm_day_ago);
136         t_past=mktime(&tm);
137
138         double seconds = difftime(t_past, t);
139
140         return (int)seconds;
141 }
142
143 void getPreviousQuarterInterval(int number_of_intervals, char *date_and_time)
144 {
145         time_t t = time(NULL);
146         t -= 15 * 60 * number_of_intervals;
147         struct tm tm = *localtime(&t);
148
149         tm.tm_min -= (tm.tm_min % 15);
150         tm.tm_sec = 0;
151
152         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
153         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
154         tm.tm_hour, tm.tm_min, tm.tm_sec);
155
156         return;
157 }
158
159 void getPreviousDayPmTimestamp(int number_of_intervals, char *date_and_time)
160 {
161         time_t t = time(NULL);
162         t -= 24 * 60 * 60 * number_of_intervals;
163         struct tm tm = *localtime(&t);
164
165         tm.tm_hour = 0;
166         tm.tm_min = 0;
167         tm.tm_sec = 0;
168
169         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
170         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
171         tm.tm_hour, tm.tm_min, tm.tm_sec);
172
173         return;
174 }
175
176 long int getMicrosecondsSinceEpoch(void)
177 {
178         time_t t = time(NULL);
179         struct timeval tv;
180         long int useconds;
181
182         gettimeofday(&tv, NULL);
183         useconds = t*1000 + tv.tv_usec; //add the microseconds to the seconds
184
185         return useconds;
186 }
187
188 //TODO need to implement other authentication methods as well, not only no-auth
189 void prepare_ves_message_curl(CURL *curl)
190 {
191         curl_easy_reset(curl);
192         set_curl_common_info_ves(curl);
193
194         char *ves_ip = getVesIpFromConfigJson();
195         int ves_port = getVesPortFromConfigJson();
196     char *ves_auth_method = getVesAuthMethodFromConfigJson();
197     if (strcmp(ves_auth_method, "basic-auth") == 0)
198     {
199         char *ves_username = getVesUsernameFromConfigJson();
200         char *ves_password = getVesPasswordFromConfigJson();
201
202         char credentials[200];
203         sprintf(credentials, "%s:%s", ves_username, ves_password);
204
205         free(ves_username);
206         free(ves_password);
207
208         curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
209     }
210     free(ves_auth_method);
211
212         char url[300];
213         char ves_protocol[15] = "https";
214         if( !strcmp(getenv("VES_HTTPS"), "false")  )
215         {
216             strcpy(ves_protocol ,"http" );
217             printf("VES connection protocol %s enabled\n", ves_protocol);
218         }
219
220         sprintf(url, "%s://%s:%d/eventListener/v7", ves_protocol, ves_ip, ves_port);
221         curl_easy_setopt(curl, CURLOPT_URL, url);
222
223     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
224     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
225     curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
226     curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
227
228         free(ves_ip);
229
230         return;
231 }
232
233 /*
234  * Dynamically allocated memory;
235  * Caller needs to free the memory after it uses the value.
236  *
237 */
238 cJSON*  vesCreateCommonEventHeader(char *domain, char *event_type, char *source_name, int seq_id)
239 {
240         char dateAndTime[50];
241         getCurrentDateAndTime(dateAndTime);
242
243         long useconds = getMicrosecondsSinceEpoch();
244
245         cJSON *commonEventHeader = cJSON_CreateObject();
246         if (commonEventHeader == NULL)
247         {
248                 printf("Could not create JSON object: commonEventHeader\n");
249                 return NULL;
250         }
251
252         if (cJSON_AddStringToObject(commonEventHeader, "domain", domain) == NULL)
253         {
254                 printf("Could not create JSON object: domain\n");
255                 cJSON_Delete(commonEventHeader);
256                 return NULL;
257         }
258
259         char eventId[200];
260         sprintf(eventId, "%s_%s", source_name, dateAndTime);
261
262         if (cJSON_AddStringToObject(commonEventHeader, "eventId", eventId) == NULL)
263         {
264                 printf("Could not create JSON object: eventId\n");
265                 cJSON_Delete(commonEventHeader);
266                 return NULL;
267         }
268
269         char event_name[200];
270         sprintf(event_name, "%s_%s", domain, event_type);
271
272         if (cJSON_AddStringToObject(commonEventHeader, "eventName", event_name) == NULL)
273         {
274                 printf("Could not create JSON object: eventName\n");
275                 cJSON_Delete(commonEventHeader);
276                 return NULL;
277         }
278
279         if (cJSON_AddStringToObject(commonEventHeader, "eventType", event_type) == NULL)
280         {
281                 printf("Could not create JSON object: eventType\n");
282                 cJSON_Delete(commonEventHeader);
283                 return NULL;
284         }
285
286         if (cJSON_AddNumberToObject(commonEventHeader, "sequence", (double)(seq_id)) == NULL)
287         {
288                 printf("Could not create JSON object: sequence\n");
289                 cJSON_Delete(commonEventHeader);
290                 return NULL;
291         }
292
293         if (cJSON_AddStringToObject(commonEventHeader, "priority", "Low") == NULL)
294         {
295                 printf("Could not create JSON object: priority\n");
296                 cJSON_Delete(commonEventHeader);
297                 return NULL;
298         }
299
300         if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityId", "") == NULL)
301         {
302                 printf("Could not create JSON object: reportingEntityId\n");
303                 cJSON_Delete(commonEventHeader);
304                 return NULL;
305         }
306
307         if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityName", source_name) == NULL)
308         {
309                 printf("Could not create JSON object: reportingEntityName\n");
310                 cJSON_Delete(commonEventHeader);
311                 return NULL;
312         }
313
314         if (cJSON_AddStringToObject(commonEventHeader, "sourceId", "") == NULL)
315         {
316                 printf("Could not create JSON object: sourceId\n");
317                 cJSON_Delete(commonEventHeader);
318                 return NULL;
319         }
320
321         if (cJSON_AddStringToObject(commonEventHeader, "sourceName", source_name) == NULL)
322         {
323                 printf("Could not create JSON object: sourceName\n");
324                 cJSON_Delete(commonEventHeader);
325                 return NULL;
326         }
327
328         if (cJSON_AddNumberToObject(commonEventHeader, "startEpochMicrosec", (double)(useconds)) == NULL)
329         {
330                 printf("Could not create JSON object: startEpochMicrosec\n");
331                 cJSON_Delete(commonEventHeader);
332                 return NULL;
333         }
334
335         if (cJSON_AddNumberToObject(commonEventHeader, "lastEpochMicrosec", (double)(useconds)) == NULL)
336         {
337                 printf("Could not create JSON object: lastEpochMicrosec\n");
338                 cJSON_Delete(commonEventHeader);
339                 return NULL;
340         }
341
342         if (cJSON_AddStringToObject(commonEventHeader, "nfNamingCode", "sdn controller") == NULL)
343         {
344                 printf("Could not create JSON object: nfNamingCode\n");
345                 cJSON_Delete(commonEventHeader);
346                 return NULL;
347         }
348
349         if (cJSON_AddStringToObject(commonEventHeader, "nfVendorName", "sdn") == NULL)
350         {
351                 printf("Could not create JSON object: nfVendorName\n");
352                 cJSON_Delete(commonEventHeader);
353                 return NULL;
354         }
355
356         if (cJSON_AddStringToObject(commonEventHeader, "timeZoneOffset", "+00:00") == NULL)
357         {
358                 printf("Could not create JSON object: timeZoneOffset\n");
359                 cJSON_Delete(commonEventHeader);
360                 return NULL;
361         }
362
363         if (cJSON_AddStringToObject(commonEventHeader, "version", "4.0.1") == NULL)
364         {
365                 printf("Could not create JSON object: version\n");
366                 cJSON_Delete(commonEventHeader);
367                 return NULL;
368         }
369
370         if (cJSON_AddStringToObject(commonEventHeader, "vesEventListenerVersion", "7.0.1") == NULL)
371         {
372                 printf("Could not create JSON object: vesEventListenerVersion\n");
373                 cJSON_Delete(commonEventHeader);
374                 return NULL;
375         }
376
377         return commonEventHeader;
378 }
379
380 /*
381  * Dynamically allocated memory;
382  * Caller needs to free the memory after it uses the value.
383  *
384 */
385 cJSON*  vesCreateHeartbeatFields(int heartbeat_interval)
386 {
387         char dateAndTime[50];
388         getCurrentDateAndTime(dateAndTime);
389
390         cJSON *heartbeatFields = cJSON_CreateObject();
391         if (heartbeatFields == NULL)
392         {
393                 printf("Could not create JSON object: heartbeatFields\n");
394                 return NULL;
395         }
396
397         if (cJSON_AddStringToObject(heartbeatFields, "heartbeatFieldsVersion", "3.0") == NULL)
398         {
399                 printf("Could not create JSON object: heartbeatFieldsVersion\n");
400                 cJSON_Delete(heartbeatFields);
401                 return NULL;
402         }
403
404         if (cJSON_AddNumberToObject(heartbeatFields, "heartbeatInterval", (double)(heartbeat_interval)) == NULL)
405         {
406                 printf("Could not create JSON object: heartbeatInterval\n");
407                 cJSON_Delete(heartbeatFields);
408                 return NULL;
409         }
410
411         cJSON *additionalFields = cJSON_CreateObject();
412         if (additionalFields == NULL)
413         {
414                 printf("Could not create JSON object: additionalFields\n");
415                 cJSON_Delete(heartbeatFields);
416                 return NULL;
417         }
418         cJSON_AddItemToObject(heartbeatFields, "additionalFields", additionalFields);
419
420         if (cJSON_AddStringToObject(additionalFields, "eventTime", dateAndTime) == NULL)
421         {
422                 printf("Could not create JSON object: eventTime\n");
423                 cJSON_Delete(heartbeatFields);
424                 return NULL;
425         }
426
427         return heartbeatFields;
428 }
429
430 /*
431  * Dynamically allocated memory;
432  * Caller needs to free the memory after it uses the value.
433  *
434 */
435 char*   readConfigFileInString(void)
436 {
437         char * buffer = 0;
438         long length;
439         char config_file[200];
440
441         //sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
442
443         // --> recommended fix, Karl Koch, Deutsche Telekom AG, 22. 5. 2020.
444         //     Path to config_file contains NULL when env variable is unset.
445         char *scripts_dir = getenv("SCRIPTS_DIR");
446         char *scripts_dir_default = "/opt/dev/ntsimulator/scripts";
447
448         if(NULL != scripts_dir)
449         {
450         sprintf(config_file, "%s/configuration.json", scripts_dir);
451         }
452         else
453         {
454         sprintf(config_file, "%s/configuration.json", scripts_dir_default);
455             printf("warning: opening config file in default path: <%s>\n",
456                    config_file);
457         }
458         // end of fix <--
459
460         FILE * f = fopen (config_file, "rb");
461
462         if (f)
463         {
464           fseek (f, 0, SEEK_END);
465           length = ftell (f);
466           fseek (f, 0, SEEK_SET);
467           buffer = malloc (length + 1);
468           if (buffer)
469           {
470             fread (buffer, 1, length, f);
471           }
472           fclose (f);
473           buffer[length] = '\0';
474         }
475
476         if (buffer)
477         {
478           return buffer;
479         }
480
481         return NULL;
482 }
483
484 void    writeConfigFile(char *config)
485 {
486         char config_file[200];
487
488         //sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
489
490         // --> recommended fix, Karl Koch, Deutsche Telekom AG, 22. 5. 2020.
491         //     Path to config_file contains NULL when env variable is unset.
492         char *scripts_dir = getenv("SCRIPTS_DIR");
493         char *scripts_dir_default = "/opt/dev/ntsimulator/scripts";
494
495         if(NULL != scripts_dir)
496         {
497         sprintf(config_file, "%s/configuration.json", scripts_dir);
498         }
499         else
500         {
501         sprintf(config_file, "%s/configuration.json", scripts_dir_default);
502         printf("warning: opening config file in default path: <%s>\n",
503                    config_file);
504         }
505         // end of fix <--
506
507         FILE * f = fopen (config_file, "w");
508
509         if (f)
510         {
511                 fputs(config, f);
512                 fclose(f);
513         }
514         else
515         {
516                 printf("Could not write configuration file");
517         }
518 }
519
520 int getFaultNotificationDelayPeriodFromConfigJson(int *period_array, int *count)
521 {
522         char *stringConfig = readConfigFileInString();
523
524         if (stringConfig == NULL)
525         {
526                 printf("Could not read JSON configuration file in string.");
527                 return 0;
528         }
529
530         cJSON *jsonConfig = cJSON_Parse(stringConfig);
531         if (jsonConfig == NULL)
532         {
533                 free(stringConfig);
534                 const char *error_ptr = cJSON_GetErrorPtr();
535                 if (error_ptr != NULL)
536                 {
537                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
538                 }
539                 return SR_ERR_OPERATION_FAILED;
540         }
541         //we don't need the string anymore
542         free(stringConfig);
543         stringConfig = NULL;
544
545         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
546         if (!cJSON_IsObject(notifConfig))
547         {
548                 printf("Configuration JSON is not as expected: notification-config is not an object");
549                 cJSON_Delete(jsonConfig);
550                 return SR_ERR_OPERATION_FAILED;
551         }
552
553         cJSON *faultNotifDelay = cJSON_GetObjectItemCaseSensitive(notifConfig, "fault-notification-delay-period");
554         if (!cJSON_IsArray(faultNotifDelay))
555         {
556                 printf("Configuration JSON is not as expected: fault-notification-delay-period is not an array.");
557                 cJSON_Delete(jsonConfig);
558                 return SR_ERR_OPERATION_FAILED;
559         }
560
561     cJSON *iterator = NULL;
562     *count = 0;
563     int i = 0;
564
565     cJSON_ArrayForEach(iterator, faultNotifDelay) 
566     {
567         if (cJSON_IsNumber(iterator)) 
568         {
569             period_array[i++] = iterator->valueint;
570         } 
571         else 
572         {
573             printf("Invalid number in array!");
574         }
575     }
576
577     *count = i;
578
579         cJSON_Delete(jsonConfig);
580
581         return SR_ERR_OK;
582 }
583
584 int     getVesHeartbeatPeriodFromConfigJson(void)
585 {
586         char *stringConfig = readConfigFileInString();
587         int vesHeartbeat = 0;
588
589         if (stringConfig == NULL)
590         {
591                 printf("Could not read JSON configuration file in string.");
592                 return 0;
593         }
594
595         cJSON *jsonConfig = cJSON_Parse(stringConfig);
596         if (jsonConfig == NULL)
597         {
598                 free(stringConfig);
599                 const char *error_ptr = cJSON_GetErrorPtr();
600                 if (error_ptr != NULL)
601                 {
602                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
603                 }
604                 return SR_ERR_OPERATION_FAILED;
605         }
606         //we don't need the string anymore
607         free(stringConfig);
608         stringConfig = NULL;
609
610         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
611         if (!cJSON_IsObject(notifConfig))
612         {
613                 printf("Configuration JSON is not as expected: notification-config is not an object");
614                 cJSON_Delete(jsonConfig);
615                 return SR_ERR_OPERATION_FAILED;
616         }
617
618         cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
619         if (!cJSON_IsNumber(vesHeartbeatPeriod))
620         {
621                 printf("Configuration JSON is not as expected: ves-heartbeat-period is not a number");
622                 cJSON_Delete(jsonConfig);
623                 return SR_ERR_OPERATION_FAILED;
624         }
625
626         vesHeartbeat = (int)(vesHeartbeatPeriod->valuedouble);
627
628         cJSON_Delete(jsonConfig);
629
630         return vesHeartbeat;
631 }
632
633
634 /*
635  * Dynamically allocated memory;
636  * Caller needs to free the memory after it uses the value.
637  *
638 */
639 char*   getVesAuthMethodFromConfigJson(void)
640 {
641         char *stringConfig = readConfigFileInString();
642
643         if (stringConfig == NULL)
644         {
645                 printf("Could not read JSON configuration file in string.");
646                 return 0;
647         }
648
649         cJSON *jsonConfig = cJSON_Parse(stringConfig);
650         if (jsonConfig == NULL)
651         {
652                 free(stringConfig);
653                 const char *error_ptr = cJSON_GetErrorPtr();
654                 if (error_ptr != NULL)
655                 {
656                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
657                 }
658                 return NULL;
659         }
660         //we don't need the string anymore
661         free(stringConfig);
662         stringConfig = NULL;
663
664         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
665         if (!cJSON_IsObject(vesDetails))
666         {
667                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
668                 cJSON_Delete(jsonConfig);
669                 return NULL;
670         }
671
672         cJSON *vesAuthMethod = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-auth-method");
673         if (!cJSON_IsString(vesAuthMethod))
674         {
675                 printf("Configuration JSON is not as expected: ves-endpoint-auth-method is not an object");
676                 cJSON_Delete(jsonConfig);
677                 return NULL;
678         }
679
680         char *auth_method_string = strdup(cJSON_GetStringValue(vesAuthMethod));
681
682         cJSON_Delete(jsonConfig);
683
684         return auth_method_string;
685 }
686
687 /*
688  * Dynamically allocated memory;
689  * Caller needs to free the memory after it uses the value.
690  *
691 */
692 char*   getVesIpFromConfigJson(void)
693 {
694     char *stringConfig = readConfigFileInString();
695
696     if (stringConfig == NULL)
697     {
698         printf("Could not read JSON configuration file in string.");
699         return 0;
700     }
701
702     cJSON *jsonConfig = cJSON_Parse(stringConfig);
703     if (jsonConfig == NULL)
704     {
705         free(stringConfig);
706         const char *error_ptr = cJSON_GetErrorPtr();
707         if (error_ptr != NULL)
708         {
709             fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
710         }
711         return NULL;
712     }
713     //we don't need the string anymore
714     free(stringConfig);
715     stringConfig = NULL;
716
717     cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
718     if (!cJSON_IsObject(vesDetails))
719     {
720         printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
721         cJSON_Delete(jsonConfig);
722         return NULL;
723     }
724
725     cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
726     if (!cJSON_IsString(vesIp))
727     {
728         printf("Configuration JSON is not as expected: ves-endpoint-ip is not an object");
729         cJSON_Delete(jsonConfig);
730         return NULL;
731     }
732
733     char *ves_ip = strdup(cJSON_GetStringValue(vesIp));
734
735     cJSON_Delete(jsonConfig);
736
737     return ves_ip;
738 }
739
740 /*
741  * Dynamically allocated memory;
742  * Caller needs to free the memory after it uses the value.
743  *
744 */
745 char*   getVesUsernameFromConfigJson(void)
746 {
747     char *stringConfig = readConfigFileInString();
748
749     if (stringConfig == NULL)
750     {
751         printf("Could not read JSON configuration file in string.");
752         return 0;
753     }
754
755     cJSON *jsonConfig = cJSON_Parse(stringConfig);
756     if (jsonConfig == NULL)
757     {
758         free(stringConfig);
759         const char *error_ptr = cJSON_GetErrorPtr();
760         if (error_ptr != NULL)
761         {
762             fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
763         }
764         return NULL;
765     }
766     //we don't need the string anymore
767     free(stringConfig);
768     stringConfig = NULL;
769
770     cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
771     if (!cJSON_IsObject(vesDetails))
772     {
773         printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
774         cJSON_Delete(jsonConfig);
775         return NULL;
776     }
777
778     cJSON *vesUsername = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-username");
779     if (!cJSON_IsString(vesUsername))
780     {
781         printf("Configuration JSON is not as expected: ves-endpoint-username is not an object");
782         cJSON_Delete(jsonConfig);
783         return NULL;
784     }
785
786     char *ves_username = strdup(cJSON_GetStringValue(vesUsername));
787
788     cJSON_Delete(jsonConfig);
789
790     return ves_username;
791 }
792
793 /*
794  * Dynamically allocated memory;
795  * Caller needs to free the memory after it uses the value.
796  *
797 */
798 char*   getVesPasswordFromConfigJson(void)
799 {
800     char *stringConfig = readConfigFileInString();
801
802     if (stringConfig == NULL)
803     {
804         printf("Could not read JSON configuration file in string.");
805         return 0;
806     }
807
808     cJSON *jsonConfig = cJSON_Parse(stringConfig);
809     if (jsonConfig == NULL)
810     {
811         free(stringConfig);
812         const char *error_ptr = cJSON_GetErrorPtr();
813         if (error_ptr != NULL)
814         {
815             fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
816         }
817         return NULL;
818     }
819     //we don't need the string anymore
820     free(stringConfig);
821     stringConfig = NULL;
822
823     cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
824     if (!cJSON_IsObject(vesDetails))
825     {
826         printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
827         cJSON_Delete(jsonConfig);
828         return NULL;
829     }
830
831     cJSON *vesPassword = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-password");
832     if (!cJSON_IsString(vesPassword))
833     {
834         printf("Configuration JSON is not as expected: ves-endpoint-password is not an object");
835         cJSON_Delete(jsonConfig);
836         return NULL;
837     }
838
839     char *ves_password = strdup(cJSON_GetStringValue(vesPassword));
840
841     cJSON_Delete(jsonConfig);
842
843     return ves_password;
844 }
845
846 int     getVesPortFromConfigJson(void)
847 {
848         char *stringConfig = readConfigFileInString();
849
850         if (stringConfig == NULL)
851         {
852                 printf("Could not read JSON configuration file in string.");
853                 return 0;
854         }
855
856         cJSON *jsonConfig = cJSON_Parse(stringConfig);
857         if (jsonConfig == NULL)
858         {
859                 free(stringConfig);
860                 const char *error_ptr = cJSON_GetErrorPtr();
861                 if (error_ptr != NULL)
862                 {
863                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
864                 }
865                 return SR_ERR_OPERATION_FAILED;
866         }
867         //we don't need the string anymore
868         free(stringConfig);
869         stringConfig = NULL;
870
871         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
872         if (!cJSON_IsObject(vesDetails))
873         {
874                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
875                 cJSON_Delete(jsonConfig);
876                 return SR_ERR_OPERATION_FAILED;
877         }
878
879         cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
880         if (!cJSON_IsNumber(vesPort))
881         {
882                 printf("Configuration JSON is not as expected: ves-endpoint-port is not an object");
883                 cJSON_Delete(jsonConfig);
884                 return SR_ERR_OPERATION_FAILED;
885         }
886
887         int port = (int)(vesPort->valuedouble);
888
889         cJSON_Delete(jsonConfig);
890
891         return port;
892 }
893
894 int     getVesRegistrationFromConfigJson(void)
895 {
896         char *stringConfig = readConfigFileInString();
897
898         if (stringConfig == NULL)
899         {
900                 printf("Could not read JSON configuration file in string.");
901                 return 0;
902         }
903
904         cJSON *jsonConfig = cJSON_Parse(stringConfig);
905         if (jsonConfig == NULL)
906         {
907                 free(stringConfig);
908                 const char *error_ptr = cJSON_GetErrorPtr();
909                 if (error_ptr != NULL)
910                 {
911                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
912                 }
913                 return SR_ERR_OPERATION_FAILED;
914         }
915         //we don't need the string anymore
916         free(stringConfig);
917         stringConfig = NULL;
918
919         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
920         if (!cJSON_IsObject(vesDetails))
921         {
922                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
923                 cJSON_Delete(jsonConfig);
924                 return SR_ERR_OPERATION_FAILED;
925         }
926
927         cJSON *vesReg = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
928         if (!cJSON_IsBool(vesReg))
929         {
930                 printf("Configuration JSON is not as expected: ves-registration is not an object");
931                 cJSON_Delete(jsonConfig);
932                 return SR_ERR_OPERATION_FAILED;
933         }
934
935         int is_ves_reg = (cJSON_IsTrue(vesReg)) ? TRUE : FALSE;
936
937         cJSON_Delete(jsonConfig);
938
939         return is_ves_reg;
940 }
941
942 /*
943  * Dynamically allocated memory;
944  * Caller needs to free the memory after it uses the value.
945  *
946 */
947 cJSON*  vesCreatePnfRegistrationFields(int port, bool is_tls)
948 {
949         cJSON *pnfRegistrationFields = cJSON_CreateObject();
950         if (pnfRegistrationFields == NULL)
951         {
952                 printf("Could not create JSON object: pnfRegistrationFields\n");
953                 return NULL;
954         }
955
956         if (cJSON_AddStringToObject(pnfRegistrationFields, "pnfRegistrationFieldsVersion", "2.0") == NULL)
957         {
958                 printf("Could not create JSON object: pnfRegistrationFieldsVersion\n");
959                 cJSON_Delete(pnfRegistrationFields);
960                 return NULL;
961         }
962
963         if (cJSON_AddStringToObject(pnfRegistrationFields, "lastServiceDate", "2019-08-16") == NULL)
964         {
965                 printf("Could not create JSON object: lastServiceDate\n");
966                 cJSON_Delete(pnfRegistrationFields);
967                 return NULL;
968         }
969
970         char mac_addr[40];
971         generateRandomMacAddress(mac_addr);
972
973         if (cJSON_AddStringToObject(pnfRegistrationFields, "macAddress", mac_addr) == NULL)
974         {
975                 printf("Could not create JSON object: macAddress\n");
976                 cJSON_Delete(pnfRegistrationFields);
977                 return NULL;
978         }
979
980         if (cJSON_AddStringToObject(pnfRegistrationFields, "manufactureDate", "2019-08-16") == NULL)
981         {
982                 printf("Could not create JSON object: manufactureDate\n");
983                 cJSON_Delete(pnfRegistrationFields);
984                 return NULL;
985         }
986
987         if (cJSON_AddStringToObject(pnfRegistrationFields, "modelNumber", "Simulated Device Melacon") == NULL)
988         {
989                 printf("Could not create JSON object: manufactureDate\n");
990                 cJSON_Delete(pnfRegistrationFields);
991                 return NULL;
992         }
993
994         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV4IpAddress", getenv("EXTERNAL_NTS_IP")) == NULL)
995         {
996                 printf("Could not create JSON object: oamV4IpAddress\n");
997                 cJSON_Delete(pnfRegistrationFields);
998                 return NULL;
999         }
1000
1001         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == NULL)
1002         {
1003                 printf("Could not create JSON object: oamV6IpAddress\n");
1004                 cJSON_Delete(pnfRegistrationFields);
1005                 return NULL;
1006         }
1007
1008         char serial_number[100];
1009         sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", getenv("HOSTNAME"), getenv("EXTERNAL_NTS_IP"), port);
1010
1011         if (cJSON_AddStringToObject(pnfRegistrationFields, "serialNumber", serial_number) == NULL)
1012         {
1013                 printf("Could not create JSON object: serialNumber\n");
1014                 cJSON_Delete(pnfRegistrationFields);
1015                 return NULL;
1016         }
1017
1018         if (cJSON_AddStringToObject(pnfRegistrationFields, "softwareVersion", "2.3.5") == NULL)
1019         {
1020                 printf("Could not create JSON object: softwareVersion\n");
1021                 cJSON_Delete(pnfRegistrationFields);
1022                 return NULL;
1023         }
1024
1025         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitFamily", "Simulated Device") == NULL)
1026         {
1027                 printf("Could not create JSON object: unitFamily\n");
1028                 cJSON_Delete(pnfRegistrationFields);
1029                 return NULL;
1030         }
1031
1032         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitType", "O-RAN-sim") == NULL)
1033         {
1034                 printf("Could not create JSON object: unitType\n");
1035                 cJSON_Delete(pnfRegistrationFields);
1036                 return NULL;
1037         }
1038
1039         if (cJSON_AddStringToObject(pnfRegistrationFields, "vendorName", "Melacon") == NULL)
1040         {
1041                 printf("Could not create JSON object: vendorName\n");
1042                 cJSON_Delete(pnfRegistrationFields);
1043                 return NULL;
1044         }
1045
1046         cJSON *additionalFields = cJSON_CreateObject();
1047         if (additionalFields == NULL)
1048         {
1049                 printf("Could not create JSON object: additionalFields\n");
1050                 cJSON_Delete(pnfRegistrationFields);
1051                 return NULL;
1052         }
1053         cJSON_AddItemToObject(pnfRegistrationFields, "additionalFields", additionalFields);
1054
1055         char portString[10];
1056         sprintf(portString, "%d", port);
1057
1058         if (cJSON_AddStringToObject(additionalFields, "oamPort", portString) == NULL)
1059         {
1060                 printf("Could not create JSON object: oamPort\n");
1061                 cJSON_Delete(pnfRegistrationFields);
1062                 return NULL;
1063         }
1064
1065         if (is_tls)
1066         {
1067                 //TLS specific configuration
1068                 if (cJSON_AddStringToObject(additionalFields, "protocol", "TLS") == NULL)
1069                 {
1070                         printf("Could not create JSON object: protocol\n");
1071                         cJSON_Delete(pnfRegistrationFields);
1072                         return NULL;
1073                 }
1074
1075                 //TODO here we have the username from the docker container hardcoded: netconf
1076                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
1077                 {
1078                         printf("Could not create JSON object: username\n");
1079                         cJSON_Delete(pnfRegistrationFields);
1080                         return NULL;
1081                 }
1082
1083                 if (cJSON_AddStringToObject(additionalFields, "keyId", "device-key") == NULL)
1084                 {
1085                         printf("Could not create JSON object: keyId\n");
1086                         cJSON_Delete(pnfRegistrationFields);
1087                         return NULL;
1088                 }
1089         }
1090         else
1091         {
1092                 //SSH specific configuration
1093                 if (cJSON_AddStringToObject(additionalFields, "protocol", "SSH") == NULL)
1094                 {
1095                         printf("Could not create JSON object: protocol\n");
1096                         cJSON_Delete(pnfRegistrationFields);
1097                         return NULL;
1098                 }
1099
1100                 //TODO here we have the username from the docker container hardcoded: netconf
1101                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
1102                 {
1103                         printf("Could not create JSON object: username\n");
1104                         cJSON_Delete(pnfRegistrationFields);
1105                         return NULL;
1106                 }
1107
1108                 //TODO here we have the password from the docker container hardcoded: netconf
1109                 if (cJSON_AddStringToObject(additionalFields, "password", "netconf") == NULL)
1110                 {
1111                         printf("Could not create JSON object: password\n");
1112                         cJSON_Delete(pnfRegistrationFields);
1113                         return NULL;
1114                 }
1115         }
1116
1117         if (cJSON_AddStringToObject(additionalFields, "reconnectOnChangedSchema", "false") == NULL)
1118         {
1119                 printf("Could not create JSON object: reconnectOnChangedSchema\n");
1120                 cJSON_Delete(pnfRegistrationFields);
1121                 return NULL;
1122         }
1123
1124         if (cJSON_AddStringToObject(additionalFields, "sleep-factor", "1.5") == NULL)
1125         {
1126                 printf("Could not create JSON object: sleep-factor\n");
1127                 cJSON_Delete(pnfRegistrationFields);
1128                 return NULL;
1129         }
1130
1131         if (cJSON_AddStringToObject(additionalFields, "tcpOnly", "false") == NULL)
1132         {
1133                 printf("Could not create JSON object: tcpOnly\n");
1134                 cJSON_Delete(pnfRegistrationFields);
1135                 return NULL;
1136         }
1137
1138         if (cJSON_AddStringToObject(additionalFields, "connectionTimeout", "20000") == NULL)
1139         {
1140                 printf("Could not create JSON object: connectionTimeout\n");
1141                 cJSON_Delete(pnfRegistrationFields);
1142                 return NULL;
1143         }
1144
1145         if (cJSON_AddStringToObject(additionalFields, "maxConnectionAttempts", "100") == NULL)
1146         {
1147                 printf("Could not create JSON object: maxConnectionAttempts\n");
1148                 cJSON_Delete(pnfRegistrationFields);
1149                 return NULL;
1150         }
1151
1152         if (cJSON_AddStringToObject(additionalFields, "betweenAttemptsTimeout", "2000") == NULL)
1153         {
1154                 printf("Could not create JSON object: betweenAttemptsTimeout\n");
1155                 cJSON_Delete(pnfRegistrationFields);
1156                 return NULL;
1157         }
1158
1159         if (cJSON_AddStringToObject(additionalFields, "keepaliveDelay", "120") == NULL)
1160         {
1161                 printf("Could not create JSON object: keepaliveDelay\n");
1162                 cJSON_Delete(pnfRegistrationFields);
1163                 return NULL;
1164         }
1165
1166         return pnfRegistrationFields;
1167 }
1168
1169 int     getNetconfAvailableFromConfigJson(void)
1170 {
1171         char *stringConfig = readConfigFileInString();
1172
1173         if (stringConfig == NULL)
1174         {
1175                 printf("Could not read JSON configuration file in string.");
1176                 return 0;
1177         }
1178
1179         cJSON *jsonConfig = cJSON_Parse(stringConfig);
1180         if (jsonConfig == NULL)
1181         {
1182                 free(stringConfig);
1183                 const char *error_ptr = cJSON_GetErrorPtr();
1184                 if (error_ptr != NULL)
1185                 {
1186                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1187                 }
1188                 return SR_ERR_OPERATION_FAILED;
1189         }
1190         //we don't need the string anymore
1191         free(stringConfig);
1192         stringConfig = NULL;
1193
1194         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1195         if (!cJSON_IsObject(notifDetails))
1196         {
1197                 printf("Configuration JSON is not as expected: notification-config is not an object");
1198                 cJSON_Delete(jsonConfig);
1199                 return SR_ERR_OPERATION_FAILED;
1200         }
1201
1202         cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-netconf-available");
1203         if (!cJSON_IsBool(isNetconfAvailable))
1204         {
1205                 printf("Configuration JSON is not as expected: is-netconf-available is not an object");
1206                 cJSON_Delete(jsonConfig);
1207                 return SR_ERR_OPERATION_FAILED;
1208         }
1209
1210         int is_netconf_available = (cJSON_IsTrue(isNetconfAvailable)) ? TRUE : FALSE;
1211
1212         cJSON_Delete(jsonConfig);
1213
1214         return is_netconf_available;
1215 }
1216
1217 int     getVesAvailableFromConfigJson(void)
1218 {
1219         char *stringConfig = readConfigFileInString();
1220
1221         if (stringConfig == NULL)
1222         {
1223                 printf("Could not read JSON configuration file in string.");
1224                 return 0;
1225         }
1226
1227         cJSON *jsonConfig = cJSON_Parse(stringConfig);
1228         if (jsonConfig == NULL)
1229         {
1230                 free(stringConfig);
1231                 const char *error_ptr = cJSON_GetErrorPtr();
1232                 if (error_ptr != NULL)
1233                 {
1234                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1235                 }
1236                 return SR_ERR_OPERATION_FAILED;
1237         }
1238         //we don't need the string anymore
1239         free(stringConfig);
1240         stringConfig = NULL;
1241
1242         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1243         if (!cJSON_IsObject(notifDetails))
1244         {
1245                 printf("Configuration JSON is not as expected: notification-config is not an object");
1246                 cJSON_Delete(jsonConfig);
1247                 return SR_ERR_OPERATION_FAILED;
1248         }
1249
1250         cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-ves-available");
1251         if (!cJSON_IsBool(isVesAvailable))
1252         {
1253                 printf("Configuration JSON is not as expected: is-ves-available is not an object");
1254                 cJSON_Delete(jsonConfig);
1255                 return SR_ERR_OPERATION_FAILED;
1256         }
1257
1258         int is_netconf_available = (cJSON_IsTrue(isVesAvailable)) ? TRUE : FALSE;
1259
1260         cJSON_Delete(jsonConfig);
1261
1262         return is_netconf_available;
1263 }
1264
1265 /*
1266  * Dynamically allocated memory;
1267  * Caller needs to free the memory after it uses the value.
1268  *
1269 */
1270 cJSON*  vesCreateFaultFields(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem)
1271 {
1272         cJSON *faultFields = cJSON_CreateObject();
1273         if (faultFields == NULL)
1274         {
1275                 printf("Could not create JSON object: faultFields\n");
1276                 return NULL;
1277         }
1278
1279         if (cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == NULL)
1280         {
1281                 printf("Could not create JSON object: faultFieldsVersion\n");
1282                 cJSON_Delete(faultFields);
1283                 return NULL;
1284         }
1285
1286         if (cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == NULL)
1287         {
1288                 printf("Could not create JSON object: alarmCondition\n");
1289                 cJSON_Delete(faultFields);
1290                 return NULL;
1291         }
1292
1293         if (cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == NULL)
1294         {
1295                 printf("Could not create JSON object: alarmInterfaceA\n");
1296                 cJSON_Delete(faultFields);
1297                 return NULL;
1298         }
1299
1300         if (cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == NULL)
1301         {
1302                 printf("Could not create JSON object: eventSourceType\n");
1303                 cJSON_Delete(faultFields);
1304                 return NULL;
1305         }
1306
1307         if (cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == NULL)
1308         {
1309                 printf("Could not create JSON object: specificProblem\n");
1310                 cJSON_Delete(faultFields);
1311                 return NULL;
1312         }
1313
1314         if (cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == NULL)
1315         {
1316                 printf("Could not create JSON object: eventSeverity\n");
1317                 cJSON_Delete(faultFields);
1318                 return NULL;
1319         }
1320
1321         if (cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == NULL)
1322         {
1323                 printf("Could not create JSON object: vfStatus\n");
1324                 cJSON_Delete(faultFields);
1325                 return NULL;
1326         }
1327
1328         cJSON *alarmAdditionalInformation = cJSON_CreateObject();
1329         if (alarmAdditionalInformation == NULL)
1330         {
1331                 printf("Could not create JSON object: alarmAdditionalInformation\n");
1332                 cJSON_Delete(faultFields);
1333                 return NULL;
1334         }
1335         cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
1336
1337         if (cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == NULL)
1338         {
1339                 printf("Could not create JSON object: eventTime\n");
1340                 cJSON_Delete(faultFields);
1341                 return NULL;
1342         }
1343
1344         if (cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == NULL)
1345         {
1346                 printf("Could not create JSON object: equipType\n");
1347                 cJSON_Delete(faultFields);
1348                 return NULL;
1349         }
1350
1351         if (cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == NULL)
1352         {
1353                 printf("Could not create JSON object: vendor\n");
1354                 cJSON_Delete(faultFields);
1355                 return NULL;
1356         }
1357
1358         if (cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == NULL)
1359         {
1360                 printf("Could not create JSON object: model\n");
1361                 cJSON_Delete(faultFields);
1362                 return NULL;
1363         }
1364
1365         return faultFields;
1366 }
1367
1368 static cJSON* createSeverityCounters(counterAlarms count)
1369 {
1370     cJSON *severityCounters = cJSON_CreateObject();
1371     if (severityCounters == NULL)
1372     {
1373         printf("Could not create JSON object: severityCounters\n");
1374         return NULL;
1375     }
1376
1377     if (cJSON_AddNumberToObject(severityCounters, "severity-normal", count.normal) == NULL)
1378     {
1379         printf("Could not create JSON object: severity-normal\n");
1380         return NULL;
1381     }
1382
1383     if (cJSON_AddNumberToObject(severityCounters, "severity-warning", count.warning) == NULL)
1384     {
1385         printf("Could not create JSON object: severity-warning\n");
1386         return NULL;
1387     }
1388
1389     if (cJSON_AddNumberToObject(severityCounters, "severity-minor", count.minor) == NULL)
1390     {
1391         printf("Could not create JSON object: severity-minor\n");
1392         return NULL;
1393     }
1394
1395     if (cJSON_AddNumberToObject(severityCounters, "severity-major", count.major) == NULL)
1396     {
1397         printf("Could not create JSON object: severity-major\n");
1398         return NULL;
1399     }
1400
1401     if (cJSON_AddNumberToObject(severityCounters, "severity-critical", count.critical) == NULL)
1402     {
1403         printf("Could not create JSON object: severity-critical\n");
1404         return NULL;
1405     }
1406
1407     return severityCounters;
1408 }
1409
1410 void writeStatusFile(char *status)
1411 {
1412         char status_file[200];
1413         sprintf(status_file, "%s/status.json", getenv("SCRIPTS_DIR"));
1414         FILE * f = fopen (status_file, "w");
1415
1416         if (f)
1417         {
1418                 fputs(status, f);
1419                 fclose(f);
1420         }
1421         else
1422         {
1423                 printf("Could not write status file!\n");
1424         }
1425 }
1426
1427 int     writeSkeletonStatusFile()
1428 {
1429     cJSON *statusObject = cJSON_CreateObject();
1430     if (statusObject == NULL)
1431     {
1432         printf("Could not create JSON object: statusObject\n");
1433         return SR_ERR_OPERATION_FAILED;
1434     }
1435
1436     // counterAlarms counter = {
1437     //     .normal = 0,
1438     //     .warning = 0,
1439     //     .minor = 0,
1440     //     .major = 0,
1441     //     .critical = 0
1442     // };
1443
1444     // cJSON *totalVesNotifications = createSeverityCounters(counter);
1445     // if (totalVesNotifications == NULL)
1446     // {
1447     //     printf("Could not create JSON object: totalVesNotifications\n");
1448     //     cJSON_Delete(statusObject);
1449     //     return SR_ERR_OPERATION_FAILED;
1450     // }
1451     // cJSON_AddItemToObject(statusObject, "total-ves-notifications-sent", totalVesNotifications);
1452
1453     // cJSON *totalNetconfNotifications = createSeverityCounters(counter);
1454     // if (totalNetconfNotifications == NULL)
1455     // {
1456     //     printf("Could not create JSON object: totalNetconfNotifications\n");
1457     //     cJSON_Delete(statusObject);
1458     //     return SR_ERR_OPERATION_FAILED;
1459     // }
1460     // cJSON_AddItemToObject(statusObject, "total-netconf-notifications-sent", totalNetconfNotifications);
1461
1462     cJSON *deviceList = cJSON_CreateArray();
1463     if (deviceList == NULL)
1464     {
1465         printf("Could not create JSON object: deviceList\n");
1466         cJSON_Delete(statusObject);
1467         return SR_ERR_OPERATION_FAILED;
1468         }
1469     cJSON_AddItemToObject(statusObject, "device-list", deviceList);
1470
1471     char *status_string = NULL;
1472
1473     status_string = cJSON_PrintUnformatted(statusObject);
1474
1475     writeStatusFile(status_string);
1476
1477     if (status_string != NULL)
1478     {
1479         free(status_string);
1480         status_string = NULL;
1481     }
1482
1483     if (statusObject != NULL)
1484     {
1485             cJSON_Delete(statusObject);
1486     }
1487
1488     return SR_ERR_OK;
1489 }
1490
1491 /*
1492  * Dynamically allocated memory;
1493  * Caller needs to free the memory after it uses the value.
1494  *
1495 */
1496 char*   readStatusFileInString(void)
1497 {
1498         char * buffer = 0;
1499         long length;
1500         char config_file[200];
1501         sprintf(config_file, "%s/status.json", getenv("SCRIPTS_DIR"));
1502         FILE * f = fopen (config_file, "rb");
1503
1504         if (f)
1505         {
1506           fseek (f, 0, SEEK_END);
1507           length = ftell (f);
1508           fseek (f, 0, SEEK_SET);
1509           buffer = malloc (length + 1);
1510           if (buffer)
1511           {
1512             fread (buffer, 1, length, f);
1513           }
1514           fclose (f);
1515           buffer[length] = '\0';
1516         }
1517
1518         if (buffer)
1519         {
1520           return buffer;
1521         }
1522
1523         return NULL;
1524 }
1525
1526 /*
1527  * Dynamically allocated memory;
1528  * Caller needs to free the memory after it uses the value.
1529  *
1530 */
1531 cJSON*  getDeviceListFromStatusFile(void)
1532 {
1533     char *stringStatus = readStatusFileInString();
1534
1535         if (stringStatus == NULL)
1536         {
1537                 printf("Could not read status file!\n");
1538                 return NULL;
1539         }
1540
1541         cJSON *jsonStatus = cJSON_Parse(stringStatus);
1542         if (jsonStatus == NULL)
1543         {
1544                 free(stringStatus);
1545                 const char *error_ptr = cJSON_GetErrorPtr();
1546                 if (error_ptr != NULL)
1547                 {
1548                         fprintf(stderr, "Could not parse JSON status! Error before: %s\n", error_ptr);
1549                 }
1550                 return NULL;
1551         }
1552         //we don't need the string anymore
1553         free(stringStatus);
1554         stringStatus = NULL;
1555
1556     return jsonStatus;
1557 }
1558
1559 cJSON* createDeviceListEntry(counterAlarms ves_counter, counterAlarms netconf_counter)
1560 {
1561     cJSON *deviceListEntry = cJSON_CreateObject();
1562     if (deviceListEntry == NULL)
1563     {
1564         printf("Could not create JSON object: deviceListEntry\n");
1565         return NULL;
1566     }
1567
1568     char hostname[100];
1569     sprintf(hostname, "%s", getenv("HOSTNAME"));
1570
1571     if (cJSON_AddStringToObject(deviceListEntry, "device-name", hostname) == NULL)
1572     {
1573         printf("Could not create JSON object: device-name\n");
1574         cJSON_Delete(deviceListEntry);
1575         return NULL;
1576     }
1577
1578     cJSON *vesNotificationsSent = createSeverityCounters(ves_counter);
1579     if (vesNotificationsSent == NULL)
1580     {
1581         printf("Could not create JSON object: vesNotificationsSent\n");
1582         cJSON_Delete(deviceListEntry);
1583         return NULL;
1584     }
1585     cJSON_AddItemToObject(deviceListEntry, "ves-notifications-sent", vesNotificationsSent);
1586
1587     cJSON *netconfNotificationsSent = createSeverityCounters(netconf_counter);
1588     if (netconfNotificationsSent == NULL)
1589     {
1590         printf("Could not create JSON object: netconfNotificationsSent\n");
1591         cJSON_Delete(deviceListEntry);
1592         return NULL;
1593     }
1594     cJSON_AddItemToObject(deviceListEntry, "netconf-notifications-sent", netconfNotificationsSent);
1595
1596     return deviceListEntry;
1597 }
1598
1599 static void modifySeverityCounters(cJSON **severityCounters, counterAlarms count)
1600 {
1601     cJSON *severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-normal");
1602     if (!cJSON_IsNumber(severity))
1603     {
1604         printf("Status JSON is not as expected: severity-normal is not an number");
1605         return;
1606     }
1607     //we set the value of the severity-normal object
1608     cJSON_SetNumberValue(severity, count.normal);
1609
1610     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-warning");
1611     if (!cJSON_IsNumber(severity))
1612     {
1613         printf("Status JSON is not as expected: severity-warning is not an number");
1614         return;
1615     }
1616     //we set the value of the severity-warning object
1617     cJSON_SetNumberValue(severity, count.warning);
1618
1619     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-minor");
1620     if (!cJSON_IsNumber(severity))
1621     {
1622         printf("Status JSON is not as expected: severity-minor is not an number");
1623         return;
1624     }
1625     //we set the value of the severity-minor object
1626     cJSON_SetNumberValue(severity, count.minor);
1627
1628     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-major");
1629     if (!cJSON_IsNumber(severity))
1630     {
1631         printf("Status JSON is not as expected: severity-major is not an number");
1632         return;
1633     }
1634     //we set the value of the severity-major object
1635         cJSON_SetNumberValue(severity, count.major);
1636
1637     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-critical");
1638     if (!cJSON_IsNumber(severity))
1639     {
1640         printf("Status JSON is not as expected: severity-critical is not an number");
1641         return;
1642     }
1643     //we set the value of the severity-critical object
1644         cJSON_SetNumberValue(severity, count.critical);
1645
1646     return;
1647 }
1648
1649 static void modifyDeviceListEntry(cJSON **deviceListEntry, counterAlarms ves_counter, counterAlarms netconf_counter)
1650 {
1651     cJSON *vesNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "ves-notifications-sent");
1652     if (!cJSON_IsObject(vesNotificationsSent))
1653     {
1654         printf("Status JSON is not as expected: ves-notifications-sent is not a object");
1655         return;
1656     }
1657
1658     modifySeverityCounters(&vesNotificationsSent, ves_counter);
1659
1660     cJSON *netconfNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "netconf-notifications-sent");
1661     if (!cJSON_IsObject(netconfNotificationsSent))
1662     {
1663         printf("Status JSON is not as expected: netconf-notifications-sent is not a object");
1664         return;
1665     }
1666
1667     modifySeverityCounters(&netconfNotificationsSent, netconf_counter);
1668 }
1669
1670 int writeStatusNotificationCounters(counterAlarms ves_counter, counterAlarms netconf_counter)
1671 {
1672         cJSON *jsonStatus = getDeviceListFromStatusFile();
1673
1674         cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1675         if (!cJSON_IsArray(deviceList))
1676         {
1677                 printf("Status JSON is not as expected: device-list is not an object");
1678                 cJSON_Delete(jsonStatus);
1679                 return SR_ERR_OPERATION_FAILED;
1680         }
1681
1682     int array_size = cJSON_GetArraySize(deviceList);
1683
1684     int found = 0;
1685     for (int i=0; i<array_size; ++i)
1686     {
1687         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1688         char hostname[100];
1689         sprintf(hostname, "%s", getenv("HOSTNAME"));
1690
1691         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1692         if (!cJSON_IsString(deviceName))
1693         {
1694             printf("Status JSON is not as expected: device-name is not a string.");
1695             cJSON_Delete(jsonStatus);
1696             return SR_ERR_OPERATION_FAILED;
1697         }
1698         char *deviceNameString = cJSON_GetStringValue(deviceName);
1699
1700         if (strcmp(hostname, deviceNameString) == 0)
1701         {
1702             modifyDeviceListEntry(&deviceListEntry, ves_counter, netconf_counter);
1703             found = 1;
1704             break;
1705         }
1706     }
1707     if (found == 0)
1708     {
1709         cJSON* deviceListEntry = createDeviceListEntry(ves_counter, netconf_counter);
1710     
1711         cJSON_AddItemToArray(deviceList, deviceListEntry);  
1712     }
1713
1714         //writing the new JSON to the configuration file
1715         char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
1716         writeStatusFile(stringStatus);
1717
1718     if (stringStatus != NULL)
1719     {
1720         free(stringStatus);
1721         stringStatus = NULL;
1722     }
1723
1724     if (jsonStatus != NULL)
1725     {
1726             cJSON_Delete(jsonStatus);
1727     }
1728
1729         return SR_ERR_OK;
1730 }
1731
1732
1733 int removeDeviceEntryFromStatusFile(char *containerId)
1734 {
1735     cJSON *jsonStatus = getDeviceListFromStatusFile();
1736
1737         cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1738         if (!cJSON_IsArray(deviceList))
1739         {
1740                 printf("Status JSON is not as expected: device-list is not an object");
1741                 cJSON_Delete(jsonStatus);
1742                 return SR_ERR_OPERATION_FAILED;
1743         }
1744
1745     int array_size = cJSON_GetArraySize(deviceList);
1746     int found = array_size;
1747
1748     for (int i=0; i<array_size; ++i)
1749     {
1750         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1751         char hostname[100];
1752         sprintf(hostname, "%s", getenv("HOSTNAME"));
1753
1754         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1755         if (!cJSON_IsString(deviceName))
1756         {
1757             printf("Status JSON is not as expected: device-name is not a string.");
1758             cJSON_Delete(jsonStatus);
1759             return SR_ERR_OPERATION_FAILED;
1760         }
1761         char *deviceNameString = cJSON_GetStringValue(deviceName);
1762
1763         if (strcmp(containerId, deviceNameString) == 0)
1764         {
1765             found = i;
1766             break;
1767         }
1768     }
1769
1770     if (found < array_size)
1771     {
1772         cJSON_DeleteItemFromArray(deviceList, found);
1773     }
1774     else
1775     {
1776         printf("Could not find status file entry for device with id=\"%s\"", containerId);
1777     }
1778
1779         //writing the new JSON to the configuration file
1780         char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
1781         writeStatusFile(stringStatus);
1782
1783     if (stringStatus != NULL)
1784     {
1785         free(stringStatus);
1786         stringStatus = NULL;
1787     }
1788
1789     if (jsonStatus != NULL)
1790     {
1791         cJSON_Delete(jsonStatus);
1792     }
1793
1794         return SR_ERR_OK;
1795 }
1796
1797 int compute_notifications_count(counterAlarms *ves_counter, counterAlarms *netconf_counter)
1798 {
1799     ves_counter->normal = ves_counter->warning = \
1800             ves_counter->minor = ves_counter->major = \
1801             ves_counter->critical = 0;
1802     netconf_counter->normal = netconf_counter->warning = \
1803             netconf_counter->minor = netconf_counter->major = \
1804             netconf_counter->critical = 0;
1805
1806     cJSON *jsonStatus = getDeviceListFromStatusFile();
1807
1808     cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1809         if (!cJSON_IsArray(deviceList))
1810         {
1811                 printf("Status JSON is not as expected: device-list is not an object");
1812                 cJSON_Delete(jsonStatus);
1813                 return SR_ERR_OPERATION_FAILED;
1814         }
1815
1816     int array_size = cJSON_GetArraySize(deviceList);
1817
1818     for (int i=0; i<array_size; ++i)
1819     {
1820         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1821
1822         cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
1823         if (!cJSON_IsObject(vesNotifications))
1824         {
1825             printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
1826             cJSON_Delete(jsonStatus);
1827             return SR_ERR_OPERATION_FAILED;
1828         }
1829
1830         cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
1831         if (!cJSON_IsNumber(severity))
1832         {
1833             printf("Status JSON is not as expected: severity-normal is not a string.");
1834             cJSON_Delete(jsonStatus);
1835             return SR_ERR_OPERATION_FAILED;
1836         }
1837         int counter = (int)(severity->valuedouble);
1838         ves_counter->normal += counter;
1839
1840         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
1841         if (!cJSON_IsNumber(severity))
1842         {
1843             printf("Status JSON is not as expected: severity-warning is not a string.");
1844             cJSON_Delete(jsonStatus);
1845             return SR_ERR_OPERATION_FAILED;
1846         }
1847         counter = (int)(severity->valuedouble);
1848         ves_counter->warning += counter;
1849
1850         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
1851         if (!cJSON_IsNumber(severity))
1852         {
1853             printf("Status JSON is not as expected: severity-minor is not a string.");
1854             cJSON_Delete(jsonStatus);
1855             return SR_ERR_OPERATION_FAILED;
1856         }
1857         counter = (int)(severity->valuedouble);
1858         ves_counter->minor += counter;
1859
1860         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
1861         if (!cJSON_IsNumber(severity))
1862         {
1863             printf("Status JSON is not as expected: severity-major is not a string.");
1864             cJSON_Delete(jsonStatus);
1865             return SR_ERR_OPERATION_FAILED;
1866         }
1867         counter = (int)(severity->valuedouble);
1868         ves_counter->major += counter;
1869
1870         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
1871         if (!cJSON_IsNumber(severity))
1872         {
1873             printf("Status JSON is not as expected: severity-critical is not a string.");
1874             cJSON_Delete(jsonStatus);
1875             return SR_ERR_OPERATION_FAILED;
1876         }
1877         counter = (int)(severity->valuedouble);
1878         ves_counter->critical += counter;
1879
1880         cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
1881         if (!cJSON_IsObject(netconfNotifications))
1882         {
1883             printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
1884             cJSON_Delete(jsonStatus);
1885             return SR_ERR_OPERATION_FAILED;
1886         }
1887
1888         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
1889         if (!cJSON_IsNumber(severity))
1890         {
1891             printf("Status JSON is not as expected: severity-normal is not a string.");
1892             cJSON_Delete(jsonStatus);
1893             return SR_ERR_OPERATION_FAILED;
1894         }
1895         
1896         counter = (int)(severity->valuedouble);
1897         netconf_counter->normal += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1898
1899         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
1900         if (!cJSON_IsNumber(severity))
1901         {
1902             printf("Status JSON is not as expected: severity-warning is not a string.");
1903             cJSON_Delete(jsonStatus);
1904             return SR_ERR_OPERATION_FAILED;
1905         }
1906         counter = (int)(severity->valuedouble);
1907         netconf_counter->warning += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1908
1909         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
1910         if (!cJSON_IsNumber(severity))
1911         {
1912             printf("Status JSON is not as expected: severity-minor is not a string.");
1913             cJSON_Delete(jsonStatus);
1914             return SR_ERR_OPERATION_FAILED;
1915         }
1916         counter = (int)(severity->valuedouble);
1917         netconf_counter->minor += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1918
1919         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
1920         if (!cJSON_IsNumber(severity))
1921         {
1922             printf("Status JSON is not as expected: severity-major is not a string.");
1923             cJSON_Delete(jsonStatus);
1924             return SR_ERR_OPERATION_FAILED;
1925         }
1926         counter = (int)(severity->valuedouble);
1927         netconf_counter->major += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1928
1929         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
1930         if (!cJSON_IsNumber(severity))
1931         {
1932             printf("Status JSON is not as expected: severity-critical is not a string.");
1933             cJSON_Delete(jsonStatus);
1934             return SR_ERR_OPERATION_FAILED;
1935         }
1936         counter = (int)(severity->valuedouble);
1937         netconf_counter->critical += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1938     }
1939
1940     cJSON_Delete(jsonStatus);
1941
1942     return SR_ERR_OK;
1943 }
1944
1945 int getDeviceCounters(char *containerId, counterAlarms *ves_counter, counterAlarms *netconf_counter)
1946 {
1947     cJSON *jsonStatus = getDeviceListFromStatusFile();
1948
1949     cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1950         if (!cJSON_IsArray(deviceList))
1951         {
1952                 printf("Status JSON is not as expected: device-list is not an object");
1953                 cJSON_Delete(jsonStatus);
1954                 return SR_ERR_OPERATION_FAILED;
1955         }
1956
1957     int array_size = cJSON_GetArraySize(deviceList);
1958
1959     ves_counter->critical = ves_counter->major = ves_counter->minor = ves_counter->warning = ves_counter->normal = 0;
1960     netconf_counter->critical = netconf_counter->major = netconf_counter->minor = netconf_counter->warning = netconf_counter->normal = 0;
1961
1962     for (int i=0; i<array_size; ++i)
1963     {
1964         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1965
1966         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1967         if (!cJSON_IsString(deviceName))
1968         {
1969             printf("Status JSON is not as expected: device-name is not a string.");
1970             cJSON_Delete(jsonStatus);
1971             return SR_ERR_OPERATION_FAILED;
1972         }
1973         char *deviceNameString = cJSON_GetStringValue(deviceName);
1974
1975         if (strcmp(deviceNameString, containerId) != 0)
1976         {
1977             continue;
1978         }
1979
1980         cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
1981         if (!cJSON_IsObject(vesNotifications))
1982         {
1983             printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
1984             cJSON_Delete(jsonStatus);
1985             return SR_ERR_OPERATION_FAILED;
1986         }
1987
1988         cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
1989         if (!cJSON_IsNumber(severity))
1990         {
1991             printf("Status JSON is not as expected: severity-normal is not a string.");
1992             cJSON_Delete(jsonStatus);
1993             return SR_ERR_OPERATION_FAILED;
1994         }
1995         int counter = (int)(severity->valuedouble);
1996         ves_counter->normal = counter;
1997
1998         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
1999         if (!cJSON_IsNumber(severity))
2000         {
2001             printf("Status JSON is not as expected: severity-warning is not a string.");
2002             cJSON_Delete(jsonStatus);
2003             return SR_ERR_OPERATION_FAILED;
2004         }
2005         counter = (int)(severity->valuedouble);
2006         ves_counter->warning = counter;
2007
2008         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
2009         if (!cJSON_IsNumber(severity))
2010         {
2011             printf("Status JSON is not as expected: severity-minor is not a string.");
2012             cJSON_Delete(jsonStatus);
2013             return SR_ERR_OPERATION_FAILED;
2014         }
2015         counter = (int)(severity->valuedouble);
2016         ves_counter->minor = counter;
2017
2018         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
2019         if (!cJSON_IsNumber(severity))
2020         {
2021             printf("Status JSON is not as expected: severity-major is not a string.");
2022             cJSON_Delete(jsonStatus);
2023             return SR_ERR_OPERATION_FAILED;
2024         }
2025         counter = (int)(severity->valuedouble);
2026         ves_counter->major = counter;
2027
2028         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
2029         if (!cJSON_IsNumber(severity))
2030         {
2031             printf("Status JSON is not as expected: severity-critical is not a string.");
2032             cJSON_Delete(jsonStatus);
2033             return SR_ERR_OPERATION_FAILED;
2034         }
2035         counter = (int)(severity->valuedouble);
2036         ves_counter->critical = counter;
2037
2038         cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
2039         if (!cJSON_IsObject(netconfNotifications))
2040         {
2041             printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
2042             cJSON_Delete(jsonStatus);
2043             return SR_ERR_OPERATION_FAILED;
2044         }
2045
2046         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
2047         if (!cJSON_IsNumber(severity))
2048         {
2049             printf("Status JSON is not as expected: severity-normal is not a string.");
2050             cJSON_Delete(jsonStatus);
2051             return SR_ERR_OPERATION_FAILED;
2052         }
2053         
2054         counter = (int)(severity->valuedouble);
2055         netconf_counter->normal = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
2056
2057         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
2058         if (!cJSON_IsNumber(severity))
2059         {
2060             printf("Status JSON is not as expected: severity-warning is not a string.");
2061             cJSON_Delete(jsonStatus);
2062             return SR_ERR_OPERATION_FAILED;
2063         }
2064         counter = (int)(severity->valuedouble);
2065         netconf_counter->warning = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
2066
2067         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
2068         if (!cJSON_IsNumber(severity))
2069         {
2070             printf("Status JSON is not as expected: severity-minor is not a string.");
2071             cJSON_Delete(jsonStatus);
2072             return SR_ERR_OPERATION_FAILED;
2073         }
2074         counter = (int)(severity->valuedouble);
2075         netconf_counter->minor = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
2076
2077         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
2078         if (!cJSON_IsNumber(severity))
2079         {
2080             printf("Status JSON is not as expected: severity-major is not a string.");
2081             cJSON_Delete(jsonStatus);
2082             return SR_ERR_OPERATION_FAILED;
2083         }
2084         counter = (int)(severity->valuedouble);
2085         netconf_counter->major = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
2086
2087         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
2088         if (!cJSON_IsNumber(severity))
2089         {
2090             printf("Status JSON is not as expected: severity-critical is not a string.");
2091             cJSON_Delete(jsonStatus);
2092             return SR_ERR_OPERATION_FAILED;
2093         }
2094         counter = (int)(severity->valuedouble);
2095         netconf_counter->critical = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
2096     }
2097
2098     cJSON_Delete(jsonStatus);
2099
2100     return SR_ERR_OK;
2101 }
2102
2103 int writeSkeletonConfigFile()
2104 {
2105     cJSON *configObject = cJSON_CreateObject();
2106     if (configObject == NULL)
2107     {
2108         printf("Could not create JSON object: configObject\n");
2109         return SR_ERR_OPERATION_FAILED;
2110     }
2111
2112     cJSON *notificationConfig = cJSON_CreateObject();
2113     if (notificationConfig == NULL)
2114     {
2115         printf("Could not create JSON object: notificationConfig\n");
2116         cJSON_Delete(configObject);
2117         return SR_ERR_OPERATION_FAILED;
2118     }
2119     cJSON_AddItemToObject(configObject, "notification-config", notificationConfig);
2120
2121     if (cJSON_AddNumberToObject(notificationConfig, "ves-heartbeat-period", 0) == NULL)
2122     {
2123         printf("Could not create JSON object: ves-heartbeat-period\n");
2124         cJSON_Delete(configObject);
2125         return SR_ERR_OPERATION_FAILED;
2126     }
2127
2128     if (cJSON_AddTrueToObject(notificationConfig, "is-netconf-available") == NULL)
2129     {
2130         printf("Could not create JSON object: is-netconf-available\n");
2131         cJSON_Delete(configObject);
2132         return SR_ERR_OPERATION_FAILED;
2133     }
2134
2135     if (cJSON_AddTrueToObject(notificationConfig, "is-ves-available") == NULL)
2136     {
2137         printf("Could not create JSON object: is-ves-available\n");
2138         cJSON_Delete(configObject);
2139         return SR_ERR_OPERATION_FAILED;
2140     }
2141
2142     cJSON *faultNotificationDelayPeriod = cJSON_CreateArray();
2143     if (faultNotificationDelayPeriod == NULL)
2144     {
2145         printf("Could not create JSON object: faultNotificationDelayPeriod\n");
2146         cJSON_Delete(configObject);
2147         return SR_ERR_OPERATION_FAILED;
2148         }
2149     cJSON_AddItemToObject(notificationConfig, "fault-notification-delay-period", faultNotificationDelayPeriod);
2150
2151     cJSON *arrayItem = cJSON_CreateNumber(0);
2152     if (arrayItem == NULL)
2153     {
2154         printf("Could not create JSON object: arrayItem\n");
2155         cJSON_Delete(configObject);
2156         return SR_ERR_OPERATION_FAILED;
2157         }
2158     cJSON_AddItemToArray(faultNotificationDelayPeriod, arrayItem);
2159
2160     cJSON *vesEndPointDetails = cJSON_CreateObject();
2161     if (vesEndPointDetails == NULL)
2162     {
2163         printf("Could not create JSON object: vesEndPointDetails\n");
2164         cJSON_Delete(configObject);
2165         return SR_ERR_OPERATION_FAILED;
2166     }
2167     cJSON_AddItemToObject(configObject, "ves-endpoint-details", vesEndPointDetails);
2168
2169     if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-ip", "172.17.0.1") == NULL)
2170     {
2171         printf("Could not create JSON object: ves-endpoint-ip\n");
2172         cJSON_Delete(configObject);
2173         return SR_ERR_OPERATION_FAILED;
2174     }
2175
2176     if (cJSON_AddNumberToObject(vesEndPointDetails, "ves-endpoint-port", 30007) == NULL)
2177     {
2178         printf("Could not create JSON object: ves-endpoint-port\n");
2179         cJSON_Delete(configObject);
2180         return SR_ERR_OPERATION_FAILED;
2181     }
2182
2183     if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-auth-method", "no-auth") == NULL)
2184     {
2185         printf("Could not create JSON object: ves-endpoint-auth-method\n");
2186         cJSON_Delete(configObject);
2187         return SR_ERR_OPERATION_FAILED;
2188     }
2189
2190     if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-username", "") == NULL)
2191     {
2192         printf("Could not create JSON object: ves-endpoint-username\n");
2193         cJSON_Delete(configObject);
2194         return SR_ERR_OPERATION_FAILED;
2195     }
2196
2197     if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-password", "") == NULL)
2198     {
2199         printf("Could not create JSON object: ves-endpoint-password\n");
2200         cJSON_Delete(configObject);
2201         return SR_ERR_OPERATION_FAILED;
2202     }
2203
2204     if (cJSON_AddStringToObject(vesEndPointDetails, "ves-endpoint-certificate", "") == NULL)
2205     {
2206         printf("Could not create JSON object: ves-endpoint-certificate\n");
2207         cJSON_Delete(configObject);
2208         return SR_ERR_OPERATION_FAILED;
2209     }
2210
2211     if (cJSON_AddFalseToObject(vesEndPointDetails, "ves-registration") == NULL)
2212     {
2213         printf("Could not create JSON object: ves-registration\n");
2214         cJSON_Delete(configObject);
2215         return SR_ERR_OPERATION_FAILED;
2216     }
2217
2218     cJSON *controllerDetails = cJSON_CreateObject();
2219     if (controllerDetails == NULL)
2220     {
2221         printf("Could not create JSON object: controllerDetails\n");
2222         cJSON_Delete(configObject);
2223         return SR_ERR_OPERATION_FAILED;
2224     }
2225     cJSON_AddItemToObject(configObject, "controller-details", controllerDetails);
2226
2227     if (cJSON_AddStringToObject(controllerDetails, "controller-ip", "172.17.0.1") == NULL)
2228     {
2229         printf("Could not create JSON object: controller-ip\n");
2230         cJSON_Delete(configObject);
2231         return SR_ERR_OPERATION_FAILED;
2232     }
2233
2234     if (cJSON_AddNumberToObject(controllerDetails, "controller-port", 8181) == NULL)
2235     {
2236         printf("Could not create JSON object: controller-port\n");
2237         cJSON_Delete(configObject);
2238         return SR_ERR_OPERATION_FAILED;
2239     }
2240
2241     if (cJSON_AddNumberToObject(controllerDetails, "netconf-call-home-port", 6666) == NULL)
2242     {
2243         printf("Could not create JSON object: netconf-call-home-port\n");
2244         cJSON_Delete(configObject);
2245         return SR_ERR_OPERATION_FAILED;
2246     }
2247
2248     if (cJSON_AddStringToObject(controllerDetails, "controller-username", "admin") == NULL)
2249     {
2250         printf("Could not create JSON object: controller-username\n");
2251         cJSON_Delete(configObject);
2252         return SR_ERR_OPERATION_FAILED;
2253     }
2254
2255     if (cJSON_AddStringToObject(controllerDetails, "controller-password", "admin") == NULL)
2256     {
2257         printf("Could not create JSON object: controller-password\n");
2258         cJSON_Delete(configObject);
2259         return SR_ERR_OPERATION_FAILED;
2260     }
2261
2262     if (cJSON_AddNumberToObject(configObject, "ssh-connections", 1) == NULL)
2263     {
2264         printf("Could not create JSON object: ssh-connections\n");
2265         cJSON_Delete(configObject);
2266         return SR_ERR_OPERATION_FAILED;
2267     }
2268
2269     if (cJSON_AddNumberToObject(configObject, "tls-connections", 0) == NULL)
2270     {
2271         printf("Could not create JSON object: tls-connections\n");
2272         cJSON_Delete(configObject);
2273         return SR_ERR_OPERATION_FAILED;
2274     }
2275
2276     if (cJSON_AddFalseToObject(configObject, "netconf-call-home") == NULL)
2277     {
2278         printf("Could not create JSON object: netconf-call-home\n");
2279         cJSON_Delete(configObject);
2280         return SR_ERR_OPERATION_FAILED;
2281     }
2282
2283     char *config_string = NULL;
2284
2285     config_string = cJSON_PrintUnformatted(configObject);
2286
2287     writeConfigFile(config_string);
2288
2289     if (config_string != NULL)
2290     {
2291         free(config_string);
2292         config_string = NULL;
2293     }
2294
2295     if (configObject != NULL)
2296     {
2297         cJSON_Delete(configObject);
2298     }
2299
2300     return SR_ERR_OK;
2301 }
2302
2303 int getIntFromString(char *string, int def_value)
2304 {
2305     int rc, value = def_value;
2306     if (string != NULL)
2307     {
2308         rc = sscanf(string, "%d", &value);
2309         if (rc != 1)
2310         {
2311             printf("Could not get the %s! Using the default 0...\n", string);
2312             value = def_value;
2313         }
2314     }
2315     return value;
2316 }
2317
2318 int     getSshConnectionsFromConfigJson(void)
2319 {
2320     char *stringConfig = readConfigFileInString();
2321
2322     if (stringConfig == NULL)
2323     {
2324         printf("Could not read JSON configuration file in string.");
2325         return 0;
2326     }
2327
2328     cJSON *jsonConfig = cJSON_Parse(stringConfig);
2329     if (jsonConfig == NULL)
2330     {
2331         free(stringConfig);
2332         const char *error_ptr = cJSON_GetErrorPtr();
2333         if (error_ptr != NULL)
2334         {
2335             fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
2336         }
2337         return SR_ERR_OPERATION_FAILED;
2338     }
2339     //we don't need the string anymore
2340     free(stringConfig);
2341     stringConfig = NULL;
2342
2343     cJSON *sshConnections = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ssh-connections");
2344     if (!cJSON_IsNumber(sshConnections))
2345     {
2346         printf("Configuration JSON is not as expected: ssh-connections is not an object");
2347         cJSON_Delete(jsonConfig);
2348         return SR_ERR_OPERATION_FAILED;
2349     }
2350
2351     int num_of_ssh = (int)(sshConnections->valuedouble);
2352
2353     cJSON_Delete(jsonConfig);
2354
2355     return num_of_ssh;
2356 }
2357
2358 int     getTlsConnectionsFromConfigJson(void)
2359 {
2360     char *stringConfig = readConfigFileInString();
2361
2362     if (stringConfig == NULL)
2363     {
2364         printf("Could not read JSON configuration file in string.");
2365         return 0;
2366     }
2367
2368     cJSON *jsonConfig = cJSON_Parse(stringConfig);
2369     if (jsonConfig == NULL)
2370     {
2371         free(stringConfig);
2372         const char *error_ptr = cJSON_GetErrorPtr();
2373         if (error_ptr != NULL)
2374         {
2375             fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
2376         }
2377         return SR_ERR_OPERATION_FAILED;
2378     }
2379     //we don't need the string anymore
2380     free(stringConfig);
2381     stringConfig = NULL;
2382
2383     cJSON *tlsConnections = cJSON_GetObjectItemCaseSensitive(jsonConfig, "tls-connections");
2384     if (!cJSON_IsNumber(tlsConnections))
2385     {
2386         printf("Configuration JSON is not as expected: ssh-connections is not an object");
2387         cJSON_Delete(jsonConfig);
2388         return SR_ERR_OPERATION_FAILED;
2389     }
2390
2391     int num_of_tls = (int)(tlsConnections->valuedouble);
2392
2393     cJSON_Delete(jsonConfig);
2394
2395     return num_of_tls;
2396 }