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 23struct pss__raw_echo { 24 uint8_t buf[2048]; 25 int len; 26}; 27 28static int interrupted; 29 30static 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 50static int 51callback_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 85static 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 90void sigint_handler(int sig) 91{ 92 interrupted = 1; 93} 94 95int 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