mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-02 13:20:51 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7886a73807 | ||
|
|
ccc953318a | ||
|
|
684ae27dc2 | ||
|
|
08305b9000 | ||
|
|
69e8c0a92f | ||
|
|
8eceacc0d3 | ||
|
|
26b971b4a8 |
No files matched your search
+13
-2
@@ -2968,7 +2968,12 @@ size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
|
||||
n++;
|
||||
} else if (c == 's') {
|
||||
char *p = va_arg(*ap, char *);
|
||||
if (pr == ~0U) pr = p == NULL ? 0 : strlen(p);
|
||||
if (p != NULL && pr != ~0U) {
|
||||
for (j = 0; j < pr && p[j] != '\0'; j++) ; // portable strnlen()
|
||||
pr = j;
|
||||
} else {
|
||||
pr = p == NULL ? 0 : strlen(p);
|
||||
}
|
||||
for (j = 0; !minus && pr < w && j + pr < w; j++)
|
||||
n += scpy(out, param, &pad, 1);
|
||||
n += scpy(out, param, p, pr);
|
||||
@@ -4484,13 +4489,15 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||
static bool uri2path(const char *r, struct mg_str uri, char *buf, size_t len) {
|
||||
struct mg_str k, v, part, s = mg_str(r), u = {NULL, 0}, d = u;
|
||||
size_t n;
|
||||
bool matched = false;
|
||||
while (mg_span(s, &part, &s, ',')) {
|
||||
if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0);
|
||||
if (v.len == 0) v = k, k = mg_str("/"), u = k, d = v;
|
||||
if (uri.len < k.len) continue;
|
||||
if (mg_strcmp(k, mg_str_n(uri.buf, k.len)) != 0) continue;
|
||||
u = k, d = v;
|
||||
u = k, d = v, matched = true;
|
||||
}
|
||||
if (!matched) return false;
|
||||
n = mg_snprintf(buf, len, "%.*s", (int) d.len, d.buf);
|
||||
if (len == 0 || n + 2 >= len) return false; // Path overflow
|
||||
if (n > 0 && buf[n - 1] != '/') buf[n++] = '/', buf[n] = '\0'; // Add slash
|
||||
@@ -9399,6 +9406,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
: pkt->dhcp->siaddr ? pkt->dhcp->siaddr
|
||||
: pkt->ip->src);
|
||||
ifp->state = MG_TCPIP_STATE_REQ; // REQUESTING state
|
||||
ifp->lease_expire = ifp->now + 5000; // No ACK by then: start over
|
||||
} else if (msgtype == 5) { // DHCPACK
|
||||
if (ifp->state == MG_TCPIP_STATE_REQ && ip && gw && lease) { // got an IP
|
||||
uint64_t rand;
|
||||
@@ -10706,6 +10714,9 @@ static void mg_ip_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
if (ifp->enable_dhcp_client && s1) {
|
||||
if (ifp->state == MG_TCPIP_STATE_UP) {
|
||||
tx_dhcp_discover(ifp); // INIT (4.4.1)
|
||||
} else if (ifp->state == MG_TCPIP_STATE_REQ &&
|
||||
ifp->now >= ifp->lease_expire) {
|
||||
ifp->state = MG_TCPIP_STATE_UP; // REQUEST or ACK lost: DISCOVER again
|
||||
} else if (ifp->state == MG_TCPIP_STATE_READY &&
|
||||
ifp->lease_expire > 0) { // BOUND / RENEWING / REBINDING
|
||||
if (ifp->now >= ifp->lease_expire) {
|
||||
|
||||
@@ -4109,6 +4109,8 @@ struct mg_dash {
|
||||
struct mg_fs *upload_fs; // FS for uploads/listing, default &mg_fs_posix
|
||||
// Resolves the built-in file manager's root dir for user u, e.g. per-user
|
||||
// upload directories. NULL: file manager disabled
|
||||
// - The returned directory must be nonempty and must not contain ',' or '=',
|
||||
// because it is used as an mg_http_serve_opts::root_dir mapping target.
|
||||
bool (*files_dir)(const struct mg_dash_user *u, char *buf, size_t len);
|
||||
};
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ struct mg_dash {
|
||||
struct mg_fs *upload_fs; // FS for uploads/listing, default &mg_fs_posix
|
||||
// Resolves the built-in file manager's root dir for user u, e.g. per-user
|
||||
// upload directories. NULL: file manager disabled
|
||||
// - The returned directory must be nonempty and must not contain ',' or '=',
|
||||
// because it is used as an mg_http_serve_opts::root_dir mapping target.
|
||||
bool (*files_dir)(const struct mg_dash_user *u, char *buf, size_t len);
|
||||
};
|
||||
|
||||
|
||||
@@ -214,7 +214,12 @@ size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
|
||||
n++;
|
||||
} else if (c == 's') {
|
||||
char *p = va_arg(*ap, char *);
|
||||
if (pr == ~0U) pr = p == NULL ? 0 : strlen(p);
|
||||
if (p != NULL && pr != ~0U) {
|
||||
for (j = 0; j < pr && p[j] != '\0'; j++) ; // portable strnlen()
|
||||
pr = j;
|
||||
} else {
|
||||
pr = p == NULL ? 0 : strlen(p);
|
||||
}
|
||||
for (j = 0; !minus && pr < w && j + pr < w; j++)
|
||||
n += scpy(out, param, &pad, 1);
|
||||
n += scpy(out, param, p, pr);
|
||||
|
||||
+3
-1
@@ -734,13 +734,15 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||
static bool uri2path(const char *r, struct mg_str uri, char *buf, size_t len) {
|
||||
struct mg_str k, v, part, s = mg_str(r), u = {NULL, 0}, d = u;
|
||||
size_t n;
|
||||
bool matched = false;
|
||||
while (mg_span(s, &part, &s, ',')) {
|
||||
if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0);
|
||||
if (v.len == 0) v = k, k = mg_str("/"), u = k, d = v;
|
||||
if (uri.len < k.len) continue;
|
||||
if (mg_strcmp(k, mg_str_n(uri.buf, k.len)) != 0) continue;
|
||||
u = k, d = v;
|
||||
u = k, d = v, matched = true;
|
||||
}
|
||||
if (!matched) return false;
|
||||
n = mg_snprintf(buf, len, "%.*s", (int) d.len, d.buf);
|
||||
if (len == 0 || n + 2 >= len) return false; // Path overflow
|
||||
if (n > 0 && buf[n - 1] != '/') buf[n++] = '/', buf[n] = '\0'; // Add slash
|
||||
|
||||
@@ -734,6 +734,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
: pkt->dhcp->siaddr ? pkt->dhcp->siaddr
|
||||
: pkt->ip->src);
|
||||
ifp->state = MG_TCPIP_STATE_REQ; // REQUESTING state
|
||||
ifp->lease_expire = ifp->now + 5000; // No ACK by then: start over
|
||||
} else if (msgtype == 5) { // DHCPACK
|
||||
if (ifp->state == MG_TCPIP_STATE_REQ && ip && gw && lease) { // got an IP
|
||||
uint64_t rand;
|
||||
@@ -2041,6 +2042,9 @@ static void mg_ip_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
if (ifp->enable_dhcp_client && s1) {
|
||||
if (ifp->state == MG_TCPIP_STATE_UP) {
|
||||
tx_dhcp_discover(ifp); // INIT (4.4.1)
|
||||
} else if (ifp->state == MG_TCPIP_STATE_REQ &&
|
||||
ifp->now >= ifp->lease_expire) {
|
||||
ifp->state = MG_TCPIP_STATE_UP; // REQUEST or ACK lost: DISCOVER again
|
||||
} else if (ifp->state == MG_TCPIP_STATE_READY &&
|
||||
ifp->lease_expire > 0) { // BOUND / RENEWING / REBINDING
|
||||
if (ifp->now >= ifp->lease_expire) {
|
||||
|
||||
@@ -80,6 +80,10 @@ static void test_statechange(void) {
|
||||
onstatechange(&iface);
|
||||
ASSERT(executed == true);
|
||||
executed = false;
|
||||
iface.enable_dhcp_client = true; // DHCP REQUEST unanswered: start over
|
||||
iface.state = MG_TCPIP_STATE_REQ, iface.lease_expire = 0;
|
||||
mg_ip_poll(&iface, true);
|
||||
ASSERT(iface.state == MG_TCPIP_STATE_UP);
|
||||
}
|
||||
#if MG_ENABLE_IPV6
|
||||
static void mif6_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
|
||||
|
||||
@@ -1475,6 +1475,11 @@ static void h4(struct mg_connection *c, int ev, void *ev_data) {
|
||||
opts.root_dir = "/a=./data";
|
||||
opts.page404 = "./data/404.html"; // existing 404 page
|
||||
mg_http_serve_dir(c, hm, &opts);
|
||||
} else if (mg_match(hm->uri, mg_str("/unmapped"), NULL)) {
|
||||
struct mg_http_serve_opts opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.root_dir = "/a=./data";
|
||||
mg_http_serve_dir(c, hm, &opts);
|
||||
} else if (mg_match(hm->uri, mg_str("/b/#"), NULL)) {
|
||||
struct mg_http_serve_opts opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
@@ -1502,6 +1507,7 @@ static void test_http_404(void) {
|
||||
ASSERT(cmpbody(buf, "hello\n") == 0);
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /a/a.txt HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, "hello\n") == 0);
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /unmapped HTTP/1.0\n\n") == 400);
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /b/a.txt HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, "hello\n") == 0);
|
||||
|
||||
@@ -2399,10 +2405,15 @@ static void test_str(void) {
|
||||
ASSERT(sn("%.*s", 1, "ab"));
|
||||
ASSERT(sn("%.1s", "ab"));
|
||||
ASSERT(sn("%.99s", "a"));
|
||||
ASSERT(sn("%10.8s", "abc"));
|
||||
ASSERT(sn("%-6.4s", "ab"));
|
||||
ASSERT(sn("%5.1s", ""));
|
||||
ASSERT(sn("%11s", "a"));
|
||||
ASSERT(sn("%s", "a\0b"));
|
||||
ASSERT(sn("%2s", "a"));
|
||||
ASSERT(sn("%.*s", 3, "a\0b"));
|
||||
ASSERT(mg_snprintf(NULL, 0, "%.8s", (char *) NULL) == 0);
|
||||
ASSERT(mg_snprintf(NULL, 0, "%8.4s", (char *) NULL) == 8);
|
||||
ASSERT(sn("%d", 7));
|
||||
ASSERT(sn("%d", 123));
|
||||
#if MG_ARCH == MG_ARCH_UNIX
|
||||
|
||||
@@ -43,6 +43,29 @@ bool mg_random(void *buf, size_t len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// BSD sockets API UDP echo server: sends each datagram back to its sender
|
||||
static int s_udp_sock = -1;
|
||||
|
||||
static void udp_echo_init(uint16_t port) {
|
||||
struct sockaddr_in sa = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(port),
|
||||
.sin_addr = {.s_addr = INADDR_ANY},
|
||||
};
|
||||
s_udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
bind(s_udp_sock, (struct sockaddr *) &sa, sizeof(sa));
|
||||
MG_INFO(("UDP echo server on port %hu, sock %d", port, s_udp_sock));
|
||||
}
|
||||
|
||||
static void udp_echo_poll(void) {
|
||||
char buf[1500];
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr *sa = (struct sockaddr *) &sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
ssize_t n = recvfrom(s_udp_sock, buf, sizeof(buf), MSG_DONTWAIT, sa, &len);
|
||||
if (n > 0) sendto(s_udp_sock, buf, (size_t) n, MSG_DONTWAIT, sa, len);
|
||||
}
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
@@ -83,10 +106,14 @@ int main(void) {
|
||||
// connections. Note - baremetal implementation is non-blocking only.
|
||||
echo_init(1234);
|
||||
|
||||
// This is BSD sockets API UDP echo server, non-blocking too
|
||||
udp_echo_init(1234);
|
||||
|
||||
// Baremetal superloop. Each function in the loop must not block
|
||||
for (;;) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
echo_poll();
|
||||
udp_echo_poll();
|
||||
blink_task();
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user