Imported Upstream version 3.2.0
[platform/upstream/libwebsockets.git] / minimal-examples / http-server / minimal-http-server-eventlib-smp / minimal-http-server-eventlib-smp.c
1 /*
2  * lws-minimal-http-server-eventlib-smp
3  *
4  * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  *
9  * This demonstrates a minimal http[s] server that can work with any of the
10  * supported event loop backends, or the default poll() one.
11  *
12  * To keep it simple, it serves stuff from the subdirectory 
13  * "./mount-origin" of the directory it was started in.
14  * You can change that by changing mount.origin below.
15  */
16
17 #include <libwebsockets.h>
18 #include <string.h>
19 #include <signal.h>
20
21 #include <pthread.h>
22
23 #define COUNT_THREADS 8
24
25 static struct lws_context *context;
26 static volatile int interrupted;
27
28 static const struct lws_http_mount mount = {
29         /* .mount_next */               NULL,           /* linked-list "next" */
30         /* .mountpoint */               "/",            /* mountpoint URL */
31         /* .origin */                   "./mount-origin", /* serve from dir */
32         /* .def */                      "index.html",   /* default filename */
33         /* .protocol */                 NULL,
34         /* .cgienv */                   NULL,
35         /* .extra_mimetypes */          NULL,
36         /* .interpret */                NULL,
37         /* .cgi_timeout */              0,
38         /* .cache_max_age */            0,
39         /* .auth_mask */                0,
40         /* .cache_reusable */           0,
41         /* .cache_revalidate */         0,
42         /* .cache_intermediaries */     0,
43         /* .origin_protocol */          LWSMPRO_FILE,   /* files in a dir */
44         /* .mountpoint_len */           1,              /* char count */
45         /* .basic_auth_login_file */    NULL,
46 };
47
48 void *thread_service(void *threadid)
49 {
50         while (lws_service_tsi(context, 10000,
51                                (int)(lws_intptr_t)threadid) >= 0 &&
52                !interrupted)
53                 ;
54
55         pthread_exit(NULL);
56
57         return NULL;
58 }
59
60 void signal_cb(void *handle, int signum)
61 {
62         interrupted = 1;
63
64         switch (signum) {
65         case SIGTERM:
66         case SIGINT:
67                 break;
68         default:
69                 lwsl_err("%s: signal %d\n", __func__, signum);
70                 break;
71         }
72         lws_context_destroy(context);
73 }
74
75 void sigint_handler(int sig)
76 {
77         signal_cb(NULL, sig);
78 }
79
80 int main(int argc, const char **argv)
81 {
82         pthread_t pthread_service[COUNT_THREADS];
83         struct lws_context_creation_info info;
84         const char *p;
85         void *retval;
86         int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
87                         /* for LLL_ verbosity above NOTICE to be built into lws,
88                          * lws must have been configured and built with
89                          * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
90                         /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
91                         /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
92                         /* | LLL_DEBUG */;
93
94         if ((p = lws_cmdline_option(argc, argv, "-d")))
95                 logs = atoi(p);
96
97         lws_set_log_level(logs, NULL);
98         lwsl_user("LWS minimal http server eventlib SMP | visit http://localhost:7681\n");
99         lwsl_user(" [-s (ssl)] [--uv (libuv)] [--ev (libev)] [--event (libevent)]\n");
100         lwsl_user("WARNING: Not stable, under development!\n");
101
102         memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
103         info.port = 7681;
104         info.mounts = &mount;
105         info.error_document_404 = "/404.html";
106         info.pcontext = &context;
107         info.signal_cb = signal_cb;
108         info.options =
109                 LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
110
111         if ((p = lws_cmdline_option(argc, argv, "-t"))) {
112                 info.count_threads = atoi(p);
113                 if (info.count_threads < 1 || info.count_threads > LWS_MAX_SMP)
114                         return 1;
115         } else
116                 info.count_threads = COUNT_THREADS;
117
118         if (lws_cmdline_option(argc, argv, "-s")) {
119                 info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
120                 info.ssl_cert_filepath = "localhost-100y.cert";
121                 info.ssl_private_key_filepath = "localhost-100y.key";
122         }
123
124         if (lws_cmdline_option(argc, argv, "--uv"))
125                 info.options |= LWS_SERVER_OPTION_LIBUV;
126         else
127                 if (lws_cmdline_option(argc, argv, "--event"))
128                         info.options |= LWS_SERVER_OPTION_LIBEVENT;
129                 else
130                         if (lws_cmdline_option(argc, argv, "--ev"))
131                                 info.options |= LWS_SERVER_OPTION_LIBEV;
132                         else
133                                 signal(SIGINT, sigint_handler);
134
135         context = lws_create_context(&info);
136         if (!context) {
137                 lwsl_err("lws init failed\n");
138                 return 1;
139         }
140
141         lwsl_notice("  Service threads: %d\n", lws_get_count_threads(context));
142
143         /* start all the service threads */
144
145         for (n = 0; n < lws_get_count_threads(context); n++)
146                 if (pthread_create(&pthread_service[n], NULL, thread_service,
147                                    (void *)(lws_intptr_t)n))
148                         lwsl_err("Failed to start service thread\n");
149
150         /* wait for all the service threads to exit */
151
152         while ((--n) >= 0)
153                 pthread_join(pthread_service[n], &retval);
154
155         lwsl_notice("%s: calling external context destroy\n", __func__);
156         lws_context_destroy(context);
157
158         return 0;
159 }