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); } } }
inline bool handle_read(mg_connection* connection,const bool authenticated,const std::string& request, const std::string& query) { std::string comma_list=get_query(connection,"read"); if(comma_list.size()>0) { auto& database=get_database(connection); std::cout<<"\tReading \""<<comma_list<<"\"..."<<std::flush; if((database.permissions&P_READ)!=0||(authenticated&&database.allow_authentication())) { mg_send(connection,database.read(comma_list),"application/json"); std::cout<<"done."<<std::endl; } else { mg_send_status(connection,"401 UNAUTHORIZED"); std::cout<<"denied."<<std::endl; } return true; } return false; }
SJ_PRIVATE enum v7_err Http_response_writeHead(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; DECLARE_CONN(); unsigned long code = 200; v7_val_t arg0 = v7_arg(v7, 0), arg1 = v7_arg(v7, 1); if (v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) { rcode = v7_throwf(v7, "Error", "Headers already sent"); goto clean; } if (v7_is_number(arg0)) { code = v7_to_number(arg0); } write_http_status(c, code); http_write_headers(v7, arg1, c); mg_send(c, "\r\n", 2); v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1)); *res = v7_get_this(v7); clean: return rcode; }
static void client_handler(struct mg_connection *conn, int ev, void *p) { struct mbuf *io = &conn->recv_mbuf; (void) p; if (ev == MG_EV_CONNECT) { if (conn->flags & MG_F_CLOSE_IMMEDIATELY) { printf("%s\n", "Error connecting to server!"); exit(EXIT_FAILURE); } printf("%s\n", "Connected to server. Type a message and press enter."); } else if (ev == MG_EV_RECV) { if (conn->flags & MG_F_USER_1) { // Received data from the stdin, forward it to the server struct mg_connection *c = (struct mg_connection *) conn->user_data; mg_send(c, io->buf, io->len); mbuf_remove(io, io->len); } else { // Received data from server connection, print it fwrite(io->buf, io->len, 1, stdout); mbuf_remove(io, io->len); } } else if (ev == MG_EV_CLOSE) { // Connection has closed, most probably cause server has stopped exit(EXIT_SUCCESS); } }
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()); } } }
/* * Code common to V1 and V2 */ static void upload_handler(struct mg_connection *nc, int ev, void *p) { struct mg_http_multipart_part *mp; struct file_upload_state *fus; switch (ev) { case MG_EV_HTTP_PART_BEGIN: mp = (struct mg_http_multipart_part *) p; fus = (struct file_upload_state *) calloc(1, sizeof(*fus)); if (fus == NULL) { mg_http_send_error(nc, 500, "Out of memory"); break; } fus->fd = ipc_inst_start_ext(SOURCE_WEBSERVER, strlen(mp->file_name), mp->file_name, false); if (fus->fd < 0) { mg_http_send_error(nc, 500, "Failed to queue command"); free(fus); break; } mp->user_data = fus; break; case MG_EV_HTTP_PART_DATA: mp = (struct mg_http_multipart_part *) p; fus = (struct file_upload_state *) mp->user_data; if (!fus) break; ipc_send_data(fus->fd, (char *) mp->data.p, mp->data.len); fus->len += mp->data.len; break; case MG_EV_HTTP_PART_END: mp = (struct mg_http_multipart_part *) p; fus = (struct file_upload_state *) mp->user_data; if (!fus) break; ipc_end(fus->fd); mg_send_response_line(nc, 200, "Content-Type: text/plain\r\n" "Connection: close"); mg_send(nc, "\r\n", 2); mg_printf(nc, "Ok, %s - %d bytes.\r\n", mp->file_name, (int) fus->len); nc->flags |= MG_F_SEND_AND_CLOSE; mp->user_data = NULL; free(fus); break; } }
void RpcRespBroker::sendHttpResp(mg_connection *conn, int status, const std::string &resp) { mg_printf(conn, "HTTP/1.1 %d\r\n", status); mg_printf(conn, "%s", "Content-Type: text/html\r\n"); mg_printf(conn, "Content-Length: %lu\r\n", resp.size()); mg_printf(conn, "%s", "Connection: close\r\n"); mg_printf(conn, "%s", "\r\n"); mg_send(conn, resp.c_str(), resp.size()); }
/* * Forwards the jpeg frame data to all open mjpeg connections. * * Incoming messages follow a very simple binary frame format: * 4 bytes: timestamp (in network byte order) * n bytes: jpeg payload * * The timestamp is used to compute a lag. * It's done in a quite stupid way as it requires the device clock * to be synchronized with the cloud endpoint. */ static void push_frame_to_clients(struct mg_mgr *mgr, const struct websocket_message *wm) { struct mg_connection *nc; /* * mjpeg connections are tagged with the MG_F_USER_2 flag so we can find them * my scanning the connection list provided by the mongoose manager. */ for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { if (!(nc->flags & MG_F_USER_2)) continue; // Ignore un-marked requests mg_printf(nc, "--w00t\r\nContent-Type: image/jpeg\r\n" "Content-Length: %lu\r\n\r\n", (unsigned long) wm->size); mg_send(nc, wm->data, wm->size); mg_send(nc, "\r\n", 2); printf("Image pushed to %p\n", nc); } }
/** * @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
void mg_send_websocket_frame(struct mg_connection *nc, int op, const void *data, size_t len) { struct ws_mask_ctx ctx; DBG(("%p %d %d", nc, op, (int) len)); mg_send_ws_header(nc, op, len, &ctx); mg_send(nc, data, len); mg_ws_mask_frame(&nc->send_mbuf, &ctx); if (op == WEBSOCKET_OP_CLOSE) { nc->flags |= MG_F_SEND_AND_CLOSE; } }
static void ev_handler(struct mg_connection *nc, int ev, void *p) { struct mbuf *io = &nc->recv_mbuf; (void) p; switch (ev) { case MG_EV_RECV: mg_send(nc, io->buf, io->len); // Echo message back mbuf_remove(io, io->len); // Discard message from recv buffer break; default: break; } }
void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r) { size_t sent = r->io->len - r->start; mg_dns_insert_header(r->io, r->start, r->msg); if (!(nc->flags & MG_F_UDP)) { uint16_t len = htons((uint16_t) sent); mbuf_insert(r->io, r->start, &len, 2); } if (&nc->send_mbuf != r->io) { mg_send(nc, r->io->buf + r->start, r->io->len - r->start); r->io->len = r->start; } }
void mg_ev_handler(struct mg_connection *nc, int ev, void *ev_data) { LOG(LL_DEBUG, ("%p ev %d", nc, ev)); switch (ev) { case MG_EV_ACCEPT: { char addr[32]; mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); LOG(LL_INFO, ("Connection %p 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_sock_addr_to_str(&nc->sa, addr, sizeof(addr), 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, ("Connection %p closed", nc)); 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); } } }
void BasicHttp::SendFile(std::string uri, std::string content){ auto range = _connections.equal_range(uri); if(range.first == range.second) return; auto it = range.first; auto reply = std::string("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: zip\r\nContent-Length: ") .append(lsf::util::StringExt::Format("%u", content.length())).append("\r\n\r\n").append(content); mg_send(it->second, reply.c_str(), reply.length()); it->second->flags |= MG_F_SEND_AND_CLOSE; _connections.erase(it); LSF_LOG_INF("uri:%s, reply:%s", uri.c_str(), reply.c_str()); }
static void mg_send_ws_header(struct mg_connection *nc, int op, size_t len, struct ws_mask_ctx *ctx) { int header_len; unsigned char header[10]; header[0] = (op & WEBSOCKET_DONT_FIN ? 0x0 : FLAGS_MASK_FIN) | (op & FLAGS_MASK_OP); if (len < 126) { header[1] = (unsigned char) len; header_len = 2; } else if (len < 65535) { uint16_t tmp = htons((uint16_t) len); header[1] = 126; memcpy(&header[2], &tmp, sizeof(tmp)); header_len = 4; } else { uint32_t tmp; header[1] = 127; tmp = htonl((uint32_t)((uint64_t) len >> 32)); memcpy(&header[2], &tmp, sizeof(tmp)); tmp = htonl((uint32_t)(len & 0xffffffff)); memcpy(&header[6], &tmp, sizeof(tmp)); header_len = 10; } /* client connections enable masking */ if (nc->listener == NULL) { header[1] |= 1 << 7; /* set masking flag */ mg_send(nc, header, header_len); ctx->mask = mg_ws_random_mask(); mg_send(nc, &ctx->mask, sizeof(ctx->mask)); ctx->pos = nc->send_mbuf.len; } else { mg_send(nc, header, header_len); ctx->pos = 0; } }
SJ_PRIVATE enum v7_err Http_response_write(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; DECLARE_CONN(); if (!v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) { write_http_status(c, 200); mg_send(c, "\r\n", 2); v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1)); } Http_write_data(v7, c); *res = v7_get_this(v7); clean: return rcode; }
void BasicHttp::SendReply(std::string uri, std::string reply){ auto range = _connections.equal_range(uri); if(range.first == range.second) return; std::string reply_all("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\nContent-Length:"); reply_all.append(lsf::util::StringExt::Format("%u", (uint32_t)reply.length())) .append("\r\n\r\n").append(reply).append("\r\n"); auto it = range.first; mg_send(it->second, reply_all.c_str(), reply_all.length()); it->second->flags |= MG_F_SEND_AND_CLOSE; _connections.erase(it); LSF_LOG_INF("uri:%s, reply:%s", uri.c_str(), reply_all.c_str()); }
void BasicHttp::SendError(std::string uri, int errcode, std::string reply){ auto range = _connections.equal_range(uri); if(range.first == range.second) return; std::ostringstream oss; oss << "HTTP/1.1 " << errcode << " " << reply.c_str() << "\r\n\r\n" << reply.c_str() << "\r\n"; auto it = range.first; mg_send(it->second, oss.str().c_str(), oss.str().length()); it->second->flags |= MG_F_SEND_AND_CLOSE; _connections.erase(it); LSF_LOG_INF("uri:%s, reply:%s", uri.c_str(), oss.str().c_str()); }
/* * These functions are for V1 of the protocol */ static void upload_handler_v1(struct mg_connection *nc, int ev, void *p) { struct mg_str *filename, *data; struct http_message *hm; size_t length; char buf[16]; int fd; switch (ev) { case MG_EV_HTTP_REQUEST: hm = (struct http_message *) p; filename = mg_get_http_header(hm, "X_FILENAME"); if (filename == NULL) { mg_http_send_error(nc, 403, NULL); return; } data = mg_get_http_header(hm, "Content-length"); if (data == NULL || data->len >= ARRAY_SIZE(buf)) { mg_http_send_error(nc, 403, NULL); return; } memcpy(buf, data->p, data->len); buf[data->len] = '\0'; length = strtoul(data->p, NULL, 10); if (length == 0) { mg_http_send_error(nc, 403, NULL); return; } fd = ipc_inst_start_ext(SOURCE_WEBSERVER, filename->len, filename->p, false); ipc_send_data(fd, (char *) hm->body.p, hm->body.len); ipc_end(fd); mg_send_response_line(nc, 200, "Content-Type: text/plain\r\n" "Connection: close"); mg_send(nc, "\r\n", 2); mg_printf(nc, "Ok, %.*s - %d bytes.\r\n", (int) filename->len, filename->p, (int) length); nc->flags |= MG_F_SEND_AND_CLOSE; break; default: upload_handler(nc, ev, p); break; } }
static void forward_body(struct peer *src, struct peer *dst) { struct mbuf *src_io = &src->nc->recv_mbuf; if (src->body_sent < src->body_len) { size_t to_send = src->body_len - src->body_sent; if (src_io->len < to_send) { to_send = src_io->len; } mg_send(dst->nc, src_io->buf, to_send); src->body_sent += to_send; mbuf_remove(src_io, to_send); } #ifdef DEBUG write_log("forward_body %p (ka=%d) -> %p sent %d of %d\n", src->nc, src->flags.keep_alive, dst->nc, src->body_sent, src->body_len); #endif }
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; }
static void server_handler(struct mg_connection *nc, int ev, void *p) { (void) p; if (ev == MG_EV_RECV) { // Push received message to all ncections struct mbuf *io = &nc->recv_mbuf; struct mg_connection *c; for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) { if (!(c->flags |= MG_F_USER_2)) continue; // Skip non-client connections mg_send(c, io->buf, io->len); } mbuf_remove(io, io->len); } else if (ev == MG_EV_ACCEPT) { char addr[32]; mg_sock_addr_to_str(p, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); printf("New client connected from %s\n", addr); } }
void BasicHttp::HandleRequst(struct mg_connection *nc, int ev, void* ev_data){ http_message* hm = (http_message*)ev_data; std::string uri(hm->uri.p, hm->uri.len); std::string query(hm->query_string.p, hm->query_string.len); std::string body(hm->body.p, hm->body.len); auto it = _handlers.find(uri); if(_handlers.end() == it){ std::ostringstream oss; oss << "HTTP/1.1 404 Not Found\r\n\r\n404 Not Found\r\n"; mg_send(nc, oss.str().c_str(), oss.str().length()); nc->flags |= MG_F_SEND_AND_CLOSE; LSF_LOG_INF("uri:%s, query:%s,reply:%s", uri.c_str(), query.c_str(), oss.str().c_str()); return; } _connections.emplace(uri, nc); it->second(query, body); LSF_LOG_INF("GetRequest: uri:%s, query:%s, body:%s", uri.c_str(), query.c_str(), body.c_str()); }
void handle_read_call(struct mg_connection* nc, struct http_message* hm) { char** result = init_result_array(); char* tmp = init_tmp(); if (result == NULL || tmp == NULL) { free(result); free(tmp); mg_error(nc, ERR_OUT_OF_MEMORY); return; } split(result, tmp, hm->query_string.p, "&=", hm->query_string.len); int resolution = -1; char* pict_id = NULL; parse_uri(result, &resolution, &pict_id); if (resolution != -1 && pict_id != NULL) { char* image_buffer = NULL; uint32_t image_size = 0; int err_check = do_read(pict_id, resolution, &image_buffer, &image_size, db_file); if (err_check != 0) { mg_error(nc, err_check); } else { mg_printf(nc, "HTTP/1.1 200 OK\r\n" "Content-Type: image/jpeg\r\n" "Content-Length: %" PRIu32 "\r\n\r\n", image_size); mg_send(nc, image_buffer, image_size); nc->flags |= MG_F_SEND_AND_CLOSE; } free(image_buffer); } else { mg_error(nc, ERR_INVALID_ARGUMENT); } free(result); free(tmp); }
void mg_send_websocket_framev(struct mg_connection *nc, int op, const struct mg_str *strv, int strvcnt) { struct ws_mask_ctx ctx; int i; int len = 0; for (i = 0; i < strvcnt; i++) { len += strv[i].len; } mg_send_ws_header(nc, op, len, &ctx); for (i = 0; i < strvcnt; i++) { mg_send(nc, strv[i].p, strv[i].len); } mg_ws_mask_frame(&nc->send_mbuf, &ctx); if (op == WEBSOCKET_OP_CLOSE) { nc->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; }
void do_send(struct mg_connection *nc) { if (nc->send_mbuf.len > HWM) return; mg_send(nc, data, sizeof(data)); }
void osd_http_send(struct mg_connection *nc, struct http_message *hm) { int last_hashs[NUM_BLOCKS]; int i; char hex[9]; int send_count; int num_blocks; long long end_time; uint32_t x = 0xffffffff; // end of data s_request_time = get_current_time(); if (s_osd_data_ready == false) { //print_log("s_osd_data not ready"); send_200(nc); return; } hex[8] = '\0'; for (i = 0; i < (hm->body.len - 6) / 8; i++) { strncpy(hex, (hm->body.p + 6) + i * 8, 8); last_hashs[i] = (uint32_t)strtol(hex, NULL, 16); //print_log("hex = %s", hex); } pthread_mutex_lock(&s_mutex); num_blocks = ntohs(s_osd_data.frame_width) * ntohs(s_osd_data.frame_height) / ntohs(s_osd_data.block_width) / ntohs(s_osd_data.block_height); //print_log("num_blocks = %d", num_blocks); send_count = 0; for (i = 0; i < num_blocks; i++) { if (ntohl(s_osd_data.blocks[i].hash) != last_hashs[i]) { send_count++; } } mg_printf(nc, "HTTP/1.1 200 OK\r\n" "Access-Control-Allow-Origin: *\r\n" "Access-Control-Allow-Headers: X-Requested-With\r\n" "Content-Length: %d\r\n" "Content-Type: text/plain; charset=x-user-defined\r\n" "\r\n", 8 + send_count * sizeof(s_osd_data.blocks[0]) + 4); mg_send(nc, (const void *)&s_osd_data, 8); send_count = 0; for (i = 0; i < num_blocks; i++) { if (ntohl(s_osd_data.blocks[i].hash) != last_hashs[i]) { mg_send(nc, &s_osd_data.blocks[i], sizeof(s_osd_data.blocks[i])); send_count++; } } pthread_mutex_unlock(&s_mutex); mg_send(nc, &x, 4); end_time = get_current_time(); if (send_count != 0) { print_log("send_count = %d, time = %lld", send_count, end_time - s_request_time); } }
void TsHttpRpc::_mg_event_handler(struct mg_connection *nc, int ev, void *ev_data) { struct http_message *hm = (struct http_message*)ev_data; TsHttpRpc* _this = (TsHttpRpc*)nc->user_data; if (NULL == _this) { EXLOGE("[ERROR] invalid http request.\n"); return; } switch (ev) { case MG_EV_HTTP_REQUEST: { ex_astr uri; ex_chars _uri; _uri.resize(hm->uri.len + 1); memset(&_uri[0], 0, hm->uri.len + 1); memcpy(&_uri[0], hm->uri.p, hm->uri.len); uri = &_uri[0]; #ifdef EX_DEBUG const char* dbg_method = NULL; if (hm->method.len == 3 && 0 == memcmp(hm->method.p, "GET", hm->method.len)) dbg_method = "GET"; else if (hm->method.len == 4 && 0 == memcmp(hm->method.p, "POST", hm->method.len)) dbg_method = "POST"; else dbg_method = "UNSUPPORTED-HTTP-METHOD"; EXLOGV("[rpc] got %s request: %s\n", dbg_method, uri.c_str()); #endif ex_astr ret_buf; bool b_is_index = false; if (uri == "/") { ex_wstr page = L"<html lang=\"zh_CN\"><head><meta charset=\"utf-8\"/><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title>Teleport Assistor</title>\n<style type=\"text/css\">\n.box{padding:20px;margin:40px;border:1px solid #78b17c;background-color:#e4ffe5;}\n</style>\n</head><body><div class=\"box\">Teleport Assistor works fine.</div></body></html>"; ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %ld\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); nc->flags |= MG_F_SEND_AND_CLOSE; return; } if (uri == "/config") { uri = "/index.html"; b_is_index = true; } ex_astr temp; size_t offset = uri.find("/", 1); if (offset > 0) { temp = uri.substr(1, offset-1); if(temp == "api") { ex_astr method; ex_astr json_param; int rv = _this->_parse_request(hm, method, json_param); if (0 != rv) { EXLOGE("[ERROR] http-rpc got invalid request.\n"); _this->_create_json_ret(ret_buf, rv); } else { _this->_process_js_request(method, json_param, ret_buf); } mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %ld\r\nContent-Type: application/json\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); nc->flags |= MG_F_SEND_AND_CLOSE; return; } } ex_astr file_suffix; offset = uri.rfind("."); if (offset > 0) { file_suffix = uri.substr(offset, uri.length()); } ex_wstr2astr(g_env.m_site_path, temp); ex_astr index_path = temp + uri; FILE* file = ex_fopen(index_path.c_str(), "rb"); if (file) { unsigned long file_size = 0; char* buf = 0; size_t ret = 0; fseek(file, 0, SEEK_END); file_size = ftell(file); buf = new char[file_size]; memset(buf, 0, file_size); fseek(file, 0, SEEK_SET); ret = fread(buf, 1, file_size, file); fclose(file); ex_astr content_type = _this->get_content_type(file_suffix); mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %ld\r\nContent-Type: %s\r\n\r\n", file_size, content_type.c_str()); mg_send(nc, buf, (int)file_size); delete []buf; nc->flags |= MG_F_SEND_AND_CLOSE; return; } else if (b_is_index) { ex_wstr page = L"<html lang=\"zh_CN\"><html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr><center><p>Teleport Assistor configuration page not found.</p></center></body></html>"; ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); mg_printf(nc, "HTTP/1.0 404 File Not Found\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %ld\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); nc->flags |= MG_F_SEND_AND_CLOSE; return; } } break; default: break; } }