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