void WebServer::HTTPResponse::sendChunkHead() { if (m_dataSent) { ESP_LOGE(LOG_TAG, "HTTPResponse: Chunk headers already sent! Attempt to send again/more."); } m_dataSent = true; mg_send_head(m_nc, m_status, -1, buildHeaders().c_str()); } // sendChunkHead
void tws_mongoose_event_handler(struct mg_connection* conn, int ev, void* ev_data) { if(ev == MG_EV_HTTP_REQUEST) { try { struct http_message* hm = (struct http_message*)ev_data; tws::core::service_operation_handler_t& op = tws::core::service_operations_manager::instance().get( std::string(hm->uri.p, hm->uri.len)); tws::mongoose::http_request sg_request(hm); tws::mongoose::http_response sg_response(conn); op(sg_request, sg_response); } catch(const boost::exception& e) { std::string err_msg = "Error: "; if(const std::string* d = boost::get_error_info<tws::error_description>(e)) err_msg += *d; else err_msg += "unknown"; mg_send_head(conn, 400, err_msg.size(), "Content-Type: text/plain"); mg_send(conn, err_msg.c_str(), err_msg.size()); } } }
static void reboot_handler(struct mg_connection *c, int ev, void *p) { (void) p; if (ev != MG_EV_HTTP_REQUEST) return; LOG(LL_DEBUG, ("Reboot requested")); mg_send_head(c, 200, 0, JSON_HEADERS); c->flags |= (MG_F_SEND_AND_CLOSE | MG_F_RELOAD_CONFIG); }
/** * @brief Send data to the HTTP caller. * Send the data to the HTTP caller. No further data should be sent after this call. * @param [in] pData The data to be sent to the HTTP caller. * @param [in] length The length of the data to be sent. * @return N/A. */ void WebServer::HTTPResponse::sendData(const uint8_t* pData, size_t length) { if (m_dataSent) { ESP_LOGE(LOG_TAG, "HTTPResponse: Data already sent! Attempt to send again/more."); return; } m_dataSent = true; mg_send_head(m_nc, m_status, length, buildHeaders().c_str()); mg_send(m_nc, pData, length); m_nc->flags |= MG_F_SEND_AND_CLOSE; } // sendData
static void ro_vars_handler(struct mg_connection *c, int ev, void *p) { (void) p; if (ev != MG_EV_HTTP_REQUEST) return; LOG(LL_DEBUG, ("RO-vars requested")); /* Reply with JSON object that contains read-only variables */ mg_send_head(c, 200, -1, JSON_HEADERS); mg_printf_http_chunk(c, "{"); struct ro_var *rv; for (rv = g_ro_vars; rv != NULL; rv = rv->next) { mg_printf_http_chunk(c, "%s\n \"%s\": \"%s\"", rv == g_ro_vars ? "" : ",", rv->name, *rv->ptr); } mg_printf_http_chunk(c, "\n}\n"); mg_printf_http_chunk(c, ""); /* Zero chunk - end of response */ c->flags |= MG_F_SEND_AND_CLOSE; }
static void conf_handler(struct mg_connection *c, int ev, void *p) { struct http_message *hm = (struct http_message *) p; if (ev != MG_EV_HTTP_REQUEST) return; LOG(LL_DEBUG, ("[%.*s] requested", (int) hm->uri.len, hm->uri.p)); char *json = NULL; int status = -1; int rc = 200; if (mg_vcmp(&hm->uri, "/conf/defaults") == 0) { struct sys_config cfg; memset(&cfg, 0, sizeof(cfg)); if (load_config_defaults(&cfg)) { json = emit_sys_config(&cfg); } } else if (mg_vcmp(&hm->uri, "/conf/current") == 0) { json = emit_sys_config(&s_cfg); } else if (mg_vcmp(&hm->uri, "/conf/save") == 0) { status = (save_json(&hm->body, CONF_FILE) != 1); if (status == 0) c->flags |= MG_F_RELOAD_CONFIG; } else if (mg_vcmp(&hm->uri, "/conf/reset") == 0) { struct stat st; if (stat(CONF_FILE, &st) == 0) { status = remove(CONF_FILE); } else { status = 0; } if (status == 0) c->flags |= MG_F_RELOAD_CONFIG; } if (json == NULL) { if (asprintf(&json, "{\"status\": %d}\n", status) < 0) { json = "{\"status\": -1}"; } else { rc = (status == 0 ? 200 : 500); } } { int len = strlen(json); mg_send_head(c, rc, len, JSON_HEADERS); mg_send(c, json, len); free(json); } c->flags |= MG_F_SEND_AND_CLOSE; }
/** * @brief Send data to the HTTP caller. * Send the data to the HTTP caller. No further data should be sent after this call. * @param [in] pData The data to be sent to the HTTP caller. * @param [in] length The length of the data to be sent. * @return N/A. */ void WebServer::HTTPResponse::sendData(uint8_t *pData, size_t length) { if (m_dataSent) { ESP_LOGE(tag, "HTTPResponse: Data already sent! Attempt to send again/more."); return; } m_dataSent = true; std::map<std::string, std::string>::iterator iter; std::string headers; for (iter = m_headers.begin(); iter != m_headers.end(); iter++) { if (headers.length() == 0) { headers = iter->first + ": " + iter->second; } else { headers = "; " + iter->first + "=" + iter->second; } } mg_send_head(m_nc, m_status, length, headers.c_str()); mg_send(m_nc, pData, length); m_nc->flags |= MG_F_SEND_AND_CLOSE; } // sendData
static void recovery_status(struct mg_connection *nc, int ev, void *ev_data) { ipc_message ipc; int ret; char buf[4096]; (void)ev; (void)ev_data; ret = ipc_get_status(&ipc); if (ret) { mg_http_send_error(nc, 500, NULL); return; } snprintf(buf, sizeof(buf), "{\r\n" "\t\"Status\" : \"%d\",\r\n" "\t\"Msg\" : \"%s\",\r\n" "\t\"Error\" : \"%d\",\r\n" "\t\"LastResult\" : \"%d\"\r\n" "}\r\n", ipc.data.status.current, strlen(ipc.data.status.desc) ? ipc.data.status.desc : "", ipc.data.status.error, ipc.data.status.last_result); mg_send_head(nc, 200, strlen(buf), "Cache: no-cache\r\n" "Content-Type: text/plain"); mg_send(nc, buf, strlen(buf)); nc->flags |= MG_F_SEND_AND_CLOSE; }
/** * Handle mongoose events. These are mostly requests to process incoming * browser requests. The ones we handle are: * GET / - Send the enter details page. * GET /set - Set the connection info (REST request). * POST /ssidSelected - Set the connection info (HTML FORM). */ static void mongoose_event_handler(struct mg_connection *nc, int ev, void *evData) { ESP_LOGD(tag, "- Event: %s", mongoose_eventToString(ev)); switch (ev) { case MG_EV_HTTP_REQUEST: { struct http_message *message = (struct http_message *) evData; char *uri = mgStrToStr(message->uri); ESP_LOGD(tag, " - uri: %s", uri); if (strcmp(uri, "/set") ==0 ) { connection_info_t connectionInfo; //fix saveConnectionInfo(&connectionInfo); ESP_LOGD(tag, "- Set the new connection info to ssid: %s, password: %s", connectionInfo.ssid, connectionInfo.password); mg_send_head(nc, 200, 0, "Content-Type: text/plain"); } if (strcmp(uri, "/") == 0) { mg_send_head(nc, 200, sizeof(selectAP_html), "Content-Type: text/html"); mg_send(nc, selectAP_html, sizeof(selectAP_html)); } // Handle /ssidSelected // This is an incoming form with properties: // * ssid - The ssid of the network to connect against. // * password - the password to use to connect. // * ip - Static IP address ... may be empty // * gw - Static GW address ... may be empty // * netmask - Static netmask ... may be empty if(strcmp(uri, "/ssidSelected") == 0) { // We have received a form page containing the details. The form body will // contain: // ssid=<value>&password=<value> ESP_LOGD(tag, "- body: %.*s", message->body.len, message->body.p); connection_info_t connectionInfo; mg_get_http_var(&message->body, "ssid", connectionInfo.ssid, SSID_SIZE); mg_get_http_var(&message->body, "password", connectionInfo.password, PASSWORD_SIZE); char ipBuf[20]; if (mg_get_http_var(&message->body, "ip", ipBuf, sizeof(ipBuf)) > 0) { inet_pton(AF_INET, ipBuf, &connectionInfo.ipInfo.ip); } else { connectionInfo.ipInfo.ip.addr = 0; } if (mg_get_http_var(&message->body, "gw", ipBuf, sizeof(ipBuf)) > 0) { inet_pton(AF_INET, ipBuf, &connectionInfo.ipInfo.gw); } else { connectionInfo.ipInfo.gw.addr = 0; } if (mg_get_http_var(&message->body, "netmask", ipBuf, sizeof(ipBuf)) > 0) { inet_pton(AF_INET, ipBuf, &connectionInfo.ipInfo.netmask); } else { connectionInfo.ipInfo.netmask.addr = 0; } ESP_LOGD(tag, "ssid: %s, password: %s", connectionInfo.ssid, connectionInfo.password); mg_send_head(nc, 200, 0, "Content-Type: text/plain"); saveConnectionInfo(&connectionInfo); bootWiFi2(); } // url is "/ssidSelected" // Else ... unknown URL else { mg_send_head(nc, 404, 0, "Content-Type: text/plain"); } nc->flags |= MG_F_SEND_AND_CLOSE; free(uri); break; } // MG_EV_HTTP_REQUEST } // End of switch } // End of mongoose_event_handler