#include #include #include #include #include "network/mongoose/mongoose.h" #include "tools/log/log.h" #include "http_rel.h" /* 接收状态辅助结构 */ struct recv_state { char *request; // 完整请求字符串 int done; // 接收完成标志 int error; // 错误标志 }; static void http_recv_handler(struct mg_connection *c, int ev, void *ev_data) { // 从连接对象获取用户数据 struct recv_state *state = (struct recv_state *)c->fn_data; switch (ev) { case MG_EV_HTTP_MSG: { struct mg_http_message *hm = (struct mg_http_message *)ev_data; /* 分配内存并复制完整请求(头+体) */ state->request = malloc(hm->message.len + 1); if (state->request) { memcpy(state->request, hm->message.buf, hm->message.len); state->request[hm->message.len] = '\0'; } else { state->error = 1; // 内存不足 } state->done = 1; break; } case MG_EV_CLOSE: case MG_EV_ERROR: state->done = 1; break; } } char *recv_http_request(int cfd) { struct mg_mgr mgr; struct mg_connection *c; struct recv_state state = {0}; /* 初始化 mongoose 管理器 */ mg_mgr_init(&mgr); /* 将已连接的 socket 包装成 mongoose 连接 */ c = mg_wrapfd(&mgr, cfd, http_recv_handler, &state); /* 设置 5 秒超时 */ int64_t end_time = mg_millis() + 5000; while (!state.done && mg_millis() < end_time) { mg_mgr_poll(&mgr, 100); } /* 超时处理 */ if (!state.done) { state.error = 1; } /* 清理 mongoose 资源(不会关闭原始 fd) */ mg_mgr_free(&mgr); /* 出错时释放内存 */ if (state.error) { free(state.request); // 安全释放(free(NULL) 是安全的) return NULL; } /* 确保返回的请求不为空 */ if (!state.request) { return NULL; } return state.request; } /* http_get_body 无需修改,保持原样 */ const char *http_get_body(const char *buf) { if (!buf) return NULL; const char *sep = strstr(buf, "\r\n\r\n"); if (!sep) return NULL; const char *body = sep + 4; if (*body == '\0') return NULL; return body; } /** * @brief 初始化HTTP监听socket,所有错误通过logmanager记录 * @param port 监听端口 * @param logger 日志管理器实例指针 * @return 成功返回监听fd,失败返回-1并记录日志 */ int init_http_network(int port, log_manager *logger) { logs *log; int fd; /* 1. 创建socket */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { log = malloc(sizeof(logs)); // cppcheck-suppress uninitdata snprintf(log->log, sizeof(log->log), "[FATAL] socket() failed: %s", strerror(errno)); logger->in_log(log, logger); return -1; } /* 2. 设置SO_REUSEADDR,避免TIME_WAIT状态导致bind失败 */ int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[ERROR] setsockopt(SO_REUSEADDR) on fd=%d failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } /* 3. 设置为非阻塞模式(配合epoll使用) */ int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[ERROR] fcntl(F_GETFL) on fd=%d failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[ERROR] fcntl(O_NONBLOCK) on fd=%d failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } /* 4. 绑定到指定端口 */ struct sockaddr_in addr = {0}; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[FATAL] bind(port %d) failed: %s (fd=%d)", port, strerror(errno), fd); logger->in_log(log, logger); close(fd); return -1; } /* 5. 开始监听 */ if (listen(fd, 10) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[FATAL] listen(fd=%d, backlog=10) failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } /* 6. 成功日志 */ log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[HTTP] Successfully listening on port %d (fd=%d)", port, fd); logger->in_log(log, logger); return fd; }