samples: net: Add civetweb HTTP sample
This commit adds civetweb as a west module and a sample that uses it. Signed-off-by: Tomasz Gorochowik <tgorochowik@antmicro.com> Signed-off-by: Piotr Zierhoffer <pzierhoffer@antmicro.com>
This commit is contained in:
parent
11d8f1a1e9
commit
f2bf9a17c5
10 changed files with 623 additions and 0 deletions
8
modules/Kconfig.civetweb
Normal file
8
modules/Kconfig.civetweb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2019 Antmicro Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config CIVETWEB
|
||||
bool "Civetweb Support"
|
||||
help
|
||||
This option enables the civetweb HTTP API.
|
8
samples/net/sockets/civetweb/CMakeLists.txt
Normal file
8
samples/net/sockets/civetweb/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(hello_world)
|
||||
|
||||
target_sources(app PRIVATE src/main.c src/libc_extensions.c)
|
34
samples/net/sockets/civetweb/prj.conf
Normal file
34
samples/net/sockets/civetweb/prj.conf
Normal file
|
@ -0,0 +1,34 @@
|
|||
# General config
|
||||
CONFIG_CIVETWEB=y
|
||||
CONFIG_JSON_LIBRARY=y
|
||||
|
||||
# pthreads
|
||||
CONFIG_POSIX_API=y
|
||||
CONFIG_PTHREAD_IPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
|
||||
# networking
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV4=y
|
||||
# CONFIG_NET_IPV6 is not set
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_SOCKETS=y
|
||||
CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=131072
|
||||
CONFIG_NET_TX_STACK_SIZE=8192
|
||||
CONFIG_NET_RX_STACK_SIZE=8192
|
||||
CONFIG_ISR_STACK_SIZE=8192
|
||||
CONFIG_MAIN_STACK_SIZE=8192
|
||||
CONFIG_IDLE_STACK_SIZE=2048
|
||||
CONFIG_SOC_SERIES_SAME70=y
|
||||
|
||||
CONFIG_DNS_RESOLVER=y
|
||||
|
||||
CONFIG_NET_CONFIG_SETTINGS=y
|
||||
CONFIG_NET_CONFIG_MY_IPV4_ADDR="10.0.0.111"
|
||||
CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0"
|
||||
CONFIG_NET_CONFIG_MY_IPV4_GW="10.0.0.116"
|
||||
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="10.0.0.116"
|
||||
|
||||
# logging
|
||||
CONFIG_NET_LOG=y
|
6
samples/net/sockets/civetweb/sample.yaml
Normal file
6
samples/net/sockets/civetweb/sample.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
sample:
|
||||
description: Civetweb HTTP API sample
|
||||
name: civetweb
|
||||
tests:
|
||||
sample.net.sockets.civetweb:
|
||||
platform_whitelist: sam_e70_xplained
|
28
samples/net/sockets/civetweb/src/external_log_access.inl
Normal file
28
samples/net/sockets/civetweb/src/external_log_access.inl
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
static void log_access(const struct mg_connection *conn)
|
||||
{
|
||||
const struct mg_request_info *ri;
|
||||
char src_addr[IP_ADDR_STR_LEN];
|
||||
|
||||
if (!conn || !conn->dom_ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
ri = &conn->request_info;
|
||||
|
||||
sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
|
||||
printf("%s - \"%s %s%s%s HTTP/%s\" %d\n",
|
||||
src_addr,
|
||||
ri->request_method ? ri->request_method : "-",
|
||||
ri->request_uri ? ri->request_uri : "-",
|
||||
ri->query_string ? "?" : "",
|
||||
ri->query_string ? ri->query_string : "",
|
||||
ri->http_version,
|
||||
conn->status_code);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
static void mg_cry_internal_impl(const struct mg_connection *conn,
|
||||
const char *func,
|
||||
unsigned line,
|
||||
const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
(void)conn;
|
||||
|
||||
printf("[INTERNAL ERROR]: %s @ %d\n", func, line);
|
||||
vprintf(fmt, ap);
|
||||
printf("\n");
|
||||
}
|
262
samples/net/sockets/civetweb/src/libc_extensions.c
Normal file
262
samples/net/sockets/civetweb/src/libc_extensions.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libc_extensions.h"
|
||||
|
||||
#define FN_MISSING() printf("[IMPLEMENTATION MISSING : %s]\n", __func__)
|
||||
|
||||
size_t strcspn(const char *s1, const char *s2)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < strlen(s2); ++i) {
|
||||
for (j = 0; j < strlen(s1); ++j) {
|
||||
if (s1[j] == s2[i]) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strlen(s1);
|
||||
}
|
||||
|
||||
int iscntrl(int c)
|
||||
{
|
||||
/* All the characters placed before the space on the ASCII table
|
||||
* and the 0x7F character (DEL) are control characters.
|
||||
*/
|
||||
return (int)(c < ' ' || c == 0x7F);
|
||||
}
|
||||
|
||||
size_t strftime(char *dst, size_t dst_size,
|
||||
const char *fmt,
|
||||
const struct tm *tm)
|
||||
{
|
||||
FN_MISSING();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double difftime(time_t end, time_t beg)
|
||||
{
|
||||
return end - beg;
|
||||
}
|
||||
|
||||
struct __strerr_wrap {
|
||||
int err;
|
||||
const char *errstr;
|
||||
};
|
||||
|
||||
/* Implementation suggested by @rakons in #16527 */
|
||||
#define STRERR_DEFINE(e) {e, #e}
|
||||
|
||||
static const struct __strerr_wrap error_strings[] = {
|
||||
STRERR_DEFINE(EILSEQ),
|
||||
STRERR_DEFINE(EDOM),
|
||||
STRERR_DEFINE(ERANGE),
|
||||
STRERR_DEFINE(ENOTTY),
|
||||
STRERR_DEFINE(EACCES),
|
||||
STRERR_DEFINE(EPERM),
|
||||
STRERR_DEFINE(ENOENT),
|
||||
STRERR_DEFINE(ESRCH),
|
||||
STRERR_DEFINE(EEXIST),
|
||||
STRERR_DEFINE(ENOSPC),
|
||||
STRERR_DEFINE(ENOMEM),
|
||||
STRERR_DEFINE(EBUSY),
|
||||
STRERR_DEFINE(EINTR),
|
||||
STRERR_DEFINE(EAGAIN),
|
||||
STRERR_DEFINE(ESPIPE),
|
||||
STRERR_DEFINE(EXDEV),
|
||||
STRERR_DEFINE(EROFS),
|
||||
STRERR_DEFINE(ENOTEMPTY),
|
||||
STRERR_DEFINE(ECONNRESET),
|
||||
STRERR_DEFINE(ETIMEDOUT),
|
||||
STRERR_DEFINE(ECONNREFUSED),
|
||||
STRERR_DEFINE(EHOSTDOWN),
|
||||
STRERR_DEFINE(EHOSTUNREACH),
|
||||
STRERR_DEFINE(EADDRINUSE),
|
||||
STRERR_DEFINE(EPIPE),
|
||||
STRERR_DEFINE(EIO),
|
||||
STRERR_DEFINE(ENXIO),
|
||||
STRERR_DEFINE(ENOTBLK),
|
||||
STRERR_DEFINE(ENODEV),
|
||||
STRERR_DEFINE(ENOTDIR),
|
||||
STRERR_DEFINE(EISDIR),
|
||||
STRERR_DEFINE(ETXTBSY),
|
||||
STRERR_DEFINE(ENOEXEC),
|
||||
STRERR_DEFINE(EINVAL),
|
||||
STRERR_DEFINE(E2BIG),
|
||||
STRERR_DEFINE(ELOOP),
|
||||
STRERR_DEFINE(ENAMETOOLONG),
|
||||
STRERR_DEFINE(ENFILE),
|
||||
STRERR_DEFINE(EMFILE),
|
||||
STRERR_DEFINE(EBADF),
|
||||
STRERR_DEFINE(ECHILD),
|
||||
STRERR_DEFINE(EFAULT),
|
||||
STRERR_DEFINE(EFBIG),
|
||||
STRERR_DEFINE(EMLINK),
|
||||
STRERR_DEFINE(ENOLCK),
|
||||
STRERR_DEFINE(EDEADLK),
|
||||
STRERR_DEFINE(ECANCELED),
|
||||
STRERR_DEFINE(ENOSYS),
|
||||
STRERR_DEFINE(ENOMSG),
|
||||
STRERR_DEFINE(ENOSTR),
|
||||
STRERR_DEFINE(ENODATA),
|
||||
STRERR_DEFINE(ETIME),
|
||||
STRERR_DEFINE(ENOSR),
|
||||
STRERR_DEFINE(EPROTO),
|
||||
STRERR_DEFINE(EBADMSG),
|
||||
STRERR_DEFINE(ENOTSOCK),
|
||||
STRERR_DEFINE(EDESTADDRREQ),
|
||||
STRERR_DEFINE(EMSGSIZE),
|
||||
STRERR_DEFINE(EPROTOTYPE),
|
||||
STRERR_DEFINE(ENOPROTOOPT),
|
||||
STRERR_DEFINE(EPROTONOSUPPORT),
|
||||
STRERR_DEFINE(ESOCKTNOSUPPORT),
|
||||
STRERR_DEFINE(ENOTSUP),
|
||||
STRERR_DEFINE(EPFNOSUPPORT),
|
||||
STRERR_DEFINE(EAFNOSUPPORT),
|
||||
STRERR_DEFINE(EADDRNOTAVAIL),
|
||||
STRERR_DEFINE(ENETDOWN),
|
||||
STRERR_DEFINE(ENETUNREACH),
|
||||
STRERR_DEFINE(ENETRESET),
|
||||
STRERR_DEFINE(ECONNABORTED),
|
||||
STRERR_DEFINE(ENOBUFS),
|
||||
STRERR_DEFINE(EISCONN),
|
||||
STRERR_DEFINE(ENOTCONN),
|
||||
STRERR_DEFINE(ESHUTDOWN),
|
||||
STRERR_DEFINE(EALREADY),
|
||||
STRERR_DEFINE(EINPROGRESS),
|
||||
};
|
||||
|
||||
static char *strerr_unknown = "UNKNOWN";
|
||||
|
||||
char *strerror(int err)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(error_strings); ++i) {
|
||||
if (error_strings[i].err == err) {
|
||||
return (char *)error_strings[i].errstr;
|
||||
}
|
||||
}
|
||||
|
||||
return strerr_unknown;
|
||||
}
|
||||
|
||||
int sscanf(const char *s, const char *format, ...)
|
||||
{
|
||||
FN_MISSING();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double atof(const char *str)
|
||||
{
|
||||
/* XXX good enough for civetweb uses */
|
||||
return (double)atoi(str);
|
||||
}
|
||||
|
||||
long long int strtoll(const char *str, char **endptr, int base)
|
||||
{
|
||||
/* XXX good enough for civetweb uses */
|
||||
return (long long int)strtol(str, endptr, base);
|
||||
}
|
||||
|
||||
time_t time(time_t *t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Most of the wrappers below are copies of the wrappers in net/sockets.h,
|
||||
* but they are available only if CONFIG_NET_SOCKETS_POSIX_NAMES is enabled
|
||||
* which is impossible here.
|
||||
*/
|
||||
|
||||
int getsockname(int sock, struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
return zsock_getsockname(sock, addr, addrlen);
|
||||
}
|
||||
|
||||
int poll(struct zsock_pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
return zsock_poll(fds, nfds, timeout);
|
||||
}
|
||||
|
||||
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen,
|
||||
char *serv, socklen_t servlen, int flags)
|
||||
{
|
||||
return zsock_getnameinfo(addr, addrlen, host, hostlen,
|
||||
serv, servlen, flags);
|
||||
}
|
||||
|
||||
ssize_t send(int sock, const void *buf, size_t len, int flags)
|
||||
{
|
||||
return zsock_send(sock, buf, len, flags);
|
||||
}
|
||||
|
||||
ssize_t recv(int sock, void *buf, size_t max_len, int flags)
|
||||
{
|
||||
return zsock_recv(sock, buf, max_len, flags);
|
||||
}
|
||||
|
||||
int socket(int family, int type, int proto)
|
||||
{
|
||||
return zsock_socket(family, type, proto);
|
||||
}
|
||||
|
||||
int getaddrinfo(const char *host, const char *service,
|
||||
const struct zsock_addrinfo *hints,
|
||||
struct zsock_addrinfo **res)
|
||||
{
|
||||
return zsock_getaddrinfo(host, service, hints, res);
|
||||
}
|
||||
|
||||
void freeaddrinfo(struct zsock_addrinfo *ai)
|
||||
{
|
||||
zsock_freeaddrinfo(ai);
|
||||
}
|
||||
|
||||
int connect(int sock, const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
return zsock_connect(sock, addr, addrlen);
|
||||
}
|
||||
|
||||
int getsockopt(int sock, int level, int optname,
|
||||
void *optval, socklen_t *optlen)
|
||||
{
|
||||
return zsock_getsockopt(sock, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int setsockopt(int sock, int level, int optname,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
return zsock_setsockopt(sock, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int listen(int sock, int backlog)
|
||||
{
|
||||
return zsock_listen(sock, backlog);
|
||||
}
|
||||
|
||||
int bind(int sock, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
return zsock_bind(sock, addr, addrlen);
|
||||
}
|
||||
|
||||
int accept(int sock, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
return zsock_accept(sock, addr, addrlen);
|
||||
}
|
72
samples/net/sockets/civetweb/src/libc_extensions.h
Normal file
72
samples/net/sockets/civetweb/src/libc_extensions.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/socket.h>
|
||||
|
||||
#define pollfd zsock_pollfd
|
||||
#define fcntl zsock_fcntl
|
||||
|
||||
#define POLLIN ZSOCK_POLLIN
|
||||
#define POLLOUT ZSOCK_POLLOUT
|
||||
|
||||
#define addrinfo zsock_addrinfo
|
||||
|
||||
#define F_SETFD 2
|
||||
#define FD_CLOEXEC 1
|
||||
|
||||
size_t strcspn(const char *s1, const char *s2);
|
||||
size_t strspn(const char *s1, const char *s2);
|
||||
int iscntrl(int c);
|
||||
|
||||
double atof(const char *str);
|
||||
long long int strtoll(const char *str, char **endptr, int base);
|
||||
int sscanf(const char *s, const char *format, ...);
|
||||
char *strerror(int err);
|
||||
unsigned long long int strtoull(const char *str, char **endptr, int base);
|
||||
|
||||
time_t time(time_t *t);
|
||||
struct tm *gmtime(const time_t *ptime);
|
||||
size_t strftime(char *dst, size_t dst_size, const char *fmt,
|
||||
const struct tm *tm);
|
||||
double difftime(time_t end, time_t beg);
|
||||
struct tm *localtime(const time_t *timer);
|
||||
|
||||
int fileno(FILE *stream);
|
||||
int ferror(FILE *stream);
|
||||
int fclose(FILE *stream);
|
||||
int fseeko(FILE *stream, off_t offset, int whence);
|
||||
FILE *fopen(const char *filename, const char *mode);
|
||||
char *fgets(char *str, int num, FILE *stream);
|
||||
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
|
||||
int remove(const char *filename);
|
||||
|
||||
int getsockname(int sock, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int poll(struct zsock_pollfd *fds, int nfds, int timeout);
|
||||
|
||||
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen,
|
||||
char *serv, socklen_t servlen, int flags);
|
||||
|
||||
ssize_t send(int sock, const void *buf, size_t len, int flags);
|
||||
ssize_t recv(int sock, void *buf, size_t max_len, int flags);
|
||||
int socket(int family, int type, int proto);
|
||||
int getaddrinfo(const char *host, const char *service,
|
||||
const struct zsock_addrinfo *hints,
|
||||
struct zsock_addrinfo **res);
|
||||
|
||||
void freeaddrinfo(struct zsock_addrinfo *ai);
|
||||
int connect(int sock, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int getsockopt(int sock, int level, int optname,
|
||||
void *optval, socklen_t *optlen);
|
||||
int setsockopt(int sock, int level, int optname,
|
||||
const void *optval, socklen_t optlen);
|
||||
int listen(int sock, int backlog);
|
||||
int accept(int sock, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int bind(int sock, const struct sockaddr *addr, socklen_t addrlen);
|
181
samples/net/sockets/civetweb/src/main.c
Normal file
181
samples/net/sockets/civetweb/src/main.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <posix/pthread.h>
|
||||
#include <json.h>
|
||||
|
||||
#include "civetweb.h"
|
||||
|
||||
#define CIVETWEB_MAIN_THREAD_STACK_SIZE 4096
|
||||
|
||||
K_THREAD_STACK_DEFINE(civetweb_stack, CIVETWEB_MAIN_THREAD_STACK_SIZE);
|
||||
|
||||
struct civetweb_info {
|
||||
const char *version;
|
||||
const char *os;
|
||||
u32_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, "</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",
|
||||
"8080",
|
||||
"num_threads",
|
||||
"1",
|
||||
"max_request_size",
|
||||
"2048",
|
||||
0
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pthread_attr_t civetweb_attr;
|
||||
pthread_t civetweb_thread;
|
||||
|
||||
pthread_attr_init(&civetweb_attr);
|
||||
pthread_attr_setstack(&civetweb_attr, &civetweb_stack,
|
||||
CIVETWEB_MAIN_THREAD_STACK_SIZE);
|
||||
|
||||
pthread_create(&civetweb_thread, &civetweb_attr, &main_pthread, 0);
|
||||
|
||||
return 0;
|
||||
}
|
6
west.yml
6
west.yml
|
@ -25,6 +25,8 @@ manifest:
|
|||
remotes:
|
||||
- name: upstream
|
||||
url-base: https://github.com/zephyrproject-rtos
|
||||
- name: civetweb
|
||||
url-base: https://github.com/antmicro
|
||||
|
||||
#
|
||||
# Please add items below based on alphabetical order
|
||||
|
@ -32,6 +34,10 @@ manifest:
|
|||
- name: ci-tools
|
||||
revision: d56f2dd3510e20fa8cf4aad442495c08a658113f
|
||||
path: tools/ci-tools
|
||||
- name: civetweb
|
||||
remote: civetweb
|
||||
revision: 7ffad765f9a63a7bab3432ca45248981f559d559
|
||||
path: modules/lib/civetweb
|
||||
- name: esp-idf
|
||||
revision: 6835bfc741bf15e98fb7971293913f770df6081f
|
||||
path: modules/hal/esp-idf
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue