Buckets:
| enum { AUTH_OK, AUTH_FAIL, AUTH_ERROR }; | |
| static char *html_cache = NULL; | |
| static size_t html_cache_len = 0; | |
| static int send_unauthorized(struct lws *wsi, unsigned int code, enum lws_token_indexes header) { | |
| unsigned char buffer[1024 + LWS_PRE], *p, *end; | |
| p = buffer + LWS_PRE; | |
| end = p + sizeof(buffer) - LWS_PRE; | |
| if (lws_add_http_header_status(wsi, code, &p, end) || | |
| lws_add_http_header_by_token(wsi, header, (unsigned char *)"Basic realm=\"ttyd\"", 18, &p, end) || | |
| lws_add_http_header_content_length(wsi, 0, &p, end) || lws_finalize_http_header(wsi, &p, end) || | |
| lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) | |
| return AUTH_FAIL; | |
| return lws_http_transaction_completed(wsi) ? AUTH_FAIL : AUTH_ERROR; | |
| } | |
| static int check_auth(struct lws *wsi, struct pss_http *pss) { | |
| if (server->auth_header != NULL) { | |
| if (lws_hdr_custom_length(wsi, server->auth_header, strlen(server->auth_header)) > 0) return AUTH_OK; | |
| return send_unauthorized(wsi, HTTP_STATUS_PROXY_AUTH_REQUIRED, WSI_TOKEN_HTTP_PROXY_AUTHENTICATE); | |
| } | |
| if(server->credential != NULL) { | |
| char buf[256]; | |
| int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_AUTHORIZATION); | |
| if (len >= 7 && strstr(buf, "Basic ")) { | |
| if (!strcmp(buf + 6, server->credential)) return AUTH_OK; | |
| } | |
| return send_unauthorized(wsi, HTTP_STATUS_UNAUTHORIZED, WSI_TOKEN_HTTP_WWW_AUTHENTICATE); | |
| } | |
| return AUTH_OK; | |
| } | |
| static bool accept_gzip(struct lws *wsi) { | |
| char buf[256]; | |
| int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_ACCEPT_ENCODING); | |
| return len > 0 && strstr(buf, "gzip") != NULL; | |
| } | |
| static bool uncompress_html(char **output, size_t *output_len) { | |
| if (html_cache == NULL || html_cache_len == 0) { | |
| z_stream stream; | |
| memset(&stream, 0, sizeof(stream)); | |
| if (inflateInit2(&stream, 16 + 15) != Z_OK) return false; | |
| html_cache_len = index_html_size; | |
| html_cache = xmalloc(html_cache_len); | |
| stream.avail_in = index_html_len; | |
| stream.avail_out = html_cache_len; | |
| stream.next_in = (void *)index_html; | |
| stream.next_out = (void *)html_cache; | |
| int ret = inflate(&stream, Z_SYNC_FLUSH); | |
| inflateEnd(&stream); | |
| if (ret != Z_STREAM_END) { | |
| free(html_cache); | |
| html_cache = NULL; | |
| html_cache_len = 0; | |
| return false; | |
| } | |
| } | |
| *output = html_cache; | |
| *output_len = html_cache_len; | |
| return true; | |
| } | |
| static void pss_buffer_free(struct pss_http *pss) { | |
| if (pss->buffer != (char *)index_html && pss->buffer != html_cache) free(pss->buffer); | |
| } | |
| static void access_log(struct lws *wsi, const char *path) { | |
| char rip[50]; | |
| lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip)); | |
| lwsl_notice("HTTP %s - %s\n", path, rip); | |
| } | |
| int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { | |
| struct pss_http *pss = (struct pss_http *)user; | |
| unsigned char buffer[4096 + LWS_PRE], *p, *end; | |
| char buf[256]; | |
| bool done = false; | |
| switch (reason) { | |
| case LWS_CALLBACK_HTTP: | |
| access_log(wsi, (const char *)in); | |
| snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in); | |
| switch (check_auth(wsi, pss)) { | |
| case AUTH_OK: | |
| break; | |
| case AUTH_FAIL: | |
| return 0; | |
| case AUTH_ERROR: | |
| default: | |
| return 1; | |
| } | |
| p = buffer + LWS_PRE; | |
| end = p + sizeof(buffer) - LWS_PRE; | |
| if (strcmp(pss->path, endpoints.token) == 0) { | |
| const char *credential = server->credential != NULL ? server->credential : ""; | |
| size_t n = snprintf(buf, sizeof(buf), "{\"token\": \"%s\"}", credential); | |
| if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end) || | |
| lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, | |
| (unsigned char *)"application/json;charset=utf-8", 30, &p, end) || | |
| lws_add_http_header_content_length(wsi, (unsigned long)n, &p, end) || | |
| lws_finalize_http_header(wsi, &p, end) || | |
| lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) | |
| return 1; | |
| pss->buffer = pss->ptr = strdup(buf); | |
| pss->len = n; | |
| lws_callback_on_writable(wsi); | |
| break; | |
| } | |
| // redirects `/base-path` to `/base-path/` | |
| if (strcmp(pss->path, endpoints.parent) == 0) { | |
| if (lws_add_http_header_status(wsi, HTTP_STATUS_FOUND, &p, end) || | |
| lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, (unsigned char *)endpoints.index, | |
| (int)strlen(endpoints.index), &p, end) || | |
| lws_add_http_header_content_length(wsi, 0, &p, end) || lws_finalize_http_header(wsi, &p, end) || | |
| lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) | |
| return 1; | |
| goto try_to_reuse; | |
| } | |
| if (strcmp(pss->path, endpoints.index) != 0) { | |
| lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); | |
| goto try_to_reuse; | |
| } | |
| const char *content_type = "text/html"; | |
| if (server->index != NULL) { | |
| int n = lws_serve_http_file(wsi, server->index, content_type, NULL, 0); | |
| if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi))) return 1; | |
| } else { | |
| char *output = (char *)index_html; | |
| size_t output_len = index_html_len; | |
| if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end) || | |
| lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (const unsigned char *)content_type, 9, &p, | |
| end)) | |
| return 1; | |
| if (!uncompress_html(&output, &output_len)) return 1; | |
| if (accept_gzip(wsi)) { | |
| if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING, (unsigned char *)"gzip", 4, &p, end)) | |
| return 1; | |
| } else { | |
| if (!uncompress_html(&output, &output_len)) return 1; | |
| } | |
| if (lws_add_http_header_content_length(wsi, (unsigned long)output_len, &p, end) || | |
| lws_finalize_http_header(wsi, &p, end) || | |
| lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) | |
| return 1; | |
| pss->buffer = pss->ptr = output; | |
| pss->len = output_len; | |
| lws_callback_on_writable(wsi); | |
| } | |
| break; | |
| case LWS_CALLBACK_HTTP_WRITEABLE: | |
| if (!pss->buffer || pss->len == 0) { | |
| goto try_to_reuse; | |
| } | |
| do { | |
| int n = sizeof(buffer) - LWS_PRE; | |
| int m = lws_get_peer_write_allowance(wsi); | |
| if (m == 0) { | |
| lws_callback_on_writable(wsi); | |
| return 0; | |
| } else if (m != -1 && m < n) { | |
| n = m; | |
| } | |
| if (pss->ptr + n > pss->buffer + pss->len) { | |
| n = (int)(pss->len - (pss->ptr - pss->buffer)); | |
| done = true; | |
| } | |
| memcpy(buffer + LWS_PRE, pss->ptr, n); | |
| pss->ptr += n; | |
| if (lws_write_http(wsi, buffer + LWS_PRE, (size_t)n) < n) { | |
| pss_buffer_free(pss); | |
| return -1; | |
| } | |
| } while (!lws_send_pipe_choked(wsi) && !done); | |
| if (!done && pss->ptr < pss->buffer + pss->len) { | |
| lws_callback_on_writable(wsi); | |
| break; | |
| } | |
| pss_buffer_free(pss); | |
| goto try_to_reuse; | |
| case LWS_CALLBACK_HTTP_FILE_COMPLETION: | |
| goto try_to_reuse; | |
| case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: | |
| if (!len || (SSL_get_verify_result((SSL *)in) != X509_V_OK)) { | |
| int err = X509_STORE_CTX_get_error((X509_STORE_CTX *)user); | |
| int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX *)user); | |
| const char *msg = X509_verify_cert_error_string(err); | |
| lwsl_err("client certificate verification error: %s (%d), depth: %d\n", msg, err, depth); | |
| return 1; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| return 0; | |
| /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */ | |
| try_to_reuse: | |
| if (lws_http_transaction_completed(wsi)) return -1; | |
| return 0; | |
| } | |
Xet Storage Details
- Size:
- 8.35 kB
- Xet hash:
- 96fbe83a7debeae198f269bf7b006df28418156dbac6695c96fe4b43023bb2b1
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.