2 * Copyright (C) 2015 "IoT.bzh"
3 * Author "Fulup Ar Foll"
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 https://www.gnu.org/software/libmicrohttpd/manual/html_node/index.html#Top
20 http://www-01.ibm.com/support/knowledgecenter/SSB23S_1.1.0.9/com.ibm.ztpf-ztpfdf.doc_put.09/gtpc2/cpp_vsprintf.html?cp=SSB23S_1.1.0.9%2F0-3-8-1-0-16-8
24 #include "../include/local-def.h"
27 #include <sys/types.h>
29 #define AFB_CONFIG_JTYPE "AFB_config"
31 PUBLIC char *ERROR_LABEL[]=ERROR_LABEL_DEF;
34 STATIC AFB_errorT AFBerr [AFB_SUCCESS+1];
35 STATIC json_object *jTypeStatic;
37 /* ------------------------------------------------------------------------------
38 * Get localtime and return in a string
39 * ------------------------------------------------------------------------------ */
41 PUBLIC char * configTime (void) {
42 static char reqTime [26];
46 /* Get actual Date and Time */
50 strftime (reqTime, sizeof (reqTime), "(%d-%b %H:%M)",rt);
52 // return pointer on static data
56 // load config from disk and merge with CLI option
57 PUBLIC AFB_error configLoadFile (AFB_session * session, AFB_config *cliconfig) {
58 static char cacheTimeout [10];
60 json_object * AFBConfig, *value;
62 // TBD integrate alias-dir array with config-file
63 session->config->aliasdir = cliconfig->aliasdir;
66 if (cliconfig->httpdPort == 0) session->config->httpdPort=1234;
67 else session->config->httpdPort=cliconfig->httpdPort;
69 // default Plugin API timeout
70 if (cliconfig->apiTimeout == 0) session->config->apiTimeout=DEFLT_API_TIMEOUT;
71 else session->config->apiTimeout=cliconfig->apiTimeout;
74 if (cliconfig->token == NULL) session->config->token= DEFLT_AUTH_TOKEN;
75 else session->config->token=cliconfig->token;
77 // cache timeout default one hour
78 if (cliconfig->cacheTimeout == 0) session->config->cacheTimeout=DEFLT_CACHE_TIMEOUT;
79 else session->config->cacheTimeout=cliconfig->cacheTimeout;
81 // cache timeout default one hour
82 if (cliconfig->cntxTimeout == 0) session->config->cntxTimeout=DEFLT_CNTX_TIMEOUT;
83 else session->config->cntxTimeout=cliconfig->cntxTimeout;
85 if (cliconfig->rootdir == NULL) {
86 session->config->rootdir = getenv("AFBDIR");
87 if (session->config->rootdir == NULL) {
88 session->config->rootdir = malloc (512);
89 strncpy (session->config->rootdir, getenv("HOME"),512);
90 strncat (session->config->rootdir, "/.AFB",512);
92 // if directory does not exist createit
93 mkdir (session->config->rootdir, O_RDWR | S_IRWXU | S_IRGRP);
95 session->config->rootdir = cliconfig->rootdir;
98 // if no Angular/HTML5 rootbase let's try '/' as default
99 if (cliconfig->rootbase == NULL) {
100 session->config->rootbase = "/opa";
102 session->config->rootbase= cliconfig->rootbase;
105 if (cliconfig->rootapi == NULL) {
106 session->config->rootapi = "/api";
108 session->config->rootapi= cliconfig->rootapi;
111 if (cliconfig->smack == NULL) {
112 session->config->smack = "demo";
114 session->config->smack= cliconfig->smack;
117 if (cliconfig->plugins == NULL) {
118 session->config->plugins = PLUGIN_INSTALL_DIR;
120 session->config->plugins= cliconfig->plugins;
123 // if no session dir create a default path from rootdir
124 if (cliconfig->sessiondir == NULL) {
125 session->config->sessiondir = malloc (512);
126 strncpy (session->config->sessiondir, session->config->rootdir, 512);
127 strncat (session->config->sessiondir, "/sessions",512);
129 session->config->sessiondir = cliconfig->sessiondir;
132 // if no config dir create a default path from sessiondir
133 if (cliconfig->configfile == NULL) {
134 session->config->configfile = malloc (512);
135 strncpy (session->config->configfile, session->config->sessiondir, 512);
136 strncat (session->config->configfile, "/AFB-config.json",512);
138 session->config->configfile = cliconfig->configfile;
141 // if no config dir create a default path from sessiondir
142 if (cliconfig->pidfile == NULL) {
143 session->config->pidfile = malloc (512);
144 strncpy (session->config->pidfile, session->config->sessiondir, 512);
145 strncat (session->config->pidfile, "/AFB-process.pid",512);
147 session->config->pidfile= cliconfig->pidfile;
150 // if no config dir create a default path from sessiondir
151 if (cliconfig->console == NULL) {
152 session->config->console = malloc (512);
153 strncpy (session->config->console, session->config->sessiondir, 512);
154 strncat (session->config->console, "/AFB-console.out",512);
156 session->config->console= cliconfig->console;
159 // just upload json object and return without any further processing
160 if((fd = open(session->config->configfile, O_RDONLY)) < 0) {
161 if (verbose) fprintf (stderr, "AFB:notice: config at %s: %s\n", session->config->configfile, strerror(errno));
165 // openjson from FD is not public API we need to reopen it !!!
167 AFBConfig = json_object_from_file (session->config->configfile);
169 // check it is an AFB_config
170 if (json_object_object_get_ex (AFBConfig, "jtype", &value)) {
171 if (strcmp (AFB_CONFIG_JTYPE, json_object_get_string (value))) {
172 fprintf (stderr,"AFB: Error file [%s] is not a valid [%s] type\n ", session->config->configfile, AFB_CONFIG_JTYPE);
177 if (!cliconfig->rootdir && json_object_object_get_ex (AFBConfig, "rootdir", &value)) {
178 session->config->rootdir = strdup (json_object_get_string (value));
181 if (!cliconfig->rootbase && json_object_object_get_ex (AFBConfig, "rootbase", &value)) {
182 session->config->rootbase = strdup (json_object_get_string (value));
185 if (!cliconfig->rootapi && json_object_object_get_ex (AFBConfig, "rootapi", &value)) {
186 session->config->rootapi = strdup (json_object_get_string (value));
189 if (!cliconfig->smack && json_object_object_get_ex (AFBConfig, "smack", &value)) {
190 session->config->smack = strdup (json_object_get_string (value));
193 if (!cliconfig->plugins && json_object_object_get_ex (AFBConfig, "plugins", &value)) {
194 session->config->plugins = strdup (json_object_get_string (value));
197 if (!cliconfig->setuid && json_object_object_get_ex (AFBConfig, "setuid", &value)) {
198 session->config->setuid = strdup (json_object_get_string (value));
201 if (!cliconfig->sessiondir && json_object_object_get_ex (AFBConfig, "sessiondir", &value)) {
202 session->config->sessiondir = strdup (json_object_get_string (value));
205 if (!cliconfig->pidfile && json_object_object_get_ex (AFBConfig, "pidfile", &value)) {
206 session->config->pidfile = strdup (json_object_get_string (value));
209 if (!cliconfig->httpdPort && json_object_object_get_ex (AFBConfig, "httpdPort", &value)) {
210 session->config->httpdPort = json_object_get_int (value);
214 if (!cliconfig->localhostOnly && json_object_object_get_ex (AFBConfig, "localhostonly", &value)) {
215 session->config->localhostOnly = json_object_get_int (value);
218 if (!cliconfig->cacheTimeout && json_object_object_get_ex (AFBConfig, "cachetimeout", &value)) {
219 session->config->cacheTimeout = json_object_get_int (value);
222 if (!cliconfig->apiTimeout && json_object_object_get_ex (AFBConfig, "apitimeout", &value)) {
223 session->config->apiTimeout = json_object_get_int (value);
226 if (!cliconfig->cntxTimeout && json_object_object_get_ex (AFBConfig, "cntxtimeout", &value)) {
227 session->config->cntxTimeout = json_object_get_int (value);
230 // cacheTimeout is an integer but HTTPd wants it as a string
231 snprintf (cacheTimeout, sizeof (cacheTimeout),"%d", session->config->cacheTimeout);
232 session->cacheTimeout = cacheTimeout; // httpd uses cacheTimeout string version
234 json_object_put (AFBConfig); // decrease reference count to free the json object
241 // Save the config on disk
242 PUBLIC void configStoreFile (AFB_session * session) {
243 json_object * AFBConfig;
245 struct tm * timeinfo;
248 AFBConfig = json_object_new_object();
250 // add a timestamp and store session on disk
251 time ( &rawtime ); timeinfo = localtime ( &rawtime );
252 // A copy of the string is made and the memory is managed by the json_object
253 json_object_object_add (AFBConfig, "jtype" , json_object_new_string (AFB_CONFIG_JTYPE));
254 json_object_object_add (AFBConfig, "timestamp" , json_object_new_string (asctime (timeinfo)));
255 json_object_object_add (AFBConfig, "rootdir" , json_object_new_string (session->config->rootdir));
256 json_object_object_add (AFBConfig, "rootapi" , json_object_new_string (session->config->rootapi));
257 json_object_object_add (AFBConfig, "rootbase" , json_object_new_string (session->config->rootbase));
258 json_object_object_add (AFBConfig, "smack" , json_object_new_string (session->config->smack));
259 json_object_object_add (AFBConfig, "plugins" , json_object_new_string (session->config->plugins));
260 json_object_object_add (AFBConfig, "sessiondir" , json_object_new_string (session->config->sessiondir));
261 json_object_object_add (AFBConfig, "pidfile" , json_object_new_string (session->config->pidfile));
262 json_object_object_add (AFBConfig, "setuid" , json_object_new_string (session->config->setuid));
263 json_object_object_add (AFBConfig, "httpdPort" , json_object_new_int (session->config->httpdPort));
264 json_object_object_add (AFBConfig, "localhostonly" , json_object_new_int (session->config->localhostOnly));
265 json_object_object_add (AFBConfig, "cachetimeout" , json_object_new_int (session->config->cacheTimeout));
266 json_object_object_add (AFBConfig, "apitimeout" , json_object_new_int (session->config->apiTimeout));
267 json_object_object_add (AFBConfig, "cntxtimeout" , json_object_new_int (session->config->cntxTimeout));
269 err = json_object_to_file (session->config->configfile, AFBConfig);
270 json_object_put (AFBConfig); // decrease reference count to free the json object
272 fprintf(stderr, "AFB: Fail to save config on disk [%s]\n ", session->config->configfile);
277 PUBLIC AFB_session *configInit () {
279 AFB_session *session;
284 session = malloc (sizeof (AFB_session));
285 memset (session,0, sizeof (AFB_session));
287 // create config handle
288 config = malloc (sizeof (AFB_config));
289 memset (config,0, sizeof (AFB_config));
291 // stack config handle into session
292 session->config = config;
294 jTypeStatic = json_object_new_string ("AFB_message");
296 // initialise JSON constant messages and increase reference count to make them permanent
297 verbosesav = verbose;
298 verbose = 0; // run initialisation in silent mode
301 for (idx = 0; idx <= AFB_SUCCESS; idx++) {
302 AFBerr[idx].level = idx;
303 AFBerr[idx].label = ERROR_LABEL [idx];
304 AFBerr[idx].json = jsonNewMessage (idx, NULL);
306 verbose = verbosesav;
312 // get JSON object from error level and increase its reference count
313 PUBLIC json_object *jsonNewStatus (AFB_error level) {
315 json_object *target = AFBerr[level].json;
316 json_object_get (target);
321 // get AFB object type with adequate usage count
322 PUBLIC json_object *jsonNewjtype (void) {
323 json_object_get (jTypeStatic); // increase reference count
324 return (jTypeStatic);
327 // build an ERROR message and return it as a valid json object
328 PUBLIC json_object *jsonNewMessage (AFB_error level, char* format, ...) {
329 static int count = 0;
330 json_object * AFBResponse;
335 if (format != NULL) {
336 va_start(args, format);
337 vsnprintf (message, sizeof (message), format, args);
341 AFBResponse = json_object_new_object();
342 json_object_object_add (AFBResponse, "jtype", jsonNewjtype ());
343 json_object_object_add (AFBResponse, "status" , json_object_new_string (ERROR_LABEL[level]));
344 if (format != NULL) {
345 json_object_object_add (AFBResponse, "info" , json_object_new_string (message));
348 fprintf (stderr, "AFB:%-6s [%3d]: ", AFBerr [level].label, count++);
349 if (format != NULL) {
350 fprintf (stderr, "%s", message);
352 fprintf (stderr, "No Message");
354 fprintf (stderr, "\n");
357 return (AFBResponse);
360 // Dump a message on stderr
361 PUBLIC void jsonDumpObject (json_object * jObject) {
364 fprintf (stderr, "AFB:dump [%s]\n", json_object_to_json_string(jObject));