# API-libmongoose — 嵌入式 HTTP/WebSocket 网络库

> 版本: v1.0  
> 日期: 2026-07-08  
> 来源: Mongoose v7.22 (MIT 许可，https://github.com/cesanta/mongoose)  
> 状态: ✅ 导入完成，x86 + ARM 双平台编译通过（零警告）

---

## 1. 模块概述

libmongoose 是 Mongoose v7.22 开源库的封装模块。Mongoose 是一个**单文件、纯 C 实现的嵌入式网络库**，广泛用于 IoT 和嵌入式设备。本模块主要用于 RTU 的 Web 管理服务（`libweb_server`），提供 HTTP REST API 和 WebSocket 双向通信能力。

| 功能 | 说明 |
|------|------|
| HTTP 服务器 | 解析请求、路由匹配、JSON 响应，用于 REST API |
| WebSocket | 双向消息推送（实时遥测数据、告警通知） |
| 事件驱动 | 基于 epoll 的异步 IO，单线程管理所有连接 |
| 定时器 | 毫秒级软定时器，无需额外线程 |
| 跨平台 | Linux / FreeRTOS / Zephyr / ESP32 等，本工程只用 Linux |

### 架构位置

```
libweb_server (system/) — REST API + WebSocket 管理
    │
    ▼
libmongoose (protocol/) — HTTP/WS 协议栈
    │
    ▼
Linux kernel socket + epoll
```

---

## 2. 文件结构

```
src/protocol/libmongoose/
├── inc/
│   ├── myMongoose.h      # RTU 适配头（编译配置宏 + #include "mongoose.h"）
│   └── mongoose.h        # Mongoose v7.22 头文件（5748 行，上游文件）
└── src/
    └── mongoose.c        # Mongoose v7.22 实现（31786 行，上游文件）

release/
├── inc/
│   ├── myMongoose.h      # 拷贝自 src，供其他模块包含
│   └── mongoose.h        # 拷贝自 src
└── x86/lib/
    └── libmongoose.a     # x86 编译产物（462KB）
└── arm/lib/
    └── libmongoose.a     # ARM 编译产物（471KB）
```

---

## 3. 编译配置

在 `myMongoose.h` 中定义以下宏（必须在 `#include "mongoose.h"` 之前）：

| 宏 | 值 | 说明 |
|------|-----|------|
| `MG_ENABLE_LOG` | 1 | 启用内置日志（printf 到 stderr） |
| `MG_ENABLE_FILE` | 0 | 禁用文件系统（RTU 不通过 mongoose 提供静态文件） |
| `MG_ENABLE_POSIX_FS` | 0 | 禁用 POSIX 文件 API |
| `MG_ENABLE_EPOLL` | 1 | 启用 epoll（Linux 高效 IO 多路复用） |
| `MG_ENABLE_POLL` | 1 | 启用 poll（epoll 回退方案） |
| `MG_ENABLE_SOCKET` | 1 | 使用 Linux 内核 socket |

---

## 4. 核心数据结构

### 4.1 mg_mgr — 事件管理器

```c
struct mg_mgr
{
    struct mg_connection *conns;  /* 活动连接链表 */
    struct mg_timer *timers;      /* 定时器链表 */
    // ... 内部字段
};
```

每个进程只需一个 `mg_mgr` 实例，管理所有连接和定时器。

### 4.2 mg_connection — 连接

```c
struct mg_connection
{
    struct mg_connection *next;   /* 链表指针 */
    struct mg_mgr *mgr;           /* 所属管理器 */
    struct mg_addr peer;          /* 对端地址 */
    void *fd;                     /* socket 文件描述符 */
    unsigned long id;             /* 连接 ID */
    unsigned is_websocket : 1;    /* 是否为 WebSocket 连接 */
    unsigned is_client : 1;       /* 是否为客户端连接 */
    // ...
};
```

### 4.3 事件类型

```c
enum
{
    MG_EV_ERROR,       /* 错误 */
    MG_EV_OPEN,        /* 连接建立（仅客户端出站连接） */
    MG_EV_POLL,        /* mg_mgr_poll() 每次迭代触发 */
    MG_EV_RESOLVE,     /* DNS 解析完成 */
    MG_EV_CONNECT,     /* TCP 连接完成 */
    MG_EV_ACCEPT,      /* TCP 新连接接受 */
    MG_EV_TLS_HS,      /* TLS 握手完成 */
    MG_EV_READ,        /* 数据可读 */
    MG_EV_WRITE,       /* 数据可写 */
    MG_EV_CLOSE,       /* 连接关闭 */
    MG_EV_HTTP_MSG,    /* HTTP 请求/响应解析完成 */
    MG_EV_HTTP_CHUNK,  /* HTTP 分块数据 */
    MG_EV_WS_OPEN,     /* WebSocket 握手完成 */
    MG_EV_WS_MSG,      /* WebSocket 消息到达 */
    MG_EV_WS_CTL,      /* WebSocket 控制帧 */
    MG_EV_MQTT_CMD,    /* MQTT 命令 */
    MG_EV_MQTT_MSG,    /* MQTT 消息 */
    MG_EV_MQTT_OPEN,   /* MQTT 连接建立 */
    MG_EV_SNTP_TIME,   /* SNTP 时间 */
    MG_EV_USER,        /* 用户自定义事件起点 */
};
```

---

## 5. 接口函数

### 5.1 生命周期

```c
/** 初始化事件管理器 */
void mg_mgr_init(struct mg_mgr *mgr);

/** 事件循环（每次调用处理一批事件，阻塞不超过 ms 毫秒） */
void mg_mgr_poll(struct mg_mgr *mgr, int ms);

/** 销毁事件管理器（关闭所有连接，释放所有内存） */
void mg_mgr_free(struct mg_mgr *mgr);
```

**典型用法**:
```c
struct mg_mgr mgr;

mg_mgr_init(&mgr);

/* 注册 HTTP/WS 监听 + 定时器 */
// ...

while (running)
{
    mg_mgr_poll(&mgr, 50);  /* 50ms 超时 */
}

mg_mgr_free(&mgr);
```

### 5.2 HTTP 服务器

```c
/** 创建 HTTP 监听连接 */
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
                                     mg_event_handler_t fn, void *fn_data);

/** 获取 HTTP 请求/响应消息 */
int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
struct mg_http_message *mg_http_parse(const char *buf, size_t len);
struct mg_http_message *mg_http_parse2(const char *buf, size_t len);

/** 响应辅助 */
void mg_http_reply(struct mg_connection *c, int status_code,
                   const char *headers, const char *body_fmt, ...);
void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
                       const char *root);

/** 路由匹配 */
bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);
bool mg_http_match_uri(const struct mg_http_message *hm, const char *pattern);
```

**REST API 示例**:
```c
static void fn(struct mg_connection *c, int ev, void *ev_data)
{
    if (ev == MG_EV_HTTP_MSG)
    {
        struct mg_http_message *hm = (struct mg_http_message *)ev_data;

        if (mg_http_match_uri(hm, "/api/status"))
        {
            mg_http_reply(c, 200, "Content-Type: application/json\r\n",
                          "{\"status\":\"ok\"}");
        }
    }
}

mg_http_listen(&mgr, "http://0.0.0.0:8080", fn, NULL);
```

### 5.3 WebSocket

```c
/** 升级 HTTP 连接到 WebSocket */
void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *hm,
                   const char *fmt, ...);

/** 发送 WebSocket 消息 */
size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len, int op);

/** 格式化发送 WebSocket 消息 */
size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...);

/** 封装非 WS socket 为 WS 帧（用于代理） */
size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op,
                  const void *buf, size_t buf_len);

/** 主动连接 WebSocket 服务器（客户端模式） */
struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
                                    mg_event_handler_t fn, void *fn_data,
                                    const char *fmt, ...);
```

**WebSocket 帧操作码 (op)**:
```c
#define WEBSOCKET_OP_CONTINUE  0   /* 继续帧 */
#define WEBSOCKET_OP_TEXT      1   /* 文本消息 */
#define WEBSOCKET_OP_BINARY    2   /* 二进制消息 */
#define WEBSOCKET_OP_CLOSE     8   /* 关闭握手 */
#define WEBSOCKET_OP_PING      9   /* Ping */
#define WEBSOCKET_OP_PONG      10  /* Pong */
```

**WebSocket 服务端示例**:
```c
static void fn(struct mg_connection *c, int ev, void *ev_data)
{
    if (ev == MG_EV_HTTP_MSG)
    {
        struct mg_http_message *hm = (struct mg_http_message *)ev_data;

        if (mg_match(hm->uri, mg_str("/ws"), NULL))
        {
            mg_ws_upgrade(c, hm, NULL);
        }
    }
    else if (ev == MG_EV_WS_MSG)
    {
        struct mg_ws_message *wm = (struct mg_ws_message *)ev_data;

        /* 回显消息 */
        mg_ws_send(c, wm->data.buf, wm->data.len, WEBSOCKET_OP_TEXT);
    }
}
```

### 5.4 定时器

```c
/** 添加一次性定时器 */
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
                              unsigned flags, void (*fn)(void *), void *arg);

/** 定时器标志 */
#define MG_TIMER_REPEAT  1    /* 周期性定时器 */
#define MG_TIMER_RUN_NOW 2    /* 立即运行一次 */
```

### 5.5 通用收发

```c
/** 发送原始数据 */
bool mg_send(struct mg_connection *c, const void *buf, size_t len);

/** 格式化发送 */
size_t mg_printf(struct mg_connection *c, const char *fmt, ...);
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap);

/** 关闭连接 */
void mg_close_conn(struct mg_connection *c);
```

---

## 6. 使用约束与注意事项

### 6.1 线程安全
- `mg_mgr_poll()` 必须在**单线程**中调用
- 如需要多线程，通过 `mg_wakeup()` 向事件循环投递消息

### 6.2 内存管理
- 所有通过 `mg_http_listen()` 创建的连接在 `mg_mgr_free()` 时自动关闭释放
- `mg_http_message` 中的 `hm->body`、`hm->query` 等字段为协议栈内部缓冲区，**不可手动 free**

### 6.3 与 RTU 的集成方式
- `libweb_server` 作为 RTU 的独立线程模块，在线程内创建自己的 `mg_mgr`
- 通过 X-Macro 框架的定时器触发 `mg_mgr_poll()`
- HTTP 路由中使用 `dc_get_signal_val()` 获取实时数据，`dc_set_out_signal_val()` 发布前端写入的数据

### 6.4 日志说明
mongoose 内部使用 `printf` 向 stderr 输出日志（`MG_ENABLE_LOG=1`）。在 RTU 装置上 stderr 通常重定向到 `/dev/null` 或 syslog。如需捕获 mongoose 日志，可定义 `MG_ENABLE_CUSTOM_LOG=1` 并提供自定义 `MG_LOG()` 宏。

---

## 7. 依赖关系

### 7.1 本模块依赖
- **无**（mongoose 是纯 C、零依赖的单文件库，直接使用 Linux socket API）

### 7.2 依赖本模块的模块

| 模块 | 用途 |
|------|------|
| `libweb_server` (system/) | HTTP REST API + WebSocket 通信 |

### 7.3 模块依赖图

```
┌──────────────────┐
│ libweb_server    │ (RTU 线程模块)
│ REST API + WS    │
└────────┬─────────┘
         │ myMongoose.h
         ▼
┌──────────────────┐
│ libmongoose      │ (纯 C 协议栈)
│ HTTP + WebSocket │
└────────┬─────────┘
         │
         ▼
    Linux Socket API + epoll
```

---

## 8. 编译与构建

```bash
# 编译 libmongoose.a
cd release/src/protocol/libmongoose
make -f makefile all            # x86
make -f makefile CROSS=arm all  # ARM

# 参与全量构建
cd release && ./build.sh        # x86
cd release && ./build.sh arm    # ARM
```

---

## 9. 许可证

Mongoose 使用 **MIT 许可证**（商业友好）。完整许可文本见 `mongoose.h` 头部注释。

---

## 10. 参考链接

- [Mongoose 官方文档](https://mongoose.ws/documentation/)
- [Mongoose GitHub](https://github.com/cesanta/mongoose)
- [WebSocket RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455)
- [HTTP/1.1 RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230)
