| /* |
| * Copyright (c) 2020 Alexander Kozhinov <AlexanderKozhinov@yandex.com> |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <logging/log.h> |
| LOG_MODULE_REGISTER(http_server_handlers, LOG_LEVEL_DBG); |
| |
| #include "http_server_handlers.h" |
| |
| #define TX_CHUNK_SIZE_BYTES CONFIG_NET_TX_STACK_SIZE |
| |
| #define URL_MAIN "/$" |
| #define URL_INDEX_CSS "/index.css" |
| #define URL_INDEX_HTML "/index.html" |
| #define URL_FAVICON_ICO "/favicon.ico" |
| #define URL_WS_JS "/ws.js" |
| |
| #define HTTP_TEXT_HTML "text/html" |
| #define HTTP_TEXT_CSS "text/css" |
| #define HTTP_TEXT_JS "text/javascript" |
| #define HTTP_EOFL "\r\n" /* http end of line */ |
| |
| #define HTTP_CONTEND_ENCODING "Content-Encoding: " |
| #define HTTP_ENCODING_GZ "gzip" |
| |
| #define __code_decl /* static */ |
| #define __data_decl static |
| |
| __code_decl void this_register_handlers(struct mg_context *ctx); |
| |
| __code_decl int this_send_buffer_chunked(struct mg_connection *conn, |
| const char *mime_type, |
| const char *buff, |
| const size_t buff_len); |
| |
| __code_decl int this_redirect_2_index_html(struct mg_connection *conn, |
| void *cbdata); |
| __code_decl int this_index_html_handler(struct mg_connection *conn, |
| void *cbdata); |
| __code_decl int this_index_css_handler(struct mg_connection *conn, |
| void *cbdata); |
| __code_decl int this_ws_js_handler(struct mg_connection *conn, |
| void *cbdata); |
| __code_decl int this_favicon_ico_handler(struct mg_connection *conn, |
| void *cbdata); |
| |
| __code_decl void this_set_return_value(int *ret_val); |
| |
| void init_http_server_handlers(struct mg_context *ctx) |
| { |
| this_register_handlers(ctx); |
| } |
| |
| __code_decl void this_register_handlers(struct mg_context *ctx) |
| { |
| mg_set_request_handler(ctx, URL_MAIN, |
| this_redirect_2_index_html, NULL); |
| mg_set_request_handler(ctx, URL_INDEX_HTML, |
| this_index_html_handler, NULL); |
| mg_set_request_handler(ctx, URL_INDEX_CSS, |
| this_index_css_handler, NULL); |
| mg_set_request_handler(ctx, URL_WS_JS, |
| this_ws_js_handler, NULL); |
| mg_set_request_handler(ctx, URL_FAVICON_ICO, |
| this_favicon_ico_handler, NULL); |
| } |
| |
| __code_decl int this_send_buffer_chunked(struct mg_connection *conn, |
| const char *mime_type, |
| const char *buff, |
| const size_t buff_len) |
| { |
| int ret = 0; |
| |
| ret = mg_send_http_ok(conn, mime_type, -1); |
| if (ret < 0) { |
| goto error_this_send_buffer_chunked; |
| } |
| |
| long left_bytes = buff_len; |
| char *itr = (char *)buff; /* buffer iterator */ |
| |
| LOG_DBG("Transferring:"); |
| LOG_DBG("itr: 0x%08X ret: %d left_bytes: %ld chunk_size: %zd B", |
| (unsigned int)itr, ret, left_bytes, TX_CHUNK_SIZE_BYTES); |
| |
| while (left_bytes > TX_CHUNK_SIZE_BYTES) { |
| ret = mg_send_chunk(conn, itr, TX_CHUNK_SIZE_BYTES); |
| itr += TX_CHUNK_SIZE_BYTES; |
| left_bytes -= TX_CHUNK_SIZE_BYTES; |
| |
| LOG_DBG("itr: 0x%08X ret: %d left_bytes: %ld", |
| (unsigned int)itr, ret, left_bytes); |
| |
| if (ret < 0) { |
| goto error_this_send_buffer_chunked; |
| } |
| } |
| |
| if (left_bytes > 0) { |
| ret = mg_send_chunk(conn, itr, left_bytes); |
| itr += left_bytes; |
| left_bytes = 0; |
| |
| LOG_DBG("itr: 0x%08X ret: %d left_bytes: %ld", |
| (unsigned int)itr, ret, left_bytes); |
| |
| if (ret < 0) { |
| goto error_this_send_buffer_chunked; |
| } |
| } |
| |
| /* Must be sent at the end of the chuked sequence */ |
| ret = mg_send_chunk(conn, "", 0); |
| |
| error_this_send_buffer_chunked: |
| if (ret < 0) { |
| LOG_ERR("aborted! ret: %d", ret); |
| } |
| |
| return ret; |
| } |
| |
| __code_decl int this_redirect_2_index_html(struct mg_connection *conn, |
| void *cbdata) |
| { |
| int ret = 0; |
| |
| ret = mg_send_http_redirect(conn, URL_INDEX_HTML, 303); |
| return 202; |
| } |
| |
| __code_decl int this_index_html_handler(struct mg_connection *conn, |
| void *cbdata) |
| { |
| __data_decl const char index_html[] = { |
| #include "web_page/index.html.gz.inc" |
| }; |
| |
| int ret = 0; |
| |
| ret = this_send_buffer_chunked(conn, HTTP_TEXT_HTML |
| HTTP_EOFL |
| HTTP_CONTEND_ENCODING |
| HTTP_ENCODING_GZ, |
| index_html, sizeof(index_html)); |
| this_set_return_value(&ret); |
| return ret; |
| } |
| |
| __code_decl int this_index_css_handler(struct mg_connection *conn, void *cbdata) |
| { |
| __data_decl const char index_css[] = { |
| #include "web_page/index.css.gz.inc" |
| }; |
| |
| int ret = 0; |
| |
| ret = this_send_buffer_chunked(conn, HTTP_TEXT_CSS |
| HTTP_EOFL |
| HTTP_CONTEND_ENCODING |
| HTTP_ENCODING_GZ, |
| index_css, sizeof(index_css)); |
| this_set_return_value(&ret); |
| return ret; |
| } |
| |
| __code_decl int this_ws_js_handler(struct mg_connection *conn, void *cbdata) |
| { |
| __data_decl const char ws_js[] = { |
| #include "web_page/ws.js.gz.inc" |
| }; |
| |
| int ret = 0; |
| |
| ret = this_send_buffer_chunked(conn, HTTP_TEXT_JS |
| HTTP_EOFL |
| HTTP_CONTEND_ENCODING |
| HTTP_ENCODING_GZ, |
| ws_js, sizeof(ws_js)); |
| this_set_return_value(&ret); |
| return ret; |
| } |
| |
| __code_decl int this_favicon_ico_handler(struct mg_connection *conn, |
| void *cbdata) |
| { |
| int ret = 404; |
| return ret; /* should fail */ |
| } |
| |
| __code_decl void this_set_return_value(int *ret_val) |
| { |
| if (*ret_val < 0) { |
| *ret_val = 404; /* 404 - HTTP FAIL or 0 - handler fail */ |
| } else { |
| *ret_val = 200; /* 200 - HTTP OK*/ |
| } |
| } |