# libpeer（WebRTC）说明

## 简介

libpeer 是一个专为嵌入式系统设计的轻量级 WebRTC 对等连接库，使用 C 语言实现。它支持 ICE 连接建立、DTLS-SRTP 安全媒体传输、SCTP 数据通道等 WebRTC 核心协议，配合 K230 RT-Smart SDK 中的 MPP 媒体处理能力，可构建端到端的实时音视频通信应用。

## 架构概览

libpeer 实现 WebRTC 对等连接的核心协议栈：

```text
┌───────────────────────────────────────┐
│          PeerConnection API            │
├───────────────────────────────────────┤
│  peer_signaling │  peer_connection    │
│  (MQTT/HTTP)    │  (ICE/DTLS/SCTP)   │
├───────────────────────────────────────┤
│  STUN │ ICE │ DTLS-SRTP │ SCTP │ RTP │
├───────────────────────────────────────┤
│  mbedtls │ libsrtp │ usrsctp │ cJSON │
├───────────────────────────────────────┤
│  coreMQTT │ coreHTTP                  │
└───────────────────────────────────────┘
```

### 核心模块

| 模块 | 功能 |
| :-- | :-- |
| `peer_connection` | PeerConnection 生命周期管理，SDP 生成/解析，ICE 候选处理 |
| `peer_signaling` | 信令通道：通过 MQTT 或 HTTP 交换 SDP 和 ICE 候选 |
| `ice` | ICE 连接建立（STUN 绑定请求、连通性检查） |
| `stun` | STUN 协议编码/解码 |
| `dtls_srtp` | 基于 DTLS 的 SRTP 密钥协商（DTLS-SRTP） |
| `sctp` | 基于用户态 SCTP 的数据通道 |
| `rtp` / `rtcp` | RTP 打包/拆包与 RTCP 收发统计 |
| `sdp` | SDP 会话描述生成与解析 |
| `mdns` | mDNS 本地地址发现 |

## 功能说明

### PeerConnection API

libpeer 提供 `PeerConnection` 对象，封装 WebRTC 对等连接的核心操作：

```c
#include "peer_connection.h"

// 创建 PeerConnection
PeerConnection *pc = peer_connection_create(&config);

// 创建 SDP Offer
peer_connection_create_offer(pc);

// 获取本地 SDP
char *local_sdp = peer_connection_get_local_description(pc);

// 设置远端 SDP
peer_connection_set_remote_description(pc, remote_sdp);

// 添加 ICE 候选
peer_connection_add_ice_candidate(pc, sdp, mid, mline_index);

// 发送数据通道消息
peer_connection_datachannel_send(pc, message, length, type);

// 发送音频 RTP
peer_connection_send_audio(pc, buf, size, timestamp_ms);

// 发送视频 RTP
peer_connection_send_video(pc, buf, size, timestamp_ms);

// 销毁 PeerConnection
peer_connection_destroy(pc);
```

### 回调机制

通过配置回调函数处理异步事件：

| 回调 | 说明 |
| :-- | :-- |
| `onicecandidate` | 生成本地 ICE 候选时触发，返回 SDP 字符串 |
| `oniceconnectionstatechange` | ICE 连接状态变化（NEW → CHECKING → CONNECTED → …） |
| `on_connected` | 对等连接建立完成（DTLS 握手成功） |
| `on_receiver_packet_loss` | 接收端丢包统计回调（丢包率、总丢包数） |

### Peer Signaling（信令）

libpeer 内置信令通道，通过 `peer_signaling.h` 提供以下能力：

```c
// 连接信令服务器（MQTT 或 HTTP 模式）
peer_signaling_connect(url, token, pc);

// 信令事件循环（需周期性调用）
peer_signaling_loop();

// 注册自定义 RPC 方法处理器
peer_signaling_set_custom_rpc_handler(cb, userdata);

// 复用信令 MQTT 连接发布消息
peer_signaling_publish(topic, message);

// 断开信令连接
peer_signaling_disconnect();
```

### PeerConnection 状态机

```text
CLOSED → NEW → CHECKING → CONNECTED → COMPLETED
                  ↓
              FAILED / DISCONNECTED
```

### 支持的媒体编码

| 类型 | 编码 | 状态 |
| :-- | :-- | :-- |
| 视频 | H.264 | 已支持 |
| 视频 | VP8 | 未实现 |
| 视频 | MJPEG | 未实现 |
| 音频 | OPUS | 未实现 |
| 音频 | PCMA | 已支持 |

## 最小使用示例

以下展示一个最小可运行的 PeerConnection 创建与信令连接流程：

