mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-06 15:51:25 +00:00
remove fn_data from event handler signature
This commit is contained in:
1 parent
b8bfa5565b
commit
deca1aaf46
77 files changed
+2839
-2259
No files matched your search
+302
-309
@@ -852,8 +852,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *fn_data) {
|
||||
static void dns_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct dns_data *d, *tmp;
|
||||
struct dns_data **head = (struct dns_data **) &c->mgr->active_dns_requests;
|
||||
if (ev == MG_EV_POLL) {
|
||||
@@ -907,7 +906,6 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
mg_dns_free(head, d);
|
||||
}
|
||||
}
|
||||
(void) fn_data;
|
||||
}
|
||||
|
||||
static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
@@ -1006,8 +1004,8 @@ void mg_call(struct mg_connection *c, int ev, void *ev_data) {
|
||||
// Run user-defined handler first, in order to give it an ability
|
||||
// to intercept processing (e.g. clean input buffer) before the
|
||||
// protocol handler kicks in
|
||||
if (c->fn != NULL) c->fn(c, ev, ev_data, c->fn_data);
|
||||
if (c->pfn != NULL) c->pfn(c, ev, ev_data, c->pfn_data);
|
||||
if (c->fn != NULL) c->fn(c, ev, ev_data);
|
||||
if (c->pfn != NULL) c->pfn(c, ev, ev_data);
|
||||
}
|
||||
|
||||
void mg_error(struct mg_connection *c, const char *fmt, ...) {
|
||||
@@ -1018,7 +1016,7 @@ void mg_error(struct mg_connection *c, const char *fmt, ...) {
|
||||
va_end(ap);
|
||||
MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
|
||||
c->is_closing = 1; // Set is_closing before sending MG_EV_CALL
|
||||
mg_call(c, MG_EV_ERROR, buf); // Let user handler to override it
|
||||
mg_call(c, MG_EV_ERROR, buf); // Let user handler override it
|
||||
}
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
@@ -2286,7 +2284,7 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
||||
c->is_resp = 0;
|
||||
}
|
||||
|
||||
static void http_cb(struct mg_connection *, int, void *, void *);
|
||||
static void http_cb(struct mg_connection *, int, void *);
|
||||
static void restore_http_cb(struct mg_connection *c) {
|
||||
mg_fs_close((struct mg_fd *) c->pfn_data);
|
||||
c->pfn_data = NULL;
|
||||
@@ -2300,10 +2298,9 @@ char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void static_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *fn_data) {
|
||||
static void static_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_WRITE || ev == MG_EV_POLL) {
|
||||
struct mg_fd *fd = (struct mg_fd *) fn_data;
|
||||
struct mg_fd *fd = (struct mg_fd *) c->pfn_data;
|
||||
// Read to send IO buffer directly, avoid extra on-stack buffer
|
||||
size_t n, max = MG_IO_SIZE, space;
|
||||
size_t *cl = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
|
||||
@@ -2828,7 +2825,7 @@ static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
|
||||
return i + 2 + n + 2;
|
||||
}
|
||||
|
||||
static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_READ || ev == MG_EV_CLOSE) {
|
||||
struct mg_http_message hm;
|
||||
size_t ofs = 0; // Parsing offset
|
||||
@@ -2890,10 +2887,10 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
}
|
||||
if (ofs > 0) mg_iobuf_del(&c->recv, 0, ofs); // Delete processed data
|
||||
}
|
||||
(void) evd, (void) fnd;
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
static void mg_hfn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
|
||||
static void mg_hfn(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_http_match_uri(hm, "/quit")) {
|
||||
@@ -2908,7 +2905,7 @@ static void mg_hfn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
|
||||
mg_http_reply(c, 200, "", "hi\n");
|
||||
}
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
if (c->data[0] == 'X') *(bool *) fnd = true;
|
||||
if (c->data[0] == 'X') *(bool *) c->fn_data = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4062,7 +4059,8 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, uint8_t version,
|
||||
}
|
||||
if (p > end) return MQTT_MALFORMED;
|
||||
if (version == 5 && p + 2 < end) {
|
||||
len_len = (uint32_t) decode_varint(p, (size_t) (end - p), &m->props_size);
|
||||
len_len =
|
||||
(uint32_t) decode_varint(p, (size_t) (end - p), &m->props_size);
|
||||
if (!len_len) return MQTT_MALFORMED;
|
||||
m->props_start = (size_t) (p + len_len - buf);
|
||||
p += len_len + m->props_size;
|
||||
@@ -4078,8 +4076,7 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, uint8_t version,
|
||||
return MQTT_OK;
|
||||
}
|
||||
|
||||
static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *fn_data) {
|
||||
static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_READ) {
|
||||
for (;;) {
|
||||
uint8_t version = c->is_mqtt5 ? 5 : 4;
|
||||
@@ -4147,7 +4144,6 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
}
|
||||
}
|
||||
(void) ev_data;
|
||||
(void) fn_data;
|
||||
}
|
||||
|
||||
void mg_mqtt_ping(struct mg_connection *nc) {
|
||||
@@ -4191,289 +4187,6 @@ struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
||||
return c;
|
||||
}
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/net.c"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
|
||||
size_t old = c->send.len;
|
||||
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
|
||||
return c->send.len - old;
|
||||
}
|
||||
|
||||
size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
size_t len = 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vprintf(c, fmt, &ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
|
||||
uint32_t localhost = mg_htonl(0x7f000001);
|
||||
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
||||
memcpy(addr->ip, &localhost, sizeof(uint32_t));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
||||
if (str.len > 0) return false;
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
size_t i, num_dots = 0;
|
||||
for (i = 0; i < str.len; i++) {
|
||||
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
||||
int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
|
||||
if (octet > 255) return false;
|
||||
data[num_dots] = (uint8_t) octet;
|
||||
} else if (str.ptr[i] == '.') {
|
||||
if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
|
||||
num_dots++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (num_dots != 3 || str.ptr[i - 1] == '.') return false;
|
||||
memcpy(&addr->ip, data, sizeof(data));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
|
||||
int i;
|
||||
uint32_t ipv4;
|
||||
if (str.len < 14) return false;
|
||||
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
||||
for (i = 2; i < 6; i++) {
|
||||
if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
|
||||
}
|
||||
// struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7);
|
||||
if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
|
||||
memcpy(&ipv4, addr->ip, sizeof(ipv4));
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->ip[10] = addr->ip[11] = 255;
|
||||
memcpy(&addr->ip[12], &ipv4, 4);
|
||||
addr->is_ip6 = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
|
||||
size_t i, j = 0, n = 0, dc = 42;
|
||||
addr->scope_id = 0;
|
||||
if (str.len > 2 && str.ptr[0] == '[') str.ptr++, str.len -= 2;
|
||||
if (mg_v4mapped(str, addr)) return true;
|
||||
for (i = 0; i < str.len; i++) {
|
||||
if ((str.ptr[i] >= '0' && str.ptr[i] <= '9') ||
|
||||
(str.ptr[i] >= 'a' && str.ptr[i] <= 'f') ||
|
||||
(str.ptr[i] >= 'A' && str.ptr[i] <= 'F')) {
|
||||
unsigned long val;
|
||||
if (i > j + 3) return false;
|
||||
// MG_DEBUG(("%lu %lu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
||||
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
||||
addr->ip[n] = (uint8_t) ((val >> 8) & 255);
|
||||
addr->ip[n + 1] = (uint8_t) (val & 255);
|
||||
} else if (str.ptr[i] == ':') {
|
||||
j = i + 1;
|
||||
if (i > 0 && str.ptr[i - 1] == ':') {
|
||||
dc = n; // Double colon
|
||||
if (i > 1 && str.ptr[i - 2] == ':') return false;
|
||||
} else if (i > 0) {
|
||||
n += 2;
|
||||
}
|
||||
if (n > 14) return false;
|
||||
addr->ip[n] = addr->ip[n + 1] = 0; // For trailing ::
|
||||
} else if (str.ptr[i] == '%') { // Scope ID
|
||||
for (i = i + 1; i < str.len; i++) {
|
||||
if (str.ptr[i] < '0' || str.ptr[i] > '9') return false;
|
||||
addr->scope_id = (uint8_t) (addr->scope_id * 10);
|
||||
addr->scope_id = (uint8_t) (addr->scope_id + (str.ptr[i] - '0'));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (n < 14 && dc == 42) return false;
|
||||
if (n < 14) {
|
||||
memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
|
||||
memset(&addr->ip[dc], 0, 14 - n);
|
||||
}
|
||||
|
||||
addr->is_ip6 = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr) {
|
||||
// MG_INFO(("[%.*s]", (int) str.len, str.ptr));
|
||||
return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton4(str, addr) ||
|
||||
mg_aton6(str, addr);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
|
||||
struct mg_connection *c =
|
||||
(struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
|
||||
if (c != NULL) {
|
||||
c->mgr = mgr;
|
||||
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
|
||||
c->id = ++mgr->nextid;
|
||||
MG_PROF_INIT(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void mg_close_conn(struct mg_connection *c) {
|
||||
mg_resolve_cancel(c); // Close any pending DNS query
|
||||
LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
|
||||
if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
|
||||
if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
|
||||
// Order of operations is important. `MG_EV_CLOSE` event must be fired
|
||||
// before we deallocate received data, see #1331
|
||||
mg_call(c, MG_EV_CLOSE, NULL);
|
||||
MG_DEBUG(("%lu %ld closed", c->id, c->fd));
|
||||
MG_PROF_DUMP(c);
|
||||
MG_PROF_FREE(c);
|
||||
|
||||
mg_tls_free(c);
|
||||
mg_iobuf_free(&c->recv);
|
||||
mg_iobuf_free(&c->send);
|
||||
mg_iobuf_free(&c->rtls);
|
||||
mg_bzero((unsigned char *) c, sizeof(*c));
|
||||
free(c);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = NULL;
|
||||
if (url == NULL || url[0] == '\0') {
|
||||
MG_ERROR(("null url"));
|
||||
} else if ((c = mg_alloc_conn(mgr)) == NULL) {
|
||||
MG_ERROR(("OOM"));
|
||||
} else {
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
c->is_udp = (strncmp(url, "udp:", 4) == 0);
|
||||
c->fd = (void *) (size_t) MG_INVALID_SOCKET;
|
||||
c->fn = fn;
|
||||
c->is_client = true;
|
||||
c->fn_data = fn_data;
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
mg_call(c, MG_EV_OPEN, (void *) url);
|
||||
mg_resolve(c, url);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = NULL;
|
||||
if ((c = mg_alloc_conn(mgr)) == NULL) {
|
||||
MG_ERROR(("OOM %s", url));
|
||||
} else if (!mg_open_listener(c, url)) {
|
||||
MG_ERROR(("Failed: %s, errno %d", url, errno));
|
||||
MG_PROF_FREE(c);
|
||||
free(c);
|
||||
c = NULL;
|
||||
} else {
|
||||
c->is_listening = 1;
|
||||
c->is_udp = strncmp(url, "udp:", 4) == 0;
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
c->fn = fn;
|
||||
c->fn_data = fn_data;
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = mg_alloc_conn(mgr);
|
||||
if (c != NULL) {
|
||||
c->fd = (void *) (size_t) fd;
|
||||
c->fn = fn;
|
||||
c->fn_data = fn_data;
|
||||
MG_EPOLL_ADD(c);
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
|
||||
unsigned flags, void (*fn)(void *), void *arg) {
|
||||
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
|
||||
if (t != NULL) {
|
||||
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
|
||||
t->id = mgr->timerid++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||
if (c->rtls.len == 0) return MG_IO_WAIT;
|
||||
if (len > c->rtls.len) len = c->rtls.len;
|
||||
memcpy(buf, c->rtls.buf, len);
|
||||
mg_iobuf_del(&c->rtls, 0, len);
|
||||
return (long) len;
|
||||
}
|
||||
|
||||
void mg_mgr_free(struct mg_mgr *mgr) {
|
||||
struct mg_connection *c;
|
||||
struct mg_timer *tmp, *t = mgr->timers;
|
||||
while (t != NULL) tmp = t->next, free(t), t = tmp;
|
||||
mgr->timers = NULL; // Important. Next call to poll won't touch timers
|
||||
for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
|
||||
mg_mgr_poll(mgr, 0);
|
||||
#if MG_ENABLE_FREERTOS_TCP
|
||||
FreeRTOS_DeleteSocketSet(mgr->ss);
|
||||
#endif
|
||||
MG_DEBUG(("All connections closed"));
|
||||
#if MG_ENABLE_EPOLL
|
||||
if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
|
||||
#endif
|
||||
mg_tls_ctx_free(mgr);
|
||||
}
|
||||
|
||||
void mg_mgr_init(struct mg_mgr *mgr) {
|
||||
memset(mgr, 0, sizeof(*mgr));
|
||||
#if MG_ENABLE_EPOLL
|
||||
if ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
|
||||
MG_ERROR(("epoll_create1 errno %d", errno));
|
||||
#else
|
||||
mgr->epoll_fd = -1;
|
||||
#endif
|
||||
#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
|
||||
// clang-format off
|
||||
{ WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
|
||||
// clang-format on
|
||||
#elif MG_ENABLE_FREERTOS_TCP
|
||||
mgr->ss = FreeRTOS_CreateSocketSet();
|
||||
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
|
||||
// Ignore SIGPIPE signal, so if client cancels the request, it
|
||||
// won't kill the whole process.
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
mgr->pipe = MG_INVALID_SOCKET;
|
||||
mgr->dnstimeout = 3000;
|
||||
mgr->dns4.url = "udp://8.8.8.8:53";
|
||||
mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
|
||||
mg_tls_ctx_init(mgr);
|
||||
}
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/net_builtin.c"
|
||||
#endif
|
||||
@@ -5583,6 +5296,289 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
}
|
||||
#endif // MG_ENABLE_TCPIP
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/net.c"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
|
||||
size_t old = c->send.len;
|
||||
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
|
||||
return c->send.len - old;
|
||||
}
|
||||
|
||||
size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
size_t len = 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vprintf(c, fmt, &ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
|
||||
uint32_t localhost = mg_htonl(0x7f000001);
|
||||
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
||||
memcpy(addr->ip, &localhost, sizeof(uint32_t));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
||||
if (str.len > 0) return false;
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
size_t i, num_dots = 0;
|
||||
for (i = 0; i < str.len; i++) {
|
||||
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
||||
int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
|
||||
if (octet > 255) return false;
|
||||
data[num_dots] = (uint8_t) octet;
|
||||
} else if (str.ptr[i] == '.') {
|
||||
if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
|
||||
num_dots++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (num_dots != 3 || str.ptr[i - 1] == '.') return false;
|
||||
memcpy(&addr->ip, data, sizeof(data));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
|
||||
int i;
|
||||
uint32_t ipv4;
|
||||
if (str.len < 14) return false;
|
||||
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
||||
for (i = 2; i < 6; i++) {
|
||||
if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
|
||||
}
|
||||
// struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7);
|
||||
if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
|
||||
memcpy(&ipv4, addr->ip, sizeof(ipv4));
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->ip[10] = addr->ip[11] = 255;
|
||||
memcpy(&addr->ip[12], &ipv4, 4);
|
||||
addr->is_ip6 = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
|
||||
size_t i, j = 0, n = 0, dc = 42;
|
||||
addr->scope_id = 0;
|
||||
if (str.len > 2 && str.ptr[0] == '[') str.ptr++, str.len -= 2;
|
||||
if (mg_v4mapped(str, addr)) return true;
|
||||
for (i = 0; i < str.len; i++) {
|
||||
if ((str.ptr[i] >= '0' && str.ptr[i] <= '9') ||
|
||||
(str.ptr[i] >= 'a' && str.ptr[i] <= 'f') ||
|
||||
(str.ptr[i] >= 'A' && str.ptr[i] <= 'F')) {
|
||||
unsigned long val;
|
||||
if (i > j + 3) return false;
|
||||
// MG_DEBUG(("%lu %lu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
||||
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
||||
addr->ip[n] = (uint8_t) ((val >> 8) & 255);
|
||||
addr->ip[n + 1] = (uint8_t) (val & 255);
|
||||
} else if (str.ptr[i] == ':') {
|
||||
j = i + 1;
|
||||
if (i > 0 && str.ptr[i - 1] == ':') {
|
||||
dc = n; // Double colon
|
||||
if (i > 1 && str.ptr[i - 2] == ':') return false;
|
||||
} else if (i > 0) {
|
||||
n += 2;
|
||||
}
|
||||
if (n > 14) return false;
|
||||
addr->ip[n] = addr->ip[n + 1] = 0; // For trailing ::
|
||||
} else if (str.ptr[i] == '%') { // Scope ID
|
||||
for (i = i + 1; i < str.len; i++) {
|
||||
if (str.ptr[i] < '0' || str.ptr[i] > '9') return false;
|
||||
addr->scope_id = (uint8_t) (addr->scope_id * 10);
|
||||
addr->scope_id = (uint8_t) (addr->scope_id + (str.ptr[i] - '0'));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (n < 14 && dc == 42) return false;
|
||||
if (n < 14) {
|
||||
memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
|
||||
memset(&addr->ip[dc], 0, 14 - n);
|
||||
}
|
||||
|
||||
addr->is_ip6 = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr) {
|
||||
// MG_INFO(("[%.*s]", (int) str.len, str.ptr));
|
||||
return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton4(str, addr) ||
|
||||
mg_aton6(str, addr);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
|
||||
struct mg_connection *c =
|
||||
(struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
|
||||
if (c != NULL) {
|
||||
c->mgr = mgr;
|
||||
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
|
||||
c->id = ++mgr->nextid;
|
||||
MG_PROF_INIT(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void mg_close_conn(struct mg_connection *c) {
|
||||
mg_resolve_cancel(c); // Close any pending DNS query
|
||||
LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
|
||||
if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
|
||||
if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
|
||||
// Order of operations is important. `MG_EV_CLOSE` event must be fired
|
||||
// before we deallocate received data, see #1331
|
||||
mg_call(c, MG_EV_CLOSE, NULL);
|
||||
MG_DEBUG(("%lu %ld closed", c->id, c->fd));
|
||||
MG_PROF_DUMP(c);
|
||||
MG_PROF_FREE(c);
|
||||
|
||||
mg_tls_free(c);
|
||||
mg_iobuf_free(&c->recv);
|
||||
mg_iobuf_free(&c->send);
|
||||
mg_iobuf_free(&c->rtls);
|
||||
mg_bzero((unsigned char *) c, sizeof(*c));
|
||||
free(c);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = NULL;
|
||||
if (url == NULL || url[0] == '\0') {
|
||||
MG_ERROR(("null url"));
|
||||
} else if ((c = mg_alloc_conn(mgr)) == NULL) {
|
||||
MG_ERROR(("OOM"));
|
||||
} else {
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
c->is_udp = (strncmp(url, "udp:", 4) == 0);
|
||||
c->fd = (void *) (size_t) MG_INVALID_SOCKET;
|
||||
c->fn = fn;
|
||||
c->is_client = true;
|
||||
c->fn_data = fn_data;
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
mg_call(c, MG_EV_OPEN, (void *) url);
|
||||
mg_resolve(c, url);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = NULL;
|
||||
if ((c = mg_alloc_conn(mgr)) == NULL) {
|
||||
MG_ERROR(("OOM %s", url));
|
||||
} else if (!mg_open_listener(c, url)) {
|
||||
MG_ERROR(("Failed: %s, errno %d", url, errno));
|
||||
MG_PROF_FREE(c);
|
||||
free(c);
|
||||
c = NULL;
|
||||
} else {
|
||||
c->is_listening = 1;
|
||||
c->is_udp = strncmp(url, "udp:", 4) == 0;
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
c->fn = fn;
|
||||
c->fn_data = fn_data;
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = mg_alloc_conn(mgr);
|
||||
if (c != NULL) {
|
||||
c->fd = (void *) (size_t) fd;
|
||||
c->fn = fn;
|
||||
c->fn_data = fn_data;
|
||||
MG_EPOLL_ADD(c);
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
|
||||
unsigned flags, void (*fn)(void *), void *arg) {
|
||||
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
|
||||
if (t != NULL) {
|
||||
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
|
||||
t->id = mgr->timerid++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||
if (c->rtls.len == 0) return MG_IO_WAIT;
|
||||
if (len > c->rtls.len) len = c->rtls.len;
|
||||
memcpy(buf, c->rtls.buf, len);
|
||||
mg_iobuf_del(&c->rtls, 0, len);
|
||||
return (long) len;
|
||||
}
|
||||
|
||||
void mg_mgr_free(struct mg_mgr *mgr) {
|
||||
struct mg_connection *c;
|
||||
struct mg_timer *tmp, *t = mgr->timers;
|
||||
while (t != NULL) tmp = t->next, free(t), t = tmp;
|
||||
mgr->timers = NULL; // Important. Next call to poll won't touch timers
|
||||
for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
|
||||
mg_mgr_poll(mgr, 0);
|
||||
#if MG_ENABLE_FREERTOS_TCP
|
||||
FreeRTOS_DeleteSocketSet(mgr->ss);
|
||||
#endif
|
||||
MG_DEBUG(("All connections closed"));
|
||||
#if MG_ENABLE_EPOLL
|
||||
if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
|
||||
#endif
|
||||
mg_tls_ctx_free(mgr);
|
||||
}
|
||||
|
||||
void mg_mgr_init(struct mg_mgr *mgr) {
|
||||
memset(mgr, 0, sizeof(*mgr));
|
||||
#if MG_ENABLE_EPOLL
|
||||
if ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
|
||||
MG_ERROR(("epoll_create1 errno %d", errno));
|
||||
#else
|
||||
mgr->epoll_fd = -1;
|
||||
#endif
|
||||
#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
|
||||
// clang-format off
|
||||
{ WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
|
||||
// clang-format on
|
||||
#elif MG_ENABLE_FREERTOS_TCP
|
||||
mgr->ss = FreeRTOS_CreateSocketSet();
|
||||
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
|
||||
// Ignore SIGPIPE signal, so if client cancels the request, it
|
||||
// won't kill the whole process.
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
mgr->pipe = MG_INVALID_SOCKET;
|
||||
mgr->dnstimeout = 3000;
|
||||
mgr->dns4.url = "udp://8.8.8.8:53";
|
||||
mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
|
||||
mg_tls_ctx_init(mgr);
|
||||
}
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/ota_dummy.c"
|
||||
#endif
|
||||
@@ -6630,7 +6626,7 @@ int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_READ) {
|
||||
int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len);
|
||||
if (milliseconds > 0) {
|
||||
@@ -6644,8 +6640,7 @@ static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
mg_sntp_request(c);
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
}
|
||||
(void) fnd;
|
||||
(void) evd;
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
void mg_sntp_request(struct mg_connection *c) {
|
||||
@@ -7296,7 +7291,7 @@ static bool mg_socketpair(MG_SOCKET_TYPE sp[2], union usa usa[2]) {
|
||||
}
|
||||
|
||||
// mg_wakeup() event handler
|
||||
static void wufn(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
static void wufn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_READ) {
|
||||
unsigned long *id = (unsigned long *) c->recv.buf;
|
||||
// MG_INFO(("Got data"));
|
||||
@@ -7316,7 +7311,7 @@ static void wufn(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
closesocket(c->mgr->pipe); // When we're closing, close the other
|
||||
c->mgr->pipe = MG_INVALID_SOCKET; // side of the socketpair, too
|
||||
}
|
||||
(void) evd, (void) fnd;
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
bool mg_wakeup_init(struct mg_mgr *mgr) {
|
||||
@@ -13736,8 +13731,7 @@ static bool mg_ws_client_handshake(struct mg_connection *c) {
|
||||
return false; // Continue event handler
|
||||
}
|
||||
|
||||
static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *fn_data) {
|
||||
static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct ws_msg msg;
|
||||
size_t ofs = (size_t) c->pfn_data;
|
||||
|
||||
@@ -13803,7 +13797,6 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
(void) fn_data;
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user