Files
STM32F4-Base/docs/NET_Socket_FTP_Support_Plan.md

81 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NET Socket FTP 支持改造方案
## 背景
在 net_socket API 上移植 FTP Serverlftpd需要支持 PASV 模式数据通道。现有 API 仅支持"一个监听 Socket 独占全部数据 Socket"的单 TCP Server 模型,改造后需支持**多监听者 + 动态 Socket 分配**。
## Socket 需求量
| 用途 | Socket | 说明 |
|------|--------|------|
| 控制通道监听(端口 21 | Socket 0 | 多连接 TCP Server |
| 控制通道数据 | Socket 1 | backlog=1只接受 1 个 FTP 客户端 |
| PASV 数据监听 + 传输 | Socket 2 | 动态分配,用后释放 |
| 空闲 | Socket 3~7 | 备胎 |
## 改造项7 项)
### A. `net_sock_t` 新增 `standalone_accept` 标志
- 位置:`net_types.h:net_sock_t`
- 用途:区分多连接数据 Socket 和独立监听者(如 PASV
- 设 1PASV 监听者 `handle_connect_event` → 原地转为 `ESTABLISHED`
- 设 1`handle_disconnect_event` → 释放(`CLOSED`),不恢复 `TCP_ACCEPT`
### B. `net_listen()` 按 backlog 分配 + 登记 data_socks[]
- 循环从 `NET_TCP_SERVER_DATA_SOCK_START``backlog`
- 分配的数据 Socket 登记到 `p_sock->data_socks[]`,设 `data_sock_count`
- `backlog == 0` 时:不分配数据 Socket`standalone_accept=1`
### C. `net_bind()` 支持 port=0 自动分配
- `sin_port == 0` 时从 49152~65535 分配
- 静态变量 `s_dynamic_port` 递增
### D. `handle_connect_event()` 支持独立监听
- `LISTENING + standalone_accept`:拷贝远程 IP/Port状态转 `ESTABLISHED`
- `LISTENING + !standalone_accept`:保持 LISTENING现有行为
### E. `handle_disconnect_event()` 支持独立释放
- `ESTABLISHED + standalone_accept`:设 `state = CLOSED, in_use = 0`(释放)
- `ESTABLISHED + !standalone_accept`:恢复 `TCP_ACCEPT`(现有行为)
- 释放时不清零整个控制块(正在 `net_recv` 中的任务仍需读取 state
### F. `net_accept()` 支持单连接 + 修复多连接
- 先查 `data_socks[]`(修复现行 bug
- 再查 `standalone_accept` 监听者是否 `ESTABLISHED` → 返回自身
### G. 新增 `net_getsockname()`
- 返回 `local_port` + 本机 IP
- 本机 IP 在 `net_init()` 时缓存(`s_local_ip`),避免 SPI 竞态
## 消息队列序列化
### 问题
`net_listen()``net_accept()` 直接调用 CH395F SPI从非 netTask如 FTP 任务)调用会与 `net_poll()` 冲突。
### 方案
新增消息类型通过现有消息队列串行化:
| 消息类型 | 用途 | 状态 |
|---------|------|------|
| `NET_MSG_LISTEN` | `net_listen()` 委托 netTask 执行 | 本次实现 |
| `NET_MSG_ACCEPT` | `net_accept()` 委托 netTask 执行 | 本次实现 |
`net_bind()` 暂不消息化TCP 部分不碰 SPIUDP 暂无需跨任务调用)。
## 向后兼容
- 控制通道 `net_listen(sockfd=0, backlog=7)` 行为不变(仍配满 Socket 1~7
- `backlog < 7` 时才释放多余 Socket
- `NET_MSG_LISTEN`/`NET_MSG_ACCEPT` 仅新增,不影响现有 `NET_MSG_SEND/RECV/CLOSE/CONNECT`
- `net_sock_t` 新增字段 `standalone_accept` 默认 0不影响现有使用
## 实施顺序
1. 消息队列加 `NET_MSG_LISTEN``NET_MSG_ACCEPT`
2. `net_listen()` 消息化 + 按 backlog 分配 + data_socks 登记
3. `net_accept()` 消息化 + 单连接支持
4. `net_bind()` port=0 支持
5. `net_types.h` standalone_accept 字段
6. `handle_connect_event()` / `handle_disconnect_event()` 独立监听逻辑
7. `net_getsockname()`