Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 56 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@

```
sip-stack-parent
├── sip-message 不可变消息模型(sealed + record) [零依赖]
├── sip-codec wire-format 解析/编码 + typed headers [+sip-message]
├── sip-transport-api 传输 SPI 纯接口 [+sip-message]
├── sip-transport-nio JDK 21 NIO + 虚拟线程默认实现(UDP + TCP) [+codec, +slf4j]
├── sip-transaction RFC 3261 §17 四个事务 FSM + 时间轮 [+transport-api]
├── sip-dialog RFC 3261 §12 对话层(Route Set / Target Refresh)[+transaction]
├── sip-ua 高级 UA API(REGISTER / OPTIONS / Digest 鉴权) [+dialog]
├── sip-gb28181 GB/T 28181-2016 应用层(MANSCDP XML) [+ua]
└── sip-compliance-tests RFC 4475 / RFC 5118 合规测试 [test-only]
├── sip-message 不可变消息模型(sealed + record) [零依赖]
├── sip-codec wire-format 解析/编码 + typed headers + URI parser [+sip-message]
├── sip-transport-api 传输 SPI 纯接口 [+sip-message]
├── sip-transport-nio JDK 21 NIO 默认实现(UDP / TCP / TLS / WebSocket) [+codec, +slf4j]
├── sip-transaction RFC 3261 §17 四个事务 FSM + 时间轮 [+transport-api]
├── sip-dialog RFC 3261 §12 对话层(Route Set / Target Refresh) [+transaction]
├── sip-ua 高级 UA API(REGISTER / OPTIONS / Digest 鉴权) [+dialog]
├── sip-gb28181 GB/T 28181-2016 应用层(MANSCDP XML) [+ua]
├── sip-spring-boot-starter 可选 Spring Boot 3 自动配置层 [+ua, +spring]
├── sip-compliance-tests RFC 4475 / RFC 5118 合规测试(默认 verify) [test-only]
└── sip-interop-tests Testcontainers + Kamailio 互操作测试('interop' profile)[test-only]
```

## 关键决策
Expand All @@ -52,6 +54,28 @@ sip-stack-parent

## 快速上手

### 0. Spring Boot 自动配置(推荐)

```xml
<dependency>
<groupId>com.sip</groupId>
<artifactId>sip-spring-boot-starter</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
```

```yaml
# application.yml
sip:
transport:
udp:
enabled: true
host: 0.0.0.0
port: 5060
```

容器即可注入 `Transport` / `TimerScheduler` / `RegistrationClient` / `OptionsProbe`。

### 1. 解析 / 编码

```java
Expand Down Expand Up @@ -112,24 +136,41 @@ transport.send(message, platformEndpoint);

- [x] **Phase 0** — 骨架 + ADR-0001
- [x] **Phase 1** — typed headers(Via / NameAddr / CSeq / Contact / Route / 简单整数头 / Call-ID)
- [x] **Phase 2** — 解析器 + 编码器(含 SipUriParser)+ RFC 4475 闸门
- [x] **Phase 2** — 解析器 + 编码器(含 SipUriParser)+ RFC 4475 闸门(12 个 fixture)
- [x] **Phase 3** — `sip-transport-nio`(UDP + TCP)
- [x] **Phase 4** — 事务层四个 FSM + 时间轮(ADR-0002)
- [x] **Phase 5** — Dialog + REGISTER + OPTIONS + Digest 鉴权(RFC 7616)
- [x] **Phase 7** — GB28181 应用层(MANSCDP XML)
- [ ] **Phase 8** — TLS / WebSocket 传输
- [ ] **Phase 9** — 互操作测试(Kamailio / Asterisk + SIPp)
- [ ] **Phase 10** — Spring Boot starter(可选)
- [x] **Phase 8** — TLS(RFC 5922)+ WebSocket(RFC 7118)传输
- [x] **Phase 9** — Testcontainers + Kamailio 互操作测试骨架(`-Pinterop` 触发)
- [x] **Phase 10** — Spring Boot 3 starter

## 测试

```
```bash
# 默认:11 modules,~225 个测试(不包含 interop)
mvn -B verify

# 启用互操作测试(需要 Docker)
mvn -B verify -Pinterop
```

要求:**JDK 21+**、Maven 3.8+。

