struct wsl_ctx_s {
lws_ctx_t *ctx; /* libwebsocket context */
+ wsl_proto_t *http; /* has HTTP as upper layer protocol */
wsl_proto_t *protos; /* protocols */
int nproto; /* number of protocols */
lws_proto_t *lws_protos; /* libwebsocket protocols */
lws_t *pending; /* pending connection */
void *pending_user; /* user_data of pending */
wsl_proto_t *pending_proto; /* protocol of pending */
- int has_http; /* has HTTP as upper layer protocol */
mrp_list_hook_t pure_http; /* pure HTTP sockets */
};
{
lws_ext_t *builtin = libwebsocket_internal_extensions;
wsl_ctx_t *ctx;
- wsl_proto_t *up;
+ wsl_proto_t *up, *http;
lws_proto_t *lws_protos, *lp;
- int lws_nproto, has_http;
+ int lws_nproto;
mrp_io_event_t events;
const char *dev;
int port, i;
ctx->protos = protos;
ctx->nproto = nproto;
- has_http = !strncmp(protos[0].name, "http", 4) ? 1 : 0;
- lws_nproto = (has_http ? nproto : nproto + 1) + 1;
+ if (!strcmp(protos[0].name, "http") || !strcmp(protos[0].name, "http-only"))
+ http = &protos[0];
+ else
+ http = NULL;
+
+ lws_nproto = (http ? nproto : nproto + 1) + 1;
lws_protos = mrp_allocz_array(lws_proto_t, lws_nproto);
if (lws_protos == NULL)
lws_protos[0].name = "http";
lws_protos[0].callback = http_event;
- if (!has_http)
+ if (!http)
lws_protos[0].per_session_data_size = sizeof(void *);
else
lws_protos[0].per_session_data_size = sizeof(void *);
lp = lws_protos + 1;
- up = protos + (has_http ? 1 : 0);
+ up = protos + (http ? 1 : 0);
- for (i = has_http; i < nproto; i++) {
+ for (i = (http ? 1 : 0); i < nproto; i++) {
lp->name = up->name;
lp->callback = wsl_event;
lp->per_session_data_size = sizeof(void *);
}
ctx->lws_protos = lws_protos;
- ctx->has_http = has_http;
+ ctx->http = http;
ctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
return FALSE;
}
+
+#ifdef LWS_OPENSSL_SUPPORT
+
+static void load_extra_certs(wsl_ctx_t *ctx, void *user, lws_event_t event)
+{
+ int is_server;
+
+ if (ctx != NULL && ctx->load_certs != NULL) {
+ if (event == LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS)
+ is_server = TRUE;
+ else
+ is_server = FALSE;
+
+ ctx->load_certs(ctx, (SSL_CTX *)user, is_server);
+ }
+}
+
+
+static int verify_client_cert(void *user, void *in, size_t len)
+{
+ X509_STORE_CTX *x509_ctx;
+ SSL *ssl;
+ int pre_ok;
+
+ if (verify_client_cert_cb != NULL) {
+ x509_ctx = (X509_STORE_CTX *)user;
+ ssl = (SSL *)in;
+ pre_ok = (int)len;
+
+ if (verify_client_cert_cb(x509_ctx, ssl, pre_ok))
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+#else /* !LWS_OPENSSL_SUPPORT */
+
+static void load_extra_certs(wsl_ctx_t *ctx, void *user, lws_event_t event)
+{
+ MRP_UNUSED(ctx);
+ MRP_UNUSED(user);
+ MRP_UNUSED(event);
+
+ return;
+}
+
+
+static int verify_client_cert(void *user, void *in, size_t len)
+{
+ MRP_UNUSED(user);
+ MRP_UNUSED(in);
+ MRP_UNUSED(len);
+
+ return TRUE;
+}
+
+#endif
+
+
+
static int http_event(lws_ctx_t *ws_ctx, lws_t *ws, lws_event_t event,
void *user, void *in, size_t len)
{
case LWS_CALLBACK_HTTP:
uri = (const char *)in;
- if (!ctx->has_http) {
+ if (ctx->http == NULL) {
mrp_debug("denying HTTP request of '%s' for httpless context", uri);
return LWS_EVENT_DENY;
}
return LWS_EVENT_DENY;
}
- up = &ctx->protos[0];
-
+ up = ctx->http;
ctx->pending = ws;
ctx->pending_user = NULL;
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
uri = (const char *)in;
mrp_debug("serving '%s' over HTTP completed", uri);
+
+ sck = find_pure_http(ctx, ws);
+
+ if (sck != NULL) { /* known socket, deliver event */
+ up = sck->proto;
+
+ if (up != NULL) {
+ SOCKET_BUSY_REGION(sck, {
+ up->cbs.http_done(sck, in, sck->user_data,
+ up->proto_data);
+ up->cbs.check(sck, sck->user_data, up->proto_data);
+ });
+
+ if (check_closed(sck))
+ return 0;
+ }
+
+ status = LWS_EVENT_OK;
+ }
+
return LWS_EVENT_OK;
/*
* events always routed to protocols[0]
+ *
+ * XXX TODO: we need to open up for the upper layers using
+ * optionally settable wsl_ctx_t-level callbacks at least
+ *
+ * FILTER_NETWORK_CONNECTION
+ * FILTER_PROTOCOL_CONNECTION
+ * OPENSSL_*
+ *
+ * Probably for the sake of completeness we should open up
+ * all of these...
*/
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
return LWS_EVENT_OK;
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
+ load_extra_certs(ctx, user, event);
+ return LWS_EVENT_OK;
+
+#ifdef LWS_OPENSSL_SUPPORT
+ if (ctx != NULL && ctx->load_certs != NULL)
+ ctx->load_certs(ctx, user, FALSE);
+#endif
+ return LWS_EVENT_OK;
+
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:
- case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
- /* we don't support or do anything for SSL at the moment */
+ load_extra_certs(ctx, user, TRUE);
return LWS_EVENT_OK;
+ case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
+ if (verify_client_cert(user, in, len))
+ return LWS_EVENT_OK;
+ else
+ return LWS_EVENT_DENY;
+
case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
/* no extra headers we'd like to add */
return LWS_EVENT_OK;