blob: 35cb03831e97dfc4c83ae6ea2fd2a5d59db42761 [file] [log] [blame]
/*
* Copyright (c) 2019 Antmicro Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/zephyr.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/data/json.h>
#include "civetweb.h"
#define HTTP_PORT 8080
#define HTTPS_PORT 4443
#define CIVETWEB_MAIN_THREAD_STACK_SIZE CONFIG_MAIN_STACK_SIZE
/* Use smallest possible value of 1024 (see the line 18619 of civetweb.c) */
#define MAX_REQUEST_SIZE_BYTES 1024
K_THREAD_STACK_DEFINE(civetweb_stack, CIVETWEB_MAIN_THREAD_STACK_SIZE);
struct civetweb_info {
const char *version;
const char *os;
uint32_t features;
const char *feature_list;
const char *build;
const char *compiler;
const char *data_model;
};
#define FIELD(struct_, member_, type_) { \
.field_name = #member_, \
.field_name_len = sizeof(#member_) - 1, \
.offset = offsetof(struct_, member_), \
.type = type_ \
}
void send_ok(struct mg_connection *conn)
{
mg_printf(conn,
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n");
}
int hello_world_handler(struct mg_connection *conn, void *cbdata)
{
send_ok(conn);
mg_printf(conn, "<html><body>");
mg_printf(conn, "<h3>Hello World from Zephyr!</h3>");
mg_printf(conn, "See also:\n");
mg_printf(conn, "<ul>\n");
mg_printf(conn, "<li><a href=/info>system info</a></li>\n");
mg_printf(conn, "<li><a href=/history>cookie demo</a></li>\n");
mg_printf(conn, "</ul>\n");
mg_printf(conn, "</body></html>\n");
return 200;
}
int system_info_handler(struct mg_connection *conn, void *cbdata)
{
static const struct json_obj_descr descr[] = {
FIELD(struct civetweb_info, version, JSON_TOK_STRING),
FIELD(struct civetweb_info, os, JSON_TOK_STRING),
FIELD(struct civetweb_info, feature_list, JSON_TOK_STRING),
FIELD(struct civetweb_info, build, JSON_TOK_STRING),
FIELD(struct civetweb_info, compiler, JSON_TOK_STRING),
FIELD(struct civetweb_info, data_model, JSON_TOK_STRING),
};
struct civetweb_info info = {};
char info_str[1024] = {};
int ret;
int size;
size = mg_get_system_info(info_str, sizeof(info_str));
ret = json_obj_parse(info_str, size, descr, ARRAY_SIZE(descr), &info);
send_ok(conn);
if (ret < 0) {
mg_printf(conn, "Could not retrieve: %d\n", ret);
return 500;
}
mg_printf(conn, "<html><body>");
mg_printf(conn, "<h3>Server info</h3>");
mg_printf(conn, "<ul>\n");
mg_printf(conn, "<li>host os - %s</li>\n", info.os);
mg_printf(conn, "<li>server - civetweb %s</li>\n", info.version);
mg_printf(conn, "<li>compiler - %s</li>\n", info.compiler);
mg_printf(conn, "<li>board - %s</li>\n", CONFIG_BOARD);
mg_printf(conn, "</ul>\n");
mg_printf(conn, "</body></html>\n");
return 200;
}
int history_handler(struct mg_connection *conn, void *cbdata)
{
const struct mg_request_info *req_info = mg_get_request_info(conn);
const char *cookie = mg_get_header(conn, "Cookie");
char history_str[64];
mg_get_cookie(cookie, "history", history_str, sizeof(history_str));
mg_printf(conn, "HTTP/1.1 200 OK\r\n");
mg_printf(conn, "Connection: close\r\n");
mg_printf(conn, "Set-Cookie: history='%s'\r\n", req_info->local_uri);
mg_printf(conn, "Content-Type: text/html\r\n\r\n");
mg_printf(conn, "<html><body>");
mg_printf(conn, "<h3>Your URI is: %s<h3>\n", req_info->local_uri);
if (history_str[0] == 0) {
mg_printf(conn, "<h5>This is your first visit.</h5>\n");
} else {
mg_printf(conn, "<h5>your last /history visit was: %s</h5>\n",
history_str);
}
mg_printf(conn, "Some cookie-saving links to try:\n");
mg_printf(conn, "<ul>\n");
mg_printf(conn, "<li><a href=/history/first>first</a></li>\n");
mg_printf(conn, "<li><a href=/history/second>second</a></li>\n");
mg_printf(conn, "<li><a href=/history/third>third</a></li>\n");
mg_printf(conn, "<li><a href=/history/fourth>fourth</a></li>\n");
mg_printf(conn, "<li><a href=/history/fifth>fifth</a></li>\n");
mg_printf(conn, "</ul>\n");
mg_printf(conn, "</body></html>\n");
return 200;
}
void *main_pthread(void *arg)
{
static const char * const options[] = {
"listening_ports",
STRINGIFY(HTTP_PORT),
"num_threads",
"1",
"max_request_size",
STRINGIFY(MAX_REQUEST_SIZE_BYTES),
NULL
};
struct mg_callbacks callbacks;
struct mg_context *ctx;
(void)arg;
memset(&callbacks, 0, sizeof(callbacks));
ctx = mg_start(&callbacks, 0, (const char **)options);
if (ctx == NULL) {
printf("Unable to start the server.");
return 0;
}
mg_set_request_handler(ctx, "/$", hello_world_handler, 0);
mg_set_request_handler(ctx, "/info$", system_info_handler, 0);
mg_set_request_handler(ctx, "/history", history_handler, 0);
return 0;
}
void main(void)
{
pthread_attr_t civetweb_attr;
pthread_t civetweb_thread;
(void)pthread_attr_init(&civetweb_attr);
(void)pthread_attr_setstack(&civetweb_attr, &civetweb_stack,
CIVETWEB_MAIN_THREAD_STACK_SIZE);
(void)pthread_create(&civetweb_thread, &civetweb_attr,
&main_pthread, 0);
}