当前规模:**10 modules、169 个测试**(含 34 个合规动态测试)。
| Module | tests |
|--------|------:|
| sip-message | 10 |
| sip-codec | 69 |
| sip-transport-api | — |
| sip-transport-nio | 12(3 UDP + 4 TCP + 2 TLS + 3 WS)|
| sip-transaction | 18 |
| sip-dialog | 5 |
| sip-ua | 12 |
| sip-gb28181 | 11 |
| sip-spring-boot-starter | 4 |
| sip-compliance-tests | 65(含 36 个动态合规闸门)|
| sip-interop-tests | 2(Docker 缺位时自动跳过)|
| **total** | **~225** |

### 合规闸门

Expand Down
35 changes: 35 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,24 @@
<module>sip-dialog</module>
<module>sip-ua</module>
<module>sip-gb28181</module>
<module>sip-spring-boot-starter</module>
<module>sip-compliance-tests</module>
</modules>

<profiles>
<!--
Interoperability tests against a real Kamailio container.
Off by default because they require Docker. Enable with:
mvn verify -Pinterop
-->
<profile>
<id>interop</id>
<modules>
<module>sip-interop-tests</module>
</modules>
</profile>
</profiles>

<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand All @@ -46,6 +61,8 @@
<assertj.version>3.26.3</assertj.version>
<mockito.version>5.14.2</mockito.version>
<jmh.version>1.37</jmh.version>
<spring-boot.version>3.4.0</spring-boot.version>
<testcontainers.version>1.20.4</testcontainers.version>

<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
Expand Down Expand Up @@ -99,6 +116,24 @@
<version>${project.version}</version>
</dependency>

<!-- Spring Boot BOM — only consumed by the optional starter module -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- Testcontainers BOM — only consumed by sip-interop-tests -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- runtime: ONLY slf4j is allowed in protocol core -->
<dependency>
<groupId>org.slf4j</groupId>
Expand Down
38 changes: 38 additions & 0 deletions sip-interop-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# sip-interop-tests

End-to-end interoperability tests against real SIP implementations.
**Activated only via the `interop` Maven profile**, because the tests
require a working Docker daemon to spin up the peer SIP server.

```bash
# Default build — interop tests excluded:
mvn verify

# Run interop tests too:
mvn verify -Pinterop
```

## What's covered

| Test | Peer image | Validates |
|------|-----------|-----------|
| `KamailioRegisterInteropTest#registersWithDigestAuth` | `kamailio/kamailio-ci:5.7-alpine` | REGISTER + 401 + Digest re-authenticate + 200 |
| `KamailioRegisterInteropTest#optionsProbeReturns200` | `kamailio/kamailio-ci:5.7-alpine` | OPTIONS probe |

## Adding a peer

The pattern in `KamailioContainer` extends straightforwardly to other
peers (Asterisk, OpenSIPS, FreeSWITCH). Create a `<Name>Container`
subclass of `GenericContainer<T>` that:

1. Pins the image tag (no `:latest`).
2. Ships its config as a `Transferable` so test infra stays declarative.
3. Exposes a `waitingFor(...)` strategy that completes only when the
peer is actually ready to accept SIP traffic.

## CI

This module is **deliberately not part of the default `verify` reactor**.
Cloud-agent CIs without Docker degrade gracefully — `mvn verify` passes.
A dedicated CI job that *has* Docker can run `mvn verify -Pinterop` to
exercise this module.
88 changes: 88 additions & 0 deletions sip-interop-tests/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.sip</groupId>
<artifactId>sip-stack-parent</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>

<artifactId>sip-interop-tests</artifactId>
<name>SIP :: Interoperability Tests</name>
<description>
End-to-end interoperability tests against real SIP implementations
(Kamailio, Asterisk) launched in Docker via Testcontainers.
Activated only by the 'interop' Maven profile.
</description>

<dependencies>
<dependency>
<groupId>com.sip</groupId>
<artifactId>sip-message</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sip</groupId>
<artifactId>sip-codec</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sip</groupId>
<artifactId>sip-transport-nio</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sip</groupId>
<artifactId>sip-transaction</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sip</groupId>
<artifactId>sip-ua</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-Xlint:all,-serial,-processing,-module</arg>
<arg>-Werror</arg>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
Loading
Loading