Sip-Proxy

Changelog

本文档记录 sip-proxy 各版本的对外可见变更。版本号遵循 Semantic Versioning

[1.8.0] - 2026-05-29

🚨 BREAKING CHANGES — 老 gb28181-gateway 模块下线 + 1.8.0 兼容 shim 移除

本期是 1.8.0 最终版,一次性切换到新 sip-gateway 父聚合形态:

✨ Features — sip-gateway 父聚合 + envelope 协议化(doc/plans/1.8.0/

把寄居在 gb28181-test/...gateway/ 的”业务方网关”参考实现升级为正式 Maven 父聚合 sip-gateway/,业务方通过 sip-gateway-spring-boot-starter 一键接入。新增 gateway-core 协议中立内核 + gateway-gb28181 协议适配器,未来加协议(ONVIF/GT1078)只需新建子模块、starter AutoConfiguration.imports 加一行、gateway-core 与本期文档零改动。

新增模块拓扑:

sip-proxy/sip-gateway/                                ← 父聚合(packaging=pom)
├── gateway-core/                                     ← 协议中立内核
├── gateway-gb28181/                                  ← GB28181 协议适配器
├── sip-gateway-bom/                                  ← 依赖管理 BOM
└── sip-gateway-spring-boot-starter/                  ← 一键接入 Starter

核心抽象(gateway-core):

GB28181 适配器(gateway-gb28181):

type 命名规则(三段式):

type ::= <protocol>.<Group>.<Name>

protocol ∈ { gb28181 | onvif | gt1078 | rtsp | ... }    与 ProtocolModule#protocol() 一致
Group    ∈ { Query | Subscribe | Control | Config | Invite | Device | Lifecycle | Notify | Response | Session }
Name     := 与 GBT-2022 cmdType 严格一致

示例:gb28181.Query.Cataloggb28181.Control.Ptzgb28181.Invite.Playgb28181.Lifecycle.Onlinegb28181.Notify.Alarmgb28181.Session.ServerInvitegb28181.Response.Catalog

配置 namespace 分层:

gateway:
  node-id: node-1
  nodes:                          # 多节点部署用,跨节点 INVITE 回包路由
    node-1: http://10.0.0.1:8080
  forward-timeout-ms: 3000
  gb28181:
    invite-context-ttl-ms: 30000
    invite-idempotency-window-ms: 5000

业务方接入示例:

<!-- pom.xml -->
<dependency>
    <groupId>io.github.lunasaw</groupId>
    <artifactId>sip-gateway-spring-boot-starter</artifactId>
    <version>1.8.0</version>
</dependency>
// Application.java
@SpringBootApplication
@EnableSipServer
public class MyGatewayApp {
    public static void main(String[] args) { SpringApplication.run(MyGatewayApp.class, args); }
}

// 业务方实现 BusinessNotifier 推送 envelope(异步)
@Component
public class HttpWebhookNotifier extends AbstractProtocolBusinessNotifier {
    @Override
    @Async
    protected void onProtocolEvent(String protocol, GatewayEvent event) {
        // 推到 HTTP / MQ / Webhook
    }
}
POST /gateway/command HTTP/1.1
Content-Type: application/json

{
  "type": "gb28181.Query.Catalog",
  "deviceId": "34020000001320000001",
  "payload": {},
  "requestId": "trace-abc-123"
}

🛡️ CI 守门

📦 Migration Guide(必读)

1.7.x 用户必须做的迁移:

  1. 删除 gb28181-gateway 依赖:

    - <dependency>
    -     <groupId>io.github.lunasaw</groupId>
    -     <artifactId>gb28181-gateway</artifactId>
    - </dependency>
    + <dependency>
    +     <groupId>io.github.lunasaw</groupId>
    +     <artifactId>sip-gateway-spring-boot-starter</artifactId>
    + </dependency>
    
  2. 包名 / 接口替换:

    - import io.github.lunasaw.gbproxy.gateway.api.BusinessNotifier;
    - import io.github.lunasaw.gbproxy.gateway.config.GatewayProperties;
    - import io.github.lunasaw.gbproxy.gateway.store.InMemoryInviteContextStore;
    + import io.github.lunasaw.sipgateway.core.api.BusinessNotifier;
    + import io.github.lunasaw.sipgateway.core.config.GatewayProperties;
    + import io.github.lunasaw.sipgateway.gb28181.store.InMemoryInviteContextStore;
    
  3. BusinessNotifier 接口从 3 方法改为 1 方法 envelope:

    - public class MyNotifier implements BusinessNotifier {
    -     public void deviceOnline(String deviceId, RegisterInfo info) { ... }
    -     public void inviteIncoming(String callId, ...) { ... }
    -     public void alarm(String deviceId, DeviceAlarmNotify notify) { ... }
    - }
    + public class MyNotifier extends AbstractProtocolBusinessNotifier {
    +     @Override
    +     @Async
    +     protected void onProtocolEvent(String protocol, GatewayEvent event) {
    +         switch (event.type()) {
    +             case "gb28181.Lifecycle.Online" -> ...
    +             case "gb28181.Session.ServerInvite" -> ...
    +             case "gb28181.Notify.Alarm" -> ...
    +         }
    +     }
    + }
    
  4. HTTP 调用路径全部改:/sip/*/gateway/command(envelope 化)+ /gateway/gb28181/invite/response(INVITE 回包)

  5. type 必须三段式(如 gb28181.Query.Catalog),1.8.0 起未知前缀直接 404,无 fallback。

🔧 协议层小升级(1.7.3 内含)

ServerSessionEvent.rawSdp + DeviceSessionListener.onServerInvite(rawSdp,...) 已在 1.7.x 中落地。1.8.0 的 gb28181.Session.ServerInvite envelope 直接透传 rawSdp,业务侧需要把原始 SDP 转给 ZLM/SRS 推流时取此字段,避免 GbSessionDescription 反向序列化丢字段。

🔄 仓库版本号

仓库版本从 1.7.2 整体升级到 1.8.0,模块从 14 个调整为 13 个(删除老 gb28181-gateway,新增 4 个 sip-gateway/* 子模块)。


[1.7.0] - 2026-05-25

🚨 BREAKING CHANGES — 出站 Dialog 维护(doc/plans/1.7.0/OUTBOUND-DIALOG-PLAN.md

修复出站 BYE 不携带 to-tag 导致设备返回 481 Call leg/Transaction does not exist 的协议合规问题。同源同病的 SUBSCRIBE 续订 / 退订也一并改造为 dialog-aware 路径,避免长期被掩盖的协议错误(详见方案文档 v1.2 §3.2.10–§3.2.14)。

API 变更:

新增 SUBSCRIBE 续订 / 退订 API:

✨ Features

🐛 Bug Fixes

📦 Migration Guide

Server 侧 BYE:

- commandSender.deviceBye(deviceId, callId);
+ commandSender.deviceBye(callId);

Client 侧 BYE:

- ClientCommandSender.sendByeCommand(fromDevice, toDevice);
+ ClientCommandSender.sendByeCommand(callId);

SUBSCRIBE 续订 / 退订(新增 API,业务方按需替换历史”重发新 SUBSCRIBE”逻辑):

String callId = commandSender.deviceCatalogSubscribe(deviceId, 3600, "Catalog");
// ... 业务运行 ...
commandSender.refreshSubscribe(callId, 3600);   // 续订
// ... 不再需要 ...
commandSender.unsubscribe(callId);               // 退订

业务方对 deviceBye / sendByeCommand / refreshSubscribe / unsubscribe 调用应增加 try-catch:

try {
    commandSender.deviceBye(callId);
} catch (DialogNotFoundException e) {
    // dialog 已不存在(如对端先发 BYE / INVITE 还未 200 OK / callId 错误)
    log.warn("BYE 失败:dialog 不存在", e);
}

[1.5.0] - 2026-05-24

Added — Listener 化业务接口分层(doc/architecture/LISTENER-LAYERED-DESIGN.md

业务方接入完全脱离 SIP 协议细节,统一为 listener interface 模式:

Client 端(设备侧)新增 5 个 listener 接口 + 一站式适配基类

Client 端新增 6 个 L1 协议事件

Client 端新增 ClientListenerAdapter 内部分发器

Client 端新增协议层订阅注册表

Server 端新增 4 个 listener 接口 + 一站式适配基类

Server 端新增 ServerListenerAdapter

Removed — Client 端旧业务接口与 10 个 query/config/subscribe 事件

按 v1.5.0 一刀切策略,client 端业务方旧接入方式全部删除:

删除的 4 个旧业务接口

删除的 10 个旧 client 事件

保留的 8 个 SIP method 系 client 事件(与 SIP method 强绑定,不属于 MESSAGE 体系,继续作为协议层规范 API)

Changed — Client handler 全部改为发布外层事件

15 个 *MessageClientHandler 不再持有 MessageRequestHandler 引用,改为只 parseXml + publishEvent

Server 端非破坏性扩展(保留 32 个 typed Device*Event)

由于 server 端的 32 个 typed event 在业务侧已广泛使用,且 typed 设计(每个事件携带 typed payload)比 4 个 generic 事件 + instanceof 更安全,本次 v1.5.0 的 server 端改造采用加性策略

Migration Guide(业务侧 v1.4.0 → v1.5.0)

详见 doc/architecture/LISTENER-MIGRATION-GUIDE.md

业务侧约 20-30 个类受影响(以 voglander 为基准),集中在原 MessageRequestHandler / DeviceControlRequestHandler / SubscribeRequestHandler 实现类与对应 @EventListener 散点。

[1.4.0] - 2026-05-24

Added — GB/T 28181-2022 协议扩展

doc/GBT-28181-2022-IMPLEMENTATION-PLAN.md 落地,13 个阶段全部完成:

P0 优先级(独立流程,可单独跑通)

P1 优先级(沿用现有 MessageCommandStrategy)

P2 优先级(涉及新 CmdType 路由分支)

P3 优先级(多消息会话或外部依赖)

Added — 通用基础设施

Fixed

[1.3.0] - 2026-05-24

BREAKING CHANGES

本次为协议解耦主版本升级,不保留兼容期逻辑。详见 doc/plans/1.3.0/PROTOCOL-DECOUPLING-PLAN.md

Added

Removed

Migration

变更点 迁移方式
GbSessionDescription import IDE 自动修复至 io.github.lunasaw.gb28181.common.entity.sdp
GbSipDate import IDE 自动修复至 io.github.lunasaw.gb28181.common.entity
SipUtils.parseSdp 强转处 改用 GbSdpUtils.parseGbSdp(...)(编译期签名变更强制迁移)
SipUtils.generateGB28181Code / genSsrc 改用 GbUtil.generateGB28181Code / GbUtil.genSsrc
配置 sip.gb28181.time-sync.* 改为 sip.common.time-sync.*
SubscribeHolder / SubscribeTask 仓库核对确认无调用方;如有外部业务方依赖,自行复制保留
默认 UserAgent 还原 配置 sip.common.user-agent: LunaSaw-GB28181-Proxy