static void mg_ev_handler(struct mg_connection *nc, int ev, void *ev_data) { switch (ev) { case MG_EV_ACCEPT: { char addr[32]; mg_conn_addr_to_str(nc, addr, sizeof(addr), MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("%p conn from %s", nc, addr)); break; } case MG_EV_HTTP_REQUEST: { char addr[32]; struct http_message *hm = (struct http_message *) ev_data; cs_stat_t st; mg_conn_addr_to_str(nc, addr, sizeof(addr), MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("HTTP request from %s: %.*s %.*s", addr, (int) hm->method.len, hm->method.p, (int) hm->uri.len, hm->uri.p)); if (mg_vcmp(&hm->uri, "/upload") == 0 || (mg_vcmp(&hm->uri, "/") == 0 && mg_stat("SL:index.html", &st) != 0)) { mg_send(nc, upload_form, strlen(upload_form)); nc->flags |= MG_F_SEND_AND_CLOSE; break; } struct mg_serve_http_opts opts; memset(&opts, 0, sizeof(opts)); opts.document_root = "SL:"; mg_serve_http(nc, hm, opts); break; } case MG_EV_CLOSE: { LOG(LL_INFO, ("%p closed", nc)); break; } case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { LOG(LL_INFO, ("%p switching to data mode", nc)); nc->handler = data_conn_handler; nc->ev_timer_time = mg_time(); /* Immediately */ break; } case MG_EV_TIMER: { data_collect(); nc->ev_timer_time = mg_time() + (DATA_COLLECTION_INTERVAL_MS * 0.001); } case MG_EV_HTTP_PART_BEGIN: case MG_EV_HTTP_PART_DATA: case MG_EV_HTTP_PART_END: { struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) ev_data; if (ev == MG_EV_HTTP_PART_BEGIN) { LOG(LL_INFO, ("Begin file upload: %s", mp->file_name)); } else if (ev == MG_EV_HTTP_PART_END) { LOG(LL_INFO, ("End file upload: %s", mp->file_name)); } mg_file_upload_handler(nc, ev, ev_data, upload_fname); } } }
/* * Creates a new session for the user. */ static struct session *create_session(const char *user, const struct http_message *hm) { /* Find first available slot or use the oldest one. */ struct session *s = NULL; struct session *oldest_s = s_sessions; for (int i = 0; i < NUM_SESSIONS; i++) { if (s_sessions[i].id == 0) { s = &s_sessions[i]; break; } if (s_sessions[i].last_used < oldest_s->last_used) { oldest_s = &s_sessions[i]; } } if (s == NULL) { destroy_session(oldest_s); printf("Evicted %" INT64_X_FMT "/%s\n", oldest_s->id, oldest_s->user); s = oldest_s; } /* Initialize new session. */ s->created = s->last_used = mg_time(); s->user = strdup(user); s->lucky_number = rand(); /* Create an ID by putting various volatiles into a pot and stirring. */ cs_sha1_ctx ctx; cs_sha1_init(&ctx); cs_sha1_update(&ctx, (const unsigned char *) hm->message.p, hm->message.len); cs_sha1_update(&ctx, (const unsigned char *) s, sizeof(*s)); unsigned char digest[20]; cs_sha1_final(digest, &ctx); s->id = *((uint64_t *) digest); return s; }
static IRAM void mgos_mg_poll_cb(void *arg) { mgos_ints_disable(); s_mg_polls_in_flight--; mgos_ints_enable(); int timeout_ms = 0; if (mongoose_poll(0) == 0) { /* Nothing is happening now, see when next timer is due. */ double min_timer = mg_mgr_min_timer(mgos_get_mgr()); if (min_timer > 0) { /* Note: timeout_ms can get negative if a timer is past due. That's ok. */ timeout_ms = (int) ((min_timer - mg_time()) * 1000.0); if (timeout_ms < 0) { timeout_ms = 0; /* Now */ } else if (timeout_ms > MGOS_MONGOOSE_MAX_POLL_SLEEP_MS) { timeout_ms = MGOS_MONGOOSE_MAX_POLL_SLEEP_MS; } } else { timeout_ms = MGOS_MONGOOSE_MAX_POLL_SLEEP_MS; } } else { /* Things are happening, we need another poll ASAP. */ } if (timeout_ms == 0) { mongoose_schedule_poll(false /* from_isr */); } else { os_timer_disarm(&s_mg_poll_tmr); /* We set repeat = true in case things get stuck for any reason. */ os_timer_arm(&s_mg_poll_tmr, timeout_ms, 1 /* repeat */); } (void) arg; }
static void mg_init(struct mg_mgr *mgr) { LOG(LL_INFO, ("MG task running")); stop_nwp(); /* See function description in wifi.c */ LOG(LL_INFO, ("Starting NWP...")); int role = sl_Start(0, 0, 0); if (role < 0) { LOG(LL_ERROR, ("Failed to start NWP")); return; } { SlVersionFull ver; unsigned char opt = SL_DEVICE_GENERAL_VERSION; unsigned char len = sizeof(ver); memset(&ver, 0, sizeof(ver)); sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &opt, &len, (unsigned char *) (&ver)); LOG(LL_INFO, ("NWP v%d.%d.%d.%d started, host v%d.%d.%d.%d", ver.NwpVersion[0], ver.NwpVersion[1], ver.NwpVersion[2], ver.NwpVersion[3], SL_MAJOR_VERSION_NUM, SL_MINOR_VERSION_NUM, SL_VERSION_NUM, SL_SUB_VERSION_NUM)); } GPIO_IF_LedToggle(MCU_RED_LED_GPIO); data_init_sensors(TMP006_ADDR, BM222_ADDR); sl_fs_init(); #if defined(WIFI_STA_SSID) if (!wifi_setup_sta(WIFI_STA_SSID, WIFI_STA_PASS)) { LOG(LL_ERROR, ("Error setting up WiFi station")); } #elif defined(WIFI_AP_SSID) if (!wifi_setup_ap(WIFI_AP_SSID, WIFI_AP_PASS, WIFI_AP_CHAN)) { LOG(LL_ERROR, ("Error setting up WiFi AP")); } #else #error WiFi not configured #endif /* We don't need SimpleLink's web server. */ sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); const char *err = ""; struct mg_bind_opts opts; memset(&opts, 0, sizeof(opts)); opts.error_string = &err; struct mg_connection *nc = mg_bind_opt(mgr, "80", mg_ev_handler, opts); if (nc != NULL) { mg_set_protocol_http_websocket(nc); nc->ev_timer_time = mg_time(); /* Start data collection */ } else { LOG(LL_ERROR, ("Failed to create listener: %s", err)); } }
static void mg_ev_handler(struct mg_connection *nc, int ev, void *p) { switch (ev) { case MG_EV_ACCEPT: { char addr[32]; mg_conn_addr_to_str(nc, addr, sizeof(addr), MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("%p conn from %s", nc, addr)); break; } case MG_EV_HTTP_REQUEST: { char addr[32]; struct http_message *hm = (struct http_message *) p; mg_conn_addr_to_str(nc, addr, sizeof(addr), MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("HTTP request from %s: %.*s %.*s", addr, (int) hm->method.len, hm->method.p, (int) hm->uri.len, hm->uri.p)); struct mg_serve_http_opts opts; memset(&opts, 0, sizeof(opts)); opts.document_root = "SL:"; mg_serve_http(nc, (struct http_message *) p, opts); break; } case MG_EV_CLOSE: { LOG(LL_INFO, ("%p closed", nc)); break; } case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { LOG(LL_INFO, ("%p switching to data mode", nc)); nc->handler = data_conn_handler; nc->ev_timer_time = mg_time(); /* Immediately */ break; } case MG_EV_TIMER: { data_collect(); nc->ev_timer_time = mg_time() + (DATA_COLLECTION_INTERVAL_MS * 0.001); } case MG_EV_HTTP_PART_BEGIN: case MG_EV_HTTP_PART_DATA: case MG_EV_HTTP_PART_END: { mg_file_upload_handler(nc, ev, p, upload_fname); } } }
void data_collect(void) { double volt = tmp006_read_sensor_voltage(s_tmp006_addr); double temp = tmp006_read_die_temp(s_tmp006_addr); if (volt != TMP006_INVALID_READING && temp != TMP006_INVALID_READING) { s_temp_data.temp = temp; s_temp_data.volt = volt; s_temp_data.ts = mg_time(); LOG(LL_DEBUG, ("V = %lf mV, T = %lf C", volt, temp)); } bm222_get_data(s_accel_ctx); }
/* Cleans up sessions that have been idle for too long. */ void check_sessions() { double threshold = mg_time() - SESSION_TTL; for (int i = 0; i < NUM_SESSIONS; i++) { struct session *s = &s_sessions[i]; if (s->id != 0 && s->last_used < threshold) { fprintf(stderr, "Session %" INT64_X_FMT " (%s) closed due to idleness.\n", s->id, s->user); destroy_session(s); } } }
int main(void) { struct mg_mgr mgr; struct mg_connection *nc; srand(mg_time()); mg_mgr_init(&mgr, NULL); nc = mg_bind(&mgr, s_http_port, ev_handler); mg_set_protocol_http_websocket(nc); s_http_server_opts.document_root = "."; mg_register_http_endpoint(nc, "/login.html", login_handler); mg_register_http_endpoint(nc, "/logout", logout_handler); mg_set_timer(nc, mg_time() + SESSION_CHECK_INTERVAL); printf("Starting web server on port %s\n", s_http_port); for (;;) { mg_mgr_poll(&mgr, 1000); } mg_mgr_free(&mgr); return 0; }
bool RestServ::check_sessions() { auto threshold = mg_time() - SESSION_TTL; for (auto iter = session_list_.begin(); iter != session_list_.end(); ++iter) { if ( (*iter)->last_used < threshold ) { iter = session_list_.erase(iter); } } return true; }
void data_conn_handler(struct mg_connection *nc, int ev, void *ev_data) { struct conn_state *cs = (struct conn_state *) nc->user_data; if (cs == NULL) { cs = (struct conn_state *) calloc(1, sizeof(*cs)); nc->user_data = cs; } switch (ev) { case MG_EV_POLL: case MG_EV_TIMER: { const double now = mg_time(); const unsigned char led = GPIO_IF_LedStatus(MCU_RED_LED_GPIO); /* Send if there was a change or repeat last data every second. */ if (s_temp_data.volt != cs->td.volt || s_temp_data.temp != cs->td.temp || now > cs->last_sent_td + 1.0) { memcpy(&cs->td, &s_temp_data, sizeof(cs->td)); send_temp(nc, &cs->td); cs->last_sent_td = now; } if (led != cs->led || now > cs->last_sent_led + 1.0) { send_led(nc, now, led); cs->led = led; cs->last_sent_led = now; } if (s_accel_ctx != NULL) { const struct bm222_sample *ls = s_accel_ctx->data + s_accel_ctx->last_index; if (cs->last_sent_acc == 0) { send_acc_sample(nc, ls); cs->last_sent_acc = ls->ts; } else { double last_sent_ts = send_acc_data_since(nc, s_accel_ctx, cs->last_sent_acc); if (last_sent_ts > 0) cs->last_sent_acc = last_sent_ts; } } nc->ev_timer_time = now + 0.05; break; } case MG_EV_WEBSOCKET_FRAME: { struct websocket_message *wm = (struct websocket_message *) ev_data; process_command(nc, wm->data, wm->size); break; } case MG_EV_CLOSE: { LOG(LL_INFO, ("%p closed", nc)); free(cs); break; } } }
bool bm222_get_data(struct bm222_ctx *ctx) { unsigned char reg = BM222_REG_FIFO_STATUS; unsigned char val; if (I2C_IF_ReadFrom(ctx->addr, ®, 1, &val, 1) < 0) return false; unsigned char len = (val & 0x7f); unsigned char overflow = (val & 0x80 ? 1 : 0); LOG(LL_DEBUG, ("FIFO len: %d (ovf? %d)", len, overflow)); reg = BM222_REG_FIFO_DATA; int8_t fifo[32 * 6], *v = fifo; if (I2C_IF_ReadFrom(ctx->addr, ®, 1, (unsigned char *) fifo, len * 6) < 0) { return false; } double now = mg_time(); /* Of potentially multiple samples, pick one with maximum difference. */ int32_t max_d = 0; bool sampled = false; struct bm222_sample *ls = ctx->data + ctx->last_index, *s = NULL; if (ls->ts == 0) { /* The very first sample. */ ls->ts = now; ls->x = v[1]; ls->y = v[3]; ls->z = v[5]; v += 6; len--; sampled = true; s = ls; } for (; len > 0; v += 6, len--) { int32_t dx = ((int32_t) v[1]) - ((int32_t) ls->x); int32_t dy = ((int32_t) v[3]) - ((int32_t) ls->y); int32_t dz = ((int32_t) v[5]) - ((int32_t) ls->z); int32_t d = dx * dx + dy * dy + dz * dz; if ((d > 2 && d > max_d) || (!sampled && now - ls->ts > 1.0)) { if (!sampled) { ctx->last_index = (ctx->last_index + 1) % BM222_NUM_SAMPLES; s = ctx->data + ctx->last_index; sampled = true; } s->ts = now; s->x = v[1]; s->y = v[3]; s->z = v[5]; if (d > max_d) max_d = d; LOG(LL_VERBOSE_DEBUG, ("dx %d dy %d dz %d d %d", dx, dy, dz, d)); } } return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */ }
static s32_t failfs_write(spiffs *fs, u32_t addr, u32_t size, u8_t *src) { struct mount_info *m = (struct mount_info *) fs->user_data; _i32 r; DBG(("failfs_write %d @ %d, cidx %d # %llu, fh %d, valid %d, rw %d", (int) size, (int) addr, m->cidx, m->seq, (int) m->fh, m->valid, m->rw)); if (!m->valid) return SPIFFS_ERR_NOT_WRITABLE; if (!m->rw) { /* Remount rw. */ if (fs_switch_container(m, 0, 0) != 0) return SPIFFS_ERR_NOT_WRITABLE; } r = sl_FsWrite(m->fh, addr, src, size); DBG(("write %d", (int) r)); m->last_write = mg_time(); return (r == size) ? SPIFFS_OK : SPIFFS_ERR_NOT_WRITABLE; }
static void mg_task(void *arg) { LOG(LL_INFO, ("MG task running")); GPIO_IF_LedToggle(MCU_RED_LED_GPIO); osi_MsgQCreate(&s_v7_q, "MG", sizeof(struct event), 32 /* len */); sl_Start(NULL, NULL, NULL); data_init_sensors(TMP006_ADDR, BM222_ADDR); cc3200_fs_init(); #if defined(WIFI_STA_SSID) if (!wifi_setup_sta(WIFI_STA_SSID, WIFI_STA_PASS)) { LOG(LL_ERROR, ("Error setting up WiFi station")); } #elif defined(WIFI_AP_SSID) if (!wifi_setup_ap(WIFI_AP_SSID, WIFI_AP_PASS, WIFI_AP_CHAN)) { LOG(LL_ERROR, ("Error setting up WiFi AP")); } #else #error WiFi not configured #endif /* We don't need SimpleLink's web server. */ sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); mg_mgr_init(&mg_mgr, NULL); const char *err = ""; struct mg_bind_opts opts; memset(&opts, 0, sizeof(opts)); opts.error_string = &err; struct mg_connection *nc = mg_bind(&mg_mgr, "80", mg_ev_handler); if (nc != NULL) { mg_set_protocol_http_websocket(nc); nc->ev_timer_time = mg_time(); /* Start data collection */ } else { LOG(LL_ERROR, ("Failed to create listener: %s", err)); } while (1) { struct event e; mg_mgr_poll(&mg_mgr, 0); if (osi_MsgQRead(&s_v7_q, &e, 1) != OSI_OK) continue; } }
void mg_hexdump_connection(struct mg_connection *nc, const char *path, const void *buf, int num_bytes, int ev) { FILE *fp = NULL; char src[60], dst[60]; const char *tag = NULL; switch (ev) { case MG_EV_RECV: tag = "<-"; break; case MG_EV_SEND: tag = "->"; break; case MG_EV_ACCEPT: tag = "<A"; break; case MG_EV_CONNECT: tag = "C>"; break; case MG_EV_CLOSE: tag = "XX"; break; } if (tag == NULL) return; /* Don't log MG_EV_TIMER, etc */ if (strcmp(path, "-") == 0) { fp = stdout; } else if (strcmp(path, "--") == 0) { fp = stderr; #if MG_ENABLE_FILESYSTEM } else { fp = mg_fopen(path, "a"); #endif } if (fp == NULL) return; mg_conn_addr_to_str(nc, src, sizeof(src), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); mg_conn_addr_to_str(nc, dst, sizeof(dst), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT | MG_SOCK_STRINGIFY_REMOTE); fprintf(fp, "%lu %p %s %s %s %d\n", (unsigned long) mg_time(), (void *) nc, src, tag, dst, (int) num_bytes); if (num_bytes > 0) { mg_hexdumpf(fp, buf, num_bytes); } if (fp != stdout && fp != stderr) fclose(fp); }
/* * Parses the session cookie and returns a pointer to the session struct * or NULL if not found. */ static struct session *get_session(struct http_message *hm) { struct mg_str *cookie_header = mg_get_http_header(hm, "cookie"); if (cookie_header == NULL) return NULL; char ssid[21]; if (!mg_http_parse_header(cookie_header, SESSION_COOKIE_NAME, ssid, sizeof(ssid))) { return NULL; } uint64_t sid = strtoull(ssid, NULL, 16); for (int i = 0; i < NUM_SESSIONS; i++) { if (s_sessions[i].id == sid) { s_sessions[i].last_used = mg_time(); return &s_sessions[i]; } } return NULL; }
sj_timer_id sj_set_timer(struct timer_info *ti, int msecs, int repeat) { struct mg_connection *c; struct mg_add_sock_opts opts; do { ti->id = s_next_timer_id++; } while (ti->id == SJ_INVALID_TIMER_ID || sj_find_timer(ti->id) != NULL); ti->interval_ms = (repeat ? msecs : -1); memset(&opts, 0, sizeof(opts)); opts.user_data = ti; c = mg_add_sock_opt(&sj_mgr, INVALID_SOCKET, sj_timer_handler, opts); if (c == NULL) { free(ti); return 0; } c->ev_timer_time = mg_time() + (msecs / 1000.0); mongoose_schedule_poll(); return 1; }
/* Main event handler. */ static void ev_handler(struct mg_connection *nc, int ev, void *p) { switch (ev) { case MG_EV_HTTP_REQUEST: { struct http_message *hm = (struct http_message *) p; struct session *s = get_session(hm); /* Ask the user to log in if they did not present a valid cookie. */ if (s == NULL) { mg_printf(nc, "HTTP/1.0 302 Found\r\n" "Location: /login.html\r\n" "\r\n" "Please log in"); nc->flags |= MG_F_SEND_AND_CLOSE; break; } /* * Serve the page that was requested. * Save session in user_data for use by SSI calls. */ fprintf(stderr, "%s (sid %" INT64_X_FMT ") requested %.*s\n", s->user, s->id, (int) hm->uri.len, hm->uri.p); nc->user_data = s; mg_serve_http(nc, (struct http_message *) p, s_http_server_opts); break; } case MG_EV_SSI_CALL: { /* Expand variables in a page by using session data. */ const char *var = (const char *) p; const struct session *s = (const struct session *) nc->user_data; if (strcmp(var, "user") == 0) { mg_printf_html_escape(nc, "%s", s->user); } else if (strcmp(var, "lucky_number") == 0) { mg_printf_html_escape(nc, "%d", s->lucky_number); } break; } case MG_EV_TIMER: { /* Perform session maintenance. */ check_sessions(); mg_set_timer(nc, mg_time() + SESSION_CHECK_INTERVAL); break; } } }
static void mg_init(struct mg_mgr *mgr) { LOG(LL_INFO, ("MG task running")); stop_nwp(); /* See function description in wifi.c */ int role = sl_Start(0, 0, 0); if (role < 0) { LOG(LL_ERROR, ("Failed to start NWP")); return; } LOG(LL_INFO, ("NWP started")); GPIO_IF_LedToggle(MCU_RED_LED_GPIO); data_init_sensors(TMP006_ADDR, BM222_ADDR); sl_fs_init(); #if defined(WIFI_STA_SSID) if (!wifi_setup_sta(WIFI_STA_SSID, WIFI_STA_PASS)) { LOG(LL_ERROR, ("Error setting up WiFi station")); } #elif defined(WIFI_AP_SSID) if (!wifi_setup_ap(WIFI_AP_SSID, WIFI_AP_PASS, WIFI_AP_CHAN)) { LOG(LL_ERROR, ("Error setting up WiFi AP")); } #else #error WiFi not configured #endif /* We don't need SimpleLink's web server. */ sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); const char *err = ""; struct mg_bind_opts opts; memset(&opts, 0, sizeof(opts)); opts.error_string = &err; struct mg_connection *nc = mg_bind(mgr, "80", mg_ev_handler); if (nc != NULL) { mg_set_protocol_http_websocket(nc); nc->ev_timer_time = mg_time(); /* Start data collection */ } else { LOG(LL_ERROR, ("Failed to create listener: %s", err)); } }
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) { struct mg_connection *nc; double now; double min_timer = 0; int num_timers = 0; mg_ev_mgr_lwip_process_signals(mgr); for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; if (nc->ev_timer_time > 0) { if (num_timers == 0 || nc->ev_timer_time < min_timer) { min_timer = nc->ev_timer_time; } num_timers++; } if (nc->send_mbuf.len > 0 #if MG_ENABLE_SSL || (nc->flags & MG_F_WANT_WRITE) #endif ) { int can_send = 0; /* We have stuff to send, but can we? */ if (nc->flags & MG_F_UDP) { /* UDP is always ready for sending. */ can_send = (cs->pcb.udp != NULL); } else { can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0); } /* We want and can send, request a poll immediately. */ if (can_send) return 0; } } uint32_t timeout_ms = ~0; now = mg_time(); if (num_timers > 0) { /* If we have a timer that is past due, do a poll ASAP. */ if (min_timer < now) return 0; double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */; if (timer_timeout_ms < timeout_ms) { timeout_ms = timer_timeout_ms; } } return timeout_ms; }
std::shared_ptr<Session> RestServ::push_session(HttpMessage data) { char user[64]{0x00}, pass[64]{0x00}; auto ul = mg_get_http_var(&(data.get()->body), "user", user, sizeof(user)); auto pl = mg_get_http_var(&(data.get()->body), "pass", pass, sizeof(pass)); auto s = std::make_shared<Session>(); s->created = s->last_used = mg_time(); s->user = std::string(user, ul); s->pass = std::string(pass, pl); s->id = std::hash<std::shared_ptr<Session>>()(s); std::string&& seed = std::string(user) + std::to_string(s->id); s->id = std::hash<std::string>()(seed); session_list_.push_back(s); return s; }
std::shared_ptr<Session> RestServ::get_from_session_list(HttpMessage data) { mg_str* cookie_header = mg_get_http_header(data.get(), "cookie");; if (cookie_header == nullptr) return nullptr; char ssid[32]{0x00}; if (!mg_http_parse_header(cookie_header, SESSION_COOKIE_NAME, ssid, sizeof(ssid))) return nullptr; auto sid = std::stoul(ssid, nullptr, 10); auto ret = std::find_if(session_list_.begin(), session_list_.end(), [&sid](std::shared_ptr<Session> p){ return sid == p->id; }); if (ret == session_list_.end()) return nullptr; (*ret)->last_used = mg_time(); return *ret; }
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) { struct mg_connection *nc; double now = mg_time(); double min_timer = 0; int num_timers = 0; mg_ev_mgr_lwip_process_signals(mgr); for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { if (nc->ev_timer_time > 0) { if (num_timers == 0 || nc->ev_timer_time < min_timer) { min_timer = nc->ev_timer_time; } num_timers++; } } uint32_t timeout_ms = ~0; if (num_timers > 0) { double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */; if (timer_timeout_ms < timeout_ms) { timeout_ms = timer_timeout_ms; } } return timeout_ms; }
static void mg_rpc_channel_ws_out_reconnect(struct mg_rpc_channel *ch) { struct mg_rpc_channel_ws_out_data *chd = (struct mg_rpc_channel_ws_out_data *) ch->channel_data; if (chd->reconnect_interval > chd->cfg->reconnect_interval_max) { chd->reconnect_interval = chd->cfg->reconnect_interval_max; } if (chd->reconnect_interval == 0) return; LOG(LL_DEBUG, ("reconnect in %d", chd->reconnect_interval)); /* Set reconnect timer */ { struct mg_add_sock_opts opts; struct mg_connection *c; memset(&opts, 0, sizeof(opts)); opts.user_data = ch; c = mg_add_sock_opt(chd->mgr, INVALID_SOCKET, reconnect_ev_handler, opts); if (c != NULL) { c->ev_timer_time = mg_time() + chd->reconnect_interval; chd->reconnect_interval *= 2; } chd->fake_timer_connection = c; } }
static void sj_timer_handler(struct mg_connection *c, int ev, void *p) { struct timer_info *ti = (struct timer_info *) c->user_data; (void) p; if (ti == NULL) return; switch (ev) { case MG_EV_TIMER: { if (c->flags & MG_F_CLOSE_IMMEDIATELY) break; if (ti->v7 != NULL) sj_invoke_cb0(ti->v7, ti->js_cb); if (ti->cb != NULL) ti->cb(ti->arg); if (ti->interval_ms > 0) { c->ev_timer_time = mg_time() + ti->interval_ms / 1000.0; } else { c->flags |= MG_F_CLOSE_IMMEDIATELY; } break; } case MG_EV_CLOSE: { if (ti->v7 != NULL) v7_disown(ti->v7, &ti->js_cb); free(ti); c->user_data = NULL; break; } } }
static void mg_ev_handler(struct mg_connection *nc, int ev, void *ev_data) { switch (ev) { case MG_EV_ACCEPT: { char addr[32]; mg_conn_addr_to_str(nc, addr, sizeof(addr), MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("%p conn from %s", nc, addr)); break; } case MG_EV_HTTP_REQUEST: { char addr[32]; struct http_message *hm = (struct http_message *) ev_data; cs_stat_t st; mg_conn_addr_to_str(nc, addr, sizeof(addr), MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("HTTP request from %s: %.*s %.*s", addr, (int) hm->method.len, hm->method.p, (int) hm->uri.len, hm->uri.p)); if (mg_vcmp(&hm->uri, "/upload") == 0 || (mg_vcmp(&hm->uri, "/") == 0 && mg_stat("SL:index.html", &st) != 0)) { mg_send(nc, upload_form, strlen(upload_form)); nc->flags |= MG_F_SEND_AND_CLOSE; break; } struct mg_serve_http_opts opts; memset(&opts, 0, sizeof(opts)); opts.document_root = "SL:"; mg_serve_http(nc, hm, opts); break; } case MG_EV_CLOSE: { LOG(LL_INFO, ("%p closed", nc)); break; } case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { LOG(LL_INFO, ("%p switching to data mode", nc)); nc->handler = data_conn_handler; nc->ev_timer_time = mg_time(); /* Immediately */ break; } case MG_EV_TIMER: { data_collect(); nc->ev_timer_time = mg_time() + (DATA_COLLECTION_INTERVAL_MS * 0.001); break; } /* SimpleLink FS requires pre-declaring max file size. We use Content-Length * for that purpose - it will not exactly match file size, but is guaranteed * to exceed it and should be close enough. */ case MG_EV_HTTP_MULTIPART_REQUEST: { struct http_message *hm = (struct http_message *) ev_data; struct mg_str *cl_header = mg_get_http_header(hm, "Content-Length"); intptr_t cl = -1; if (cl_header != NULL && cl_header->len < 20) { char buf[20]; memcpy(buf, cl_header->p, cl_header->len); buf[cl_header->len] = '\0'; cl = atoi(buf); if (cl < 0) cl = -1; } nc->user_data = (void *) cl; break; } case MG_EV_HTTP_PART_BEGIN: case MG_EV_HTTP_PART_DATA: case MG_EV_HTTP_PART_END: { struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) ev_data; if (ev == MG_EV_HTTP_PART_BEGIN) { LOG(LL_INFO, ("Begin file upload: %s", mp->file_name)); } else if (ev == MG_EV_HTTP_PART_END) { LOG(LL_INFO, ("End file upload: %s", mp->file_name)); } mg_file_upload_handler(nc, ev, ev_data, upload_fname); } } }
static _i32 fs_switch_container(struct mount_info *m, _u32 mask_begin, _u32 mask_len) { int r; int new_cidx = m->cidx ^ 1; _i32 old_fh = m->fh, new_fh; _u8 *buf; _u32 offset, len, buf_size; LOG(LL_DEBUG, ("%s %d -> %d", m->cpfx, m->cidx, new_cidx)); if (old_fh > 0 && m->rw) { /* * During the switch the destination container will be unusable. * If switching from a writeable container (likely in response to an erase), * close the old container first to make it safe and reopen for reading. */ fs_close_container(m); old_fh = -1; } if (old_fh < 0) { _u8 fname[MAX_FS_CONTAINER_FNAME_LEN]; fs_container_fname(m->cpfx, m->cidx, fname); r = sl_FsOpen(fname, FS_MODE_OPEN_READ, NULL, &old_fh); DBG(("fopen %s %d", m->cpfx, r)); if (r < 0) { r = SPIFFS_ERR_NOT_READABLE; goto out_close_old; } } miot_wdt_feed(); new_fh = fs_create_container(m->cpfx, new_cidx, m->fs.cfg.phys_size); if (new_fh < 0) { r = new_fh; goto out_close_old; } buf_size = 1024; buf = get_buf(&buf_size); if (buf == NULL) { r = SPIFFS_ERR_INTERNAL; goto out_close_new; } for (offset = 0; offset < m->fs.cfg.phys_size;) { len = buf_size; if (offset == mask_begin) { offset = mask_begin + mask_len; } else if (offset + len > mask_begin && offset < mask_begin + mask_len) { len = mask_begin - offset; } if (offset + len > m->fs.cfg.phys_size) { len = m->fs.cfg.phys_size - offset; } DBG(("copy %d @ %d", (int) len, (int) offset)); if (len > 0) { r = sl_FsRead(old_fh, offset, buf, len); if (r != len) { r = SPIFFS_ERR_NOT_READABLE; goto out_free; } r = sl_FsWrite(new_fh, offset, buf, len); if (r != len) { r = SPIFFS_ERR_NOT_WRITABLE; goto out_free; } offset += len; } } m->seq--; m->cidx = new_cidx; m->fh = new_fh; new_fh = -1; m->rw = 1; r = fs_write_mount_meta(m); m->last_write = mg_time(); out_free: free(buf); out_close_new: if (new_fh > 0) sl_FsClose(new_fh, NULL, NULL, 0); out_close_old: sl_FsClose(old_fh, NULL, NULL, 0); LOG((r == 0 ? LL_DEBUG : LL_ERROR), ("%d", r)); return r; }
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { struct mg_mgr *mgr = iface->mgr; int n = 0; double now = mg_time(); struct mg_connection *nc, *tmp; double min_timer = 0; int num_timers = 0; #if 0 DBG(("begin poll @%u", (unsigned int) (now * 1000))); #endif mg_ev_mgr_lwip_process_signals(mgr); for (nc = mgr->active_connections; nc != NULL; nc = tmp) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; tmp = nc->next; n++; if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) || ((nc->flags & MG_F_SEND_AND_CLOSE) && (nc->flags & MG_F_UDP) && (nc->send_mbuf.len == 0))) { mg_close_conn(nc); continue; } mg_if_poll(nc, now); mg_if_timer(nc, now); #if MG_ENABLE_SSL if ((nc->flags & MG_F_SSL) && cs != NULL && cs->pcb.tcp != NULL && cs->pcb.tcp->state == ESTABLISHED) { if (((nc->flags & MG_F_WANT_WRITE) || ((nc->send_mbuf.len > 0) && (nc->flags & MG_F_SSL_HANDSHAKE_DONE))) && cs->pcb.tcp->snd_buf > 0) { /* Can write more. */ if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_send(nc); } else { mg_lwip_ssl_do_hs(nc); } } if (cs->rx_chain != NULL || (nc->flags & MG_F_WANT_READ)) { if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_recv(nc); } else { mg_lwip_ssl_do_hs(nc); } } } else #endif /* MG_ENABLE_SSL */ { if (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING)) { mg_lwip_send_more(nc); } } if (nc->sock != INVALID_SOCKET && !(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != NULL && cs->pcb.tcp->unsent != NULL) { tcpip_callback(tcp_output_tcpip, cs->pcb.tcp); } if (nc->ev_timer_time > 0) { if (num_timers == 0 || nc->ev_timer_time < min_timer) { min_timer = nc->ev_timer_time; } num_timers++; } if (nc->sock != INVALID_SOCKET) { /* Try to consume data from cs->rx_chain */ mg_lwip_consume_rx_chain_tcp(nc); /* * If the connection is about to close, and rx_chain is finally empty, * send the MG_SIG_CLOSE_CONN signal */ if (cs->draining_rx_chain && cs->rx_chain == NULL) { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } } } #if 0 DBG(("end poll @%u, %d conns, %d timers (min %u), next in %d ms", (unsigned int) (now * 1000), n, num_timers, (unsigned int) (min_timer * 1000), timeout_ms)); #endif (void) timeout_ms; return now; }
time_t mg_socket_if_poll(struct mg_iface *iface, int timeout_ms) { struct mg_mgr *mgr = iface->mgr; double now = mg_time(); double min_timer; struct mg_connection *nc, *tmp; struct timeval tv; fd_set read_set, write_set, err_set; sock_t max_fd = INVALID_SOCKET; int num_fds, num_ev, num_timers = 0; #ifdef __unix__ int try_dup = 1; #endif FD_ZERO(&read_set); FD_ZERO(&write_set); FD_ZERO(&err_set); #if MG_ENABLE_BROADCAST mg_add_to_set(mgr->ctl[1], &read_set, &max_fd); #endif /* * Note: it is ok to have connections with sock == INVALID_SOCKET in the list, * e.g. timer-only "connections". */ min_timer = 0; for (nc = mgr->active_connections, num_fds = 0; nc != NULL; nc = tmp) { tmp = nc->next; if (nc->sock != INVALID_SOCKET) { num_fds++; #ifdef __unix__ /* A hack to make sure all our file descriptos fit into FD_SETSIZE. */ if (nc->sock >= (sock_t) FD_SETSIZE && try_dup) { int new_sock = dup(nc->sock); if (new_sock >= 0) { if (new_sock < (sock_t) FD_SETSIZE) { closesocket(nc->sock); DBG(("new sock %d -> %d", nc->sock, new_sock)); nc->sock = new_sock; } else { closesocket(new_sock); DBG(("new sock is still larger than FD_SETSIZE, disregard")); try_dup = 0; } } else { try_dup = 0; } } #endif if (!(nc->flags & MG_F_WANT_WRITE) && nc->recv_mbuf.len < nc->recv_mbuf_limit && (!(nc->flags & MG_F_UDP) || nc->listener == NULL)) { mg_add_to_set(nc->sock, &read_set, &max_fd); } if (((nc->flags & MG_F_CONNECTING) && !(nc->flags & MG_F_WANT_READ)) || (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING))) { mg_add_to_set(nc->sock, &write_set, &max_fd); mg_add_to_set(nc->sock, &err_set, &max_fd); } } if (nc->ev_timer_time > 0) { if (num_timers == 0 || nc->ev_timer_time < min_timer) { min_timer = nc->ev_timer_time; } num_timers++; } } /* * If there is a timer to be fired earlier than the requested timeout, * adjust the timeout. */ if (num_timers > 0) { double timer_timeout_ms = (min_timer - mg_time()) * 1000 + 1 /* rounding */; if (timer_timeout_ms < timeout_ms) { timeout_ms = (int) timer_timeout_ms; } } if (timeout_ms < 0) timeout_ms = 0; tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; num_ev = select((int) max_fd + 1, &read_set, &write_set, &err_set, &tv); now = mg_time(); #if 0 DBG(("select @ %ld num_ev=%d of %d, timeout=%d", (long) now, num_ev, num_fds, timeout_ms)); #endif #if MG_ENABLE_BROADCAST if (num_ev > 0 && mgr->ctl[1] != INVALID_SOCKET && FD_ISSET(mgr->ctl[1], &read_set)) { mg_mgr_handle_ctl_sock(mgr); } #endif for (nc = mgr->active_connections; nc != NULL; nc = tmp) { int fd_flags = 0; if (nc->sock != INVALID_SOCKET) { if (num_ev > 0) { fd_flags = (FD_ISSET(nc->sock, &read_set) && (!(nc->flags & MG_F_UDP) || nc->listener == NULL) ? _MG_F_FD_CAN_READ : 0) | (FD_ISSET(nc->sock, &write_set) ? _MG_F_FD_CAN_WRITE : 0) | (FD_ISSET(nc->sock, &err_set) ? _MG_F_FD_ERROR : 0); } #if MG_LWIP /* With LWIP socket emulation layer, we don't get write events for UDP */ if ((nc->flags & MG_F_UDP) && nc->listener == NULL) { fd_flags |= _MG_F_FD_CAN_WRITE; } #endif } tmp = nc->next; mg_mgr_handle_conn(nc, fd_flags, now); } for (nc = mgr->active_connections; nc != NULL; nc = tmp) { tmp = nc->next; if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) || (nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) { mg_close_conn(nc); } } return (time_t) now; }
time_t mg_mgr_poll(struct mg_mgr *mgr, int timeout_ms) { int n = 0; double now = mg_time(); struct mg_connection *nc, *tmp; double min_timer = 0; int num_timers = 0; DBG(("begin poll @%u, hf=%u", (unsigned int) (now * 1000), system_get_free_heap_size())); for (nc = mgr->active_connections; nc != NULL; nc = tmp) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; (void) cs; tmp = nc->next; n++; if (nc->flags & MG_F_CLOSE_IMMEDIATELY) { mg_close_conn(nc); continue; } mg_if_poll(nc, now); mg_if_timer(nc, now); if (nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE) && !(nc->flags & MG_F_WANT_WRITE)) { mg_close_conn(nc); continue; } #ifdef SSL_KRYPTON if (nc->ssl != NULL && cs != NULL && cs->pcb.tcp != NULL && cs->pcb.tcp->state == ESTABLISHED) { if (((nc->flags & MG_F_WANT_WRITE) || nc->send_mbuf.len > 0) && cs->pcb.tcp->snd_buf > 0) { /* Can write more. */ if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_send(nc); } else { mg_lwip_ssl_do_hs(nc); } } if (cs->rx_chain != NULL || (nc->flags & MG_F_WANT_READ)) { if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_recv(nc); } else { mg_lwip_ssl_do_hs(nc); } } } else #endif /* SSL_KRYPTON */ { if (!(nc->flags & (MG_F_CONNECTING | MG_F_UDP))) { if (nc->send_mbuf.len > 0) mg_lwip_send_more(nc); } } if (nc->ev_timer_time > 0) { if (num_timers == 0 || nc->ev_timer_time < min_timer) { min_timer = nc->ev_timer_time; } num_timers++; } } now = mg_time(); timeout_ms = MG_POLL_INTERVAL_MS; if (num_timers > 0) { double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */; if (timer_timeout_ms < timeout_ms) { timeout_ms = timer_timeout_ms; } } if (timeout_ms <= 0) timeout_ms = 1; DBG(("end poll @%u, %d conns, %d timers (min %u), next in %d ms", (unsigned int) (now * 1000), n, num_timers, (unsigned int) (min_timer * 1000), timeout_ms)); os_timer_disarm(&s_poll_tmr); os_timer_arm(&s_poll_tmr, timeout_ms, 0 /* no repeat */); return now; }