修复log记录错误(第一个节点无法落盘),更新http解析为现成库实现,优化退出逻辑。
This commit is contained in:
@ -1,80 +1,85 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "network/mongoose/mongoose.h"
|
||||
|
||||
#include "http_rel.h"
|
||||
/* 接收状态辅助结构 */
|
||||
struct recv_state {
|
||||
char *request; // 完整请求字符串
|
||||
int done; // 接收完成标志
|
||||
int error; // 错误标志
|
||||
};
|
||||
|
||||
/* mongoose 事件处理函数 */
|
||||
static void http_recv_handler(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
|
||||
{
|
||||
struct recv_state *state = (struct recv_state *)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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return state.request;
|
||||
}
|
||||
|
||||
/* http_get_body 无需修改,保持原样 */
|
||||
const char *http_get_body(const char *buf)
|
||||
{
|
||||
if (!buf) return NULL;
|
||||
|
||||
/* 找到 header 与 body 之间的空行 "\r\n\r\n" */
|
||||
const char *sep = strstr(buf, "\r\n\r\n");
|
||||
if (!sep) return NULL; /* 格式错误 */
|
||||
|
||||
const char *body = sep + 4; /* 跳过 "\r\n\r\n" */
|
||||
|
||||
/* 简单判断:如果后面还有数据,就认为是 body */
|
||||
if (*body == '\0') return NULL; /* 没有 body */
|
||||
|
||||
if (!sep) return NULL;
|
||||
const char *body = sep + 4;
|
||||
if (*body == '\0') return NULL;
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
/* 一次性读完一个 HTTP 请求,返回 malloc 得到的完整字符串(含头+体),调用者 free。
|
||||
返回 NULL 表示读取出错或内存不足。
|
||||
*/
|
||||
char *recv_http_request(int cfd)
|
||||
{
|
||||
char head[8192];
|
||||
int body_len = 0;
|
||||
|
||||
/* 1. 读头部到 \r\n\r\n */
|
||||
size_t n = 0;
|
||||
while (n < sizeof(head)) {
|
||||
if (read(cfd, head + n, 1) != 1) goto err;
|
||||
if (n >= 3 && memcmp(head + n - 3, "\r\n\r", 3) == 0) {
|
||||
if (read(cfd, head + n, 1) != 1) goto err; /* 再吃一个 \n */
|
||||
++n;
|
||||
break;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
head[n] = 0;
|
||||
|
||||
/* 2. 解析 Content-Length */
|
||||
const char *p = head;
|
||||
while ((p = strchr(p, '\n')) != NULL) {
|
||||
if (sscanf(p, "\nContent-Length: %d", &body_len) == 1) break;
|
||||
++p;
|
||||
}
|
||||
|
||||
/* 3. 读 body */
|
||||
char *body = NULL;
|
||||
if (body_len > 0) {
|
||||
body = malloc(body_len + 1);
|
||||
if (!body) goto err;
|
||||
size_t got = 0;
|
||||
while (got < (size_t)body_len) {
|
||||
ssize_t rd = read(cfd, body + got, body_len - got);
|
||||
if (rd <= 0) { free(body); goto err; }
|
||||
got += rd;
|
||||
}
|
||||
body[got] = 0;
|
||||
}
|
||||
|
||||
/* 4. 拼成完整字符串 */
|
||||
char *full = malloc(n + (body_len ? body_len : 0) + 1);
|
||||
if (!full) { free(body); goto err; }
|
||||
memcpy(full, head, n);
|
||||
if (body_len) memcpy(full + n, body, body_len);
|
||||
full[n + body_len] = 0;
|
||||
free(body);
|
||||
return full;
|
||||
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user