1 /*
2 * lws-minimal-raw-fallback http-server
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 the most minimal http server you can make with lws.
10 *
11 * To keep it simple, it serves stuff from the subdirectory
12 * "./mount-origin" of the directory it was started in.
13 * You can change that by changing mount.origin below.
14 *
15 * In addition, if the connection does to seem to be talking http, then it
16 * falls back to a raw echo protocol.
17 */
18
19 #include <libwebsockets.h>
20 #include <string.h>
21 #include <signal.h>
22
23 struct pss__raw_echo {
24 uint8_t buf[2048];
25 int len;
26 };
27
28 static int interrupted;
29
30 static const struct lws_http_mount mount = {
31 /* .mount_next */ NULL, /* linked-list "next" */
32 /* .mountpoint */ "/", /* mountpoint URL */
33 /* .origin */ "./mount-origin", /* serve from dir */
34 /* .def */ "index.html", /* default filename */
35 /* .protocol */ NULL,
36 /* .cgienv */ NULL,
37 /* .extra_mimetypes */ NULL,
38 /* .interpret */ NULL,
39 /* .cgi_timeout */ 0,
40 /* .cache_max_age */ 0,
41 /* .auth_mask */ 0,
42 /* .cache_reusable */ 0,
43 /* .cache_revalidate */ 0,
44 /* .cache_intermediaries */ 0,
45 /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
46 /* .mountpoint_len */ 1, /* char count */
47 /* .basic_auth_login_file */ NULL,
48 };
49
50 static int
callback_raw_echo(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)51 callback_raw_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user,
52 void *in, size_t len)
53 {
54 struct pss__raw_echo *pss = (struct pss__raw_echo *)user;
55
56 switch (reason) {
57 case LWS_CALLBACK_RAW_ADOPT:
58 lwsl_notice("LWS_CALLBACK_RAW_ADOPT\n");
59 break;
60
61 case LWS_CALLBACK_RAW_RX:
62 lwsl_notice("LWS_CALLBACK_RAW_RX %ld\n", (long)len);
63 if (len > sizeof(pss->buf))
64 len = sizeof(pss->buf);
65 memcpy(pss->buf, in, len);
66 pss->len = (int)len;
67 lws_callback_on_writable(wsi);
68 break;
69
70 case LWS_CALLBACK_RAW_CLOSE:
71 lwsl_notice("LWS_CALLBACK_RAW_CLOSE\n");
72 break;
73
74 case LWS_CALLBACK_RAW_WRITEABLE:
75 lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE\n");
76 lws_write(wsi, pss->buf, (unsigned int)pss->len, LWS_WRITE_HTTP);
77 break;
78 default:
79 break;
80 }
81
82 return lws_callback_http_dummy(wsi, reason, user, in, len);
83 }
84
85 static const struct lws_protocols protocols[] = {
86 { "raw-echo", callback_raw_echo, sizeof(struct pss__raw_echo), 2048, 0, NULL, 0 },
87 LWS_PROTOCOL_LIST_TERM
88 };
89
sigint_handler(int sig)90 void sigint_handler(int sig)
91 {
92 interrupted = 1;
93 }
94
main(int argc,const char ** argv)95 int main(int argc, const char **argv)
96 {
97 struct lws_context_creation_info info;
98 struct lws_context *context;
99 const char *p;
100 int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
101
102 signal(SIGINT, sigint_handler);
103
104 if ((p = lws_cmdline_option(argc, argv, "-d")))
105 logs = atoi(p);
106
107 lws_set_log_level(logs, NULL);
108 lwsl_user("LWS minimal raw fallback http server | "
109 "visit http://localhost:7681\n");
110
111 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
112 info.port = 7681;
113 info.protocols = protocols;
114 info.mounts = &mount;
115 info.error_document_404 = "/404.html";
116 info.options =
117 LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE |
118 LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG;
119 info.listen_accept_role = "raw-skt";
120 info.listen_accept_protocol = "raw-echo";
121
122 #if defined(LWS_WITH_TLS)
123 if (lws_cmdline_option(argc, argv, "-s")) {
124 info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
125 LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
126 info.ssl_cert_filepath = "localhost-100y.cert";
127 info.ssl_private_key_filepath = "localhost-100y.key";
128
129 if (lws_cmdline_option(argc, argv, "-u"))
130 info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
131
132 if (lws_cmdline_option(argc, argv, "-h"))
133 info.options |= LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER;
134 }
135 #endif
136
137 context = lws_create_context(&info);
138 if (!context) {
139 lwsl_err("lws init failed\n");
140 return 1;
141 }
142
143 while (n >= 0 && !interrupted)
144 n = lws_service(context, 0);
145
146 lws_context_destroy(context);
147
148 return 0;
149 }
150