Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * 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*/
	}
}