move to new skeleton

This commit is contained in:
Sergio R. Caprile committed 2024-05-01 14:42:21 -03:00
1 parent 81f90c7b51
commit 2be30a3193
26 files changed
+8 -8

No files matched your search

+1 -1
View File
@@ -1 +1 @@
See detailed tutorial at https://mongoose.ws/tutorials/http-server/
See detailed tutorial at https://mongoose.ws/tutorials/http/http-server/
+1 -1
View File
@@ -1 +1 @@
See detailed tutorial at https://mongoose.ws/tutorials/http-server/
See detailed tutorial at https://mongoose.ws/tutorials/http/http-server/
+25
View File
@@ -0,0 +1,25 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
CC = gcc # Use MinGW gcc compiler
CFLAGS += -lws2_32 # Link against Winsock library
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
OUT ?= -o $(PROG) # Build output
endif
all: $(PROG) # Default target. Build and run program
$(RUN) ./$(PROG) $(ARGS)
$(PROG): $(SOURCES) # Build program from sources
$(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(OUT)
clean: # Cleanup. Delete built program and all build artifacts
$(DELETE) $(PROG) *.o *.obj *.exe *.dSYM
+1
View File
@@ -0,0 +1 @@
See detailed tutorial at https://mongoose.ws/tutorials/http/huge-response/
+89
View File
@@ -0,0 +1,89 @@
// Copyright (c) 2021 Cesanta Software Limited
// All rights reserved
//
// Example that demonstrates how to send a large responses with limited memory.
// We're going to send a JSON array of many integer values, s_data.
// The idea is to send a response in small chunks, and let the client request
// the next chunk.
// Periodically, s_data changes, which is tracked by s_version.
// Client requests a range and a version, to ensure data integrity.
//
// 1. Start this server, type `make`
// 2. Open http://localhost:8000 in your browser
#include "mongoose.h"
static const char *s_listen_on = "http://localhost:8000";
static const char *s_root_dir = "web_root";
#define DATA_SIZE 10000 // Total number of elements
#define CHUNK_SIZE 100 // Max number returned in one API call
static int s_data[DATA_SIZE]; // Simulate some complex big data
static long s_version = 0; // Data "version"
static long getparam(struct mg_http_message *hm, const char *json_path) {
double dv = 0;
mg_json_get_num(hm->body, json_path, &dv);
return dv;
}
static size_t printdata(mg_pfn_t out, void *ptr, va_list *ap) {
unsigned start = va_arg(*ap, unsigned);
unsigned max = start + CHUNK_SIZE;
const char *comma = "";
size_t n = 0;
if (max > DATA_SIZE) max = DATA_SIZE;
while (start < max) {
n += mg_xprintf(out, ptr, "%s%d", comma, s_data[start]);
comma = ",";
start++;
}
return n;
}
static void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = ev_data;
if (mg_match(hm->uri, mg_str("/api/data"), NULL)) {
const char *headers = "content-type: text/json\r\n";
long start = getparam(hm, "$.start");
long version = getparam(hm, "$.version");
MG_DEBUG(("%.*s", (int) hm->body.len, hm->body.buf));
if (version > 0 && version != s_version) {
// Version mismatch: s_data has changed while client fetches it
// Tell client to restart
mg_http_reply(c, 200, headers, "{%m:%m, %m:%ld}", MG_ESC("error"),
MG_ESC("wrong version"), MG_ESC("version"), version);
} else {
// Return data, up to CHUNK_SIZE elements
mg_http_reply(c, 200, headers, "{%m:%ld,%m:%ld,%m:[%M]}",
MG_ESC("version"), s_version, MG_ESC("start"), start,
MG_ESC("data"), printdata, start);
}
} else {
struct mg_http_serve_opts opts = {0};
opts.root_dir = s_root_dir;
mg_http_serve_dir(c, hm, &opts);
}
}
}
static void timer_fn(void *arg) {
for (int i = 0; i < DATA_SIZE; i++) {
s_data[i] = rand();
}
s_version++;
(void) arg;
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr);
srand(time(NULL));
mg_timer_add(&mgr, 5000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, NULL);
mg_http_listen(&mgr, s_listen_on, fn, NULL);
MG_INFO(("Listening on %s", s_listen_on));
for (;;) mg_mgr_poll(&mgr, 1000);
mg_mgr_free(&mgr);
return 0;
}
+1
View File
@@ -0,0 +1 @@
../../../mongoose.c
+1
View File
@@ -0,0 +1 @@
../../../mongoose.h
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>example</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
#container { margin-right: auto; margin-left: auto; max-width: 480px; }
#info { background: #e0f0f0; border-radius: .5em; padding: 2em; margin-bottom: 1em; }
#result { margin-top: 1em; }
</style>
</head>
<body>
<div id="container">
<div id="info">
On devices with limited RAM, it is important to limit the response size
of API calls. This example demonstrates how to fetch a large
data in smaller chunks, and guarantee its integrity.
Data gets returned in a series of request/response transactions,
where each response is small enough to fit into available device RAM.
<br/><br/>
Data integrity is implemented by versioning.
The idea is that the first response includes the current "version" of the
data, and that version is passed to all subsequent requests.
If data version changes in the middle of the request series,
client fails with 'wrong version' error.
</div>
<button id="btn">fetch data</button>
<div id="result"></div>
</div>
</body>
<script>
const getchunk = (start, version) =>
fetch('/api/data', {method: 'POST', body:JSON.stringify({start, version})})
.then(r => r.json());
document.getElementById('btn').onclick = function() {
var data = [], version = 0;
const load = offset => getchunk(offset, version)
.then(r => {
// console.log(r);
if (r.error) {
document.getElementById('result').innerText = 'Error: ' + r.error;
} else {
version = r.version;
data = data.concat(r.data);
if (r.data.length == 0) {
document.getElementById('result').innerText = 'Version: ' +
version + ', data: \n' +
JSON.stringify(data, null, 2);
} else {
load(offset + r.data.length, version);
}
}
});
load(0);
};
</script>
</html>
+25
View File
@@ -0,0 +1,25 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
#CFLAGS_MONGOOSE += -DMG_ENABLE_LINES
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
CC = gcc # Use MinGW gcc compiler
CFLAGS += -lws2_32 # Link against Winsock library
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
OUT ?= -o $(PROG) # Build output
endif
all: $(PROG) # Default target. Build and run program
$(RUN) ./$(PROG) $(ARGS)
$(PROG): $(SOURCES) # Build program from sources
$(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(OUT)
clean: # Cleanup. Delete built program and all build artifacts
$(DELETE) $(PROG) *.o *.obj *.exe *.dSYM
+1
View File
@@ -0,0 +1 @@
See detailed tutorial at https://mongoose.ws/tutorials/http/video-stream/
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+64
View File
@@ -0,0 +1,64 @@
// Copyright (c) 2020 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
// HTTP request handler function. It implements the following endpoints:
// /api/video1 - hangs forever, returns MJPEG video stream
// all other URI - serves web_root/ directory
static void cb(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/api/video1"), NULL)) {
c->data[0] = 'S'; // Mark that connection as live streamer
mg_printf(
c, "%s",
"HTTP/1.0 200 OK\r\n"
"Cache-Control: no-cache\r\n"
"Pragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\n"
"Content-Type: multipart/x-mixed-replace; boundary=--foo\r\n\r\n");
} else {
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
mg_http_serve_dir(c, ev_data, &opts);
}
}
}
// The image stream is simulated by sending MJPEG frames specified by the
// "files" array of file names.
static void broadcast_mjpeg_frame(struct mg_mgr *mgr) {
const char *files[] = {"images/1.jpg", "images/2.jpg", "images/3.jpg",
"images/4.jpg", "images/5.jpg", "images/6.jpg"};
size_t nfiles = sizeof(files) / sizeof(files[0]);
static size_t i;
const char *path = files[i++ % nfiles];
struct mg_str data = mg_file_read(&mg_fs_posix, path); // Read next file
struct mg_connection *c;
for (c = mgr->conns; c != NULL; c = c->next) {
if (c->data[0] != 'S') continue; // Skip non-stream connections
if (data.buf == NULL) continue; // Skip on file read error
mg_printf(c,
"--foo\r\nContent-Type: image/jpeg\r\n"
"Content-Length: %lu\r\n\r\n",
data.len);
mg_send(c, data.buf, data.len);
mg_send(c, "\r\n", 2);
}
free((void *) data.buf);
}
static void timer_callback(void *arg) {
broadcast_mjpeg_frame(arg);
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr);
mg_http_listen(&mgr, "http://localhost:8000", cb, NULL);
mg_timer_add(&mgr, 500, MG_TIMER_REPEAT, timer_callback, &mgr);
for (;;) mg_mgr_poll(&mgr, 50);
mg_mgr_free(&mgr);
return 0;
}
+1
View File
@@ -0,0 +1 @@
../../../mongoose.c
+1
View File
@@ -0,0 +1 @@
../../../mongoose.h
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>example</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
#container { margin-right: auto; margin-left: auto; max-width: 480px; }
#info { background: #e0f0f0; border-radius: .5em; padding: 2em; }
img { width: 100%; margin-top: 1em; border: 1px solid #ccc; }
</style>
</head>
<body>
<div id="container">
<div id="info">
A div below shows live MJPEG video stream from the server, which
is simulated by reading files from the images/ directory.
<br/><br/>
You can also use <code>curl</code> command-line utility:
<br/><code>curl localhost:8000/api/video1</code>
</div>
<img src="/api/video1" />
</div>
</body>
</html>