supervisor: Make it a HTTP server
[src/app-framework-binder.git] / src / afs-main.c
1 /*
2  * Copyright (C) 2016, 2017 "IoT.bzh"
3  * Author José Bollo <jose.bollo@iot.bzh>
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 #define _GNU_SOURCE
19
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25
26 #include <systemd/sd-daemon.h>
27
28 #include "afb-common.h"
29 #include "afb-hsrv.h"
30 #include "afb-hswitch.h"
31 #include "afb-hreq.h"
32 #include "afb-apiset.h"
33 #include "afb-session.h"
34
35 #include "afs-supervisor.h"
36 #include "afs-config.h"
37
38 #include "verbose.h"
39 #include "jobs.h"
40 #include "process-name.h"
41
42 /* the main config */
43 struct afs_config *main_config;
44
45 /* the main apiset */
46 struct afb_apiset *main_apiset;
47
48 /*************************************************************************************/
49
50 static int init_http_server(struct afb_hsrv *hsrv)
51 {
52         if (!afb_hsrv_add_handler
53             (hsrv, main_config->rootapi, afb_hswitch_websocket_switch, main_apiset, 20))
54                 return 0;
55
56         if (!afb_hsrv_add_handler
57             (hsrv, main_config->rootapi, afb_hswitch_apis, main_apiset, 10))
58                 return 0;
59
60         if (main_config->roothttp != NULL) {
61                 if (!afb_hsrv_add_alias
62                     (hsrv, "", afb_common_rootdir_get_fd(), main_config->roothttp,
63                      -10, 1))
64                         return 0;
65         }
66
67         if (!afb_hsrv_add_handler
68             (hsrv, main_config->rootbase, afb_hswitch_one_page_api_redirect, NULL,
69              -20))
70                 return 0;
71
72         return 1;
73 }
74
75 static struct afb_hsrv *start_http_server()
76 {
77         int rc;
78         struct afb_hsrv *hsrv;
79
80         if (afb_hreq_init_download_path(main_config->uploaddir)) {
81                 ERROR("unable to set the upload directory %s", main_config->uploaddir);
82                 return NULL;
83         }
84
85         hsrv = afb_hsrv_create();
86         if (hsrv == NULL) {
87                 ERROR("memory allocation failure");
88                 return NULL;
89         }
90
91         if (!afb_hsrv_set_cache_timeout(hsrv, main_config->cacheTimeout)
92             || !init_http_server(hsrv)) {
93                 ERROR("initialisation of httpd failed");
94                 afb_hsrv_put(hsrv);
95                 return NULL;
96         }
97
98         NOTICE("Waiting port=%d rootdir=%s", main_config->httpdPort, main_config->rootdir);
99         NOTICE("Browser URL= http://localhost:%d", main_config->httpdPort);
100
101         rc = afb_hsrv_start(hsrv, (uint16_t) main_config->httpdPort, 15);
102         if (!rc) {
103                 ERROR("starting of httpd failed");
104                 afb_hsrv_put(hsrv);
105                 return NULL;
106         }
107
108         return hsrv;
109 }
110
111 static void start(int signum, void *arg)
112 {
113         struct afb_hsrv *hsrv;
114         int rc;
115
116         /* check illness */
117         if (signum) {
118                 ERROR("start aborted: received signal %s", strsignal(signum));
119                 exit(1);
120         }
121
122         /* set the directories */
123         mkdir(main_config->workdir, S_IRWXU | S_IRGRP | S_IXGRP);
124         if (chdir(main_config->workdir) < 0) {
125                 ERROR("Can't enter working dir %s", main_config->workdir);
126                 goto error;
127         }
128         if (afb_common_rootdir_set(main_config->rootdir) < 0) {
129                 ERROR("failed to set common root directory");
130                 goto error;
131         }
132
133         /* configure the daemon */
134         if (afb_session_init(main_config->nbSessionMax, main_config->cntxTimeout, main_config->token)) {
135                 ERROR("initialisation of session manager failed");
136                 goto error;
137         }
138
139         main_apiset = afb_apiset_create("main", main_config->apiTimeout);
140         if (!main_apiset) {
141                 ERROR("can't create main apiset");
142                 goto error;
143         }
144
145         /* init the main apiset */
146         rc = afs_supervisor_add(main_apiset);
147         if (rc < 0) {
148                 ERROR("Can't create supervision's apiset: %m");
149                 goto error;
150         }
151
152         /* start the services */
153         if (afb_apiset_start_all_services(main_apiset, 1) < 0)
154                 goto error;
155
156         /* start the HTTP server */
157         if (main_config->httpdPort <= 0) {
158                 ERROR("no port is defined");
159                 goto error;
160         }
161
162         if (!afb_hreq_init_cookie(main_config->httpdPort, main_config->rootapi, main_config->cntxTimeout)) {
163                 ERROR("initialisation of HTTP cookies failed");
164                 goto error;
165         }
166
167         hsrv = start_http_server();
168         if (hsrv == NULL)
169                 goto error;
170
171         /* ready */
172         sd_notify(1, "READY=1");
173         afs_supervisor_discover();
174         return;
175 error:
176         exit(1);
177 }
178
179 /**
180  * initalize the supervision
181  */
182 int main(int ac, char **av)
183 {
184         /* scan arguments */
185         main_config = afs_config_parse_arguments(ac, av);
186         if (main_config->name) {
187                 verbose_set_name(main_config->name, 0);
188                 process_name_set_name(main_config->name);
189                 process_name_replace_cmdline(av, main_config->name);
190         }
191         /* enter job processing */
192         jobs_start(3, 0, 10, start, av[1]);
193         WARNING("hoops returned from jobs_enter! [report bug]");
194         return 1;
195 }
196