```c
#include "peer.h"
#include "peer_connection.h"
#include "peer_signaling.h"

// 1. ICE 候选回调 —— 将本地 SDP 发送给远端
static void on_ice_candidate(char *sdp, void *user_data) {
    printf("Local SDP:\n%s\n", sdp);
    // 实际应用中通过信令通道将 SDP 发送给对端
}

// 2. ICE 连接状态回调
static void on_ice_state_change(PeerConnectionState state, void *user_data) {
    const char *names[] = {
        "CLOSED", "NEW", "CHECKING", "CONNECTED",
        "COMPLETED", "FAILED", "DISCONNECTED"
    };
    printf("ICE state: %s\n", names[state]);
}

// 3. 连接建立回调
static void on_connected(void *userdata) {
    printf("PeerConnection established!\n");
    // DTLS 握手完成，可以开始发送媒体或数据通道消息
}

int main(int argc, char **argv) {
    // 初始化 libpeer
    peer_init();

    // 配置 PeerConnection
    PeerConfiguration config = {0};
    config.onicecandidate = on_ice_candidate;
    config.oniceconnectionstatechange = on_ice_state_change;
    config.on_connected = on_connected;
    config.video_codec = CODEC_H264;   // 视频编码
    config.audio_codec = CODEC_NONE;   // 暂不使用音频
    config.datachannel = 1;            // 启用数据通道

    // 创建 PeerConnection
    PeerConnection *pc = peer_connection_create(&config);
    if (!pc) {
        printf("Failed to create PeerConnection\n");
        return -1;
    }

    // 创建 Offer
    peer_connection_create_offer(pc);

    // 连接信令服务器 (MQTT 模式示例)
    peer_signaling_connect("mqtt://signaling-server:1883", "your-token", pc);

    // 主循环
    while (1) {
        peer_signaling_loop();  // 驱动信令消息收发
        usleep(5000);
    }

    // 清理
    peer_signaling_disconnect();
    peer_connection_destroy(pc);
    peer_deinit();
    return 0;
}
```

```{admonition} 提示
以上为最小框架示例，实际使用中需要替换信令服务器地址与 token，并补充 SDP 交换逻辑。建议同时阅读以下源码文件了解完整流程：
- `src/rtsmart/libs/3rd-party/libpeer/src/peer_connection.h` —— 完整 PeerConfiguration 字段说明
- `src/rtsmart/libs/3rd-party/libpeer/src/peer_signaling.h` —— 信令接口与自定义 RPC 回调
- `src/rtsmart/libs/3rd-party/libpeer/src/peer.h` —— peer_init/peer_deinit 生命周期
```

## 代码位置

- 库源码：`src/rtsmart/libs/3rd-party/libpeer/src/`
- 第三方依赖（内嵌）：`src/rtsmart/libs/3rd-party/libpeer/3rd-party/`
  - `mbedtls` — TLS/DTLS 加密
  - `libsrtp` — SRTP 媒体加密
  - `usrsctp` — 用户态 SCTP 协议栈
  - `coreHTTP` — HTTP 信令通道
  - `coreMQTT` — MQTT 信令通道

当前 libpeer 暂未提供独立示例程序。

## 编译方法

### 固件编译

在 `K230 RTOS SDK` 根目录下使用 `make menuconfig` 配置编译选项：

1. 进入 `RT-Smart 3rd-party Configuration` → 使能 `Enable Build libpeer (WebRTC)`
2. 该选项会自动选中 `Enable Build cJSON`（cJSON 为 libpeer 的 JSON 解析依赖）

然后编译固件。

## 配置说明

| Kconfig 选项 | 说明 |
| :-- | :-- |
| `RTSMART_3RD_PARTY_ENABLE_LIBPEER` | 编译 libpeer 库 (`libpeer.a`) |

`RTSMART_3RD_PARTY_ENABLE_LIBPEER` 会自动选中 `RTSMART_3RD_PARTY_ENABLE_CJSON`。

## 依赖关系

### SDK 内依赖

| 依赖库 | Kconfig 选项 | 说明 |
| :-- | :-- | :-- |
| cJSON | `RTSMART_3RD_PARTY_ENABLE_CJSON` | JSON 解析（信令协议使用） |
| MbedTLS | `RTSMART_3RD_PARTY_ENABLE_MBEDTLS` | DTLS 加密（内嵌于 3rd-party） |

### 内嵌依赖

libpeer 在 `3rd-party/` 子目录中内嵌了以下组件，不需要单独使能 SDK 中对应的库：

| 组件 | 用途 |
| :-- | :-- |
| mbedtls | TLS/DTLS 握手与加密 |
| libsrtp | SRTP 媒体流加密 |
| usrsctp | 用户态 SCTP 数据通道 |
| coreHTTP | HTTP 信令通道客户端 |
| coreMQTT | MQTT 信令通道客户端 |

```{admonition} 注意
libpeer 内嵌的 mbedtls 与 SDK 中独立的 `libs/3rd-party/mbedtls` 各有一套，互不影响。内嵌版本为 private 使用，不会导出符号或头文件。
```

## 使用建议

libpeer 面向的是有 WebRTC 概念基础的开发者，建议按照以下顺序了解：

1. 阅读 [WebRTC 官方规范](https://webrtc.org/) 了解 ICE、SDP、DTLS-SRTP 等核心概念
2. 阅读 `src/rtsmart/libs/3rd-party/libpeer/src/peer_connection.h` 了解头文件 API
3. 阅读 `src/rtsmart/libs/3rd-party/libpeer/src/peer_signaling.h` 了解信令接口
4. 参考 MPP 媒体处理相关示例，了解如何获取 H.264 编码的 RTP 载荷
5. 配合信令服务器（支持 MQTT 或 HTTP 协议）进行联调

```{admonition} 提示
libpeer 的 `peer_signaling` 模块支持通过 MQTT 复用连接发布自定义消息，可在不额外创建 MQTT 客户端的情况下实现心跳上报或设备状态同步。
```
