Commit 30ae9e929fad80f624ab632c53081db3d2dc9aec

Authored by 648540858
2 parents d295f3c5 512b0cc8

合并主线

Showing 64 changed files with 2275 additions and 1052 deletions

Too many changes to show.

To preserve performance only 64 of 128 files are displayed.

.github/ISSUE_TEMPLATE/--bug---.md renamed to .github/ISSUE_TEMPLATE/bug.md
1 1 ---
2 2 name: "[ BUG ] "
3   -about: Create a report to help us improve
4   -title: ''
5   -labels: ''
  3 +about: 关于wvp的bug,与zlm有关的建议直接在zlm的issue中提问
  4 +title: 'BUG'
  5 +labels: 'wvp的bug'
6 6 assignees: ''
7 7  
8 8 ---
9 9  
  10 +**环境信息:**
  11 +
  12 + - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/
  13 + - 2. 部署环境 windows / ubuntu/ centos ...
  14 + - 3. 端口开放情况
  15 + - 4. 是否是公网部署
  16 + - 5. 是否使用https
  17 + - 6. 方便的话提供下使用的设备品牌或平台
  18 + - 7. 你做过哪些尝试
  19 + - 8. 代码更新时间
  20 +
10 21 **描述错误**
11 22 描述下您遇到的问题
12 23  
13 24 **如何复现**
14 25 有明确复现步骤的问题会很容易被解决
15 26  
16   -**预期行为**
17   -清晰简洁的描述您期望发生的事情
  27 +**截图**
18 28  
19   -**截图**
  29 +**抓包文件**
  30 +
  31 +**日志**
  32 +```
  33 +日志内容放这里, 文件的话请直接上传
  34 +```
20 35  
21 36  
22   -**环境信息:**
23   - - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/
24   - - 2. 部署环境 windows / ubuntu/ centos ...
25   - - 3. 端口开放情况
26   - - 4. 是否是公网部署
27   - - 5. 是否使用https
28   - - 6. 方便的话提供下使用的设备品牌或平台
29   - - 7. 你做过哪些尝试
... ...
.github/ISSUE_TEMPLATE/-------.md renamed to .github/ISSUE_TEMPLATE/new.md
1 1 ---
2 2 name: "[ 新功能 ]"
3 3 about: 新功能
4   -title: ''
  4 +title: '希望wVP实现的新功能,此功能应与你的具体业务无关'
5 5 labels: ''
6 6 assignees: ''
7 7  
8 8 ---
9 9  
  10 +**项目的详细需求**
  11 +
  12 +**这样的实现什么作用**
10 13  
... ...
.github/ISSUE_TEMPLATE/solve.md 0 → 100644
  1 +---
  2 +name: "[ 技术咨询 ] "
  3 +about: 对于使用中遇到问题
  4 +title: '技术咨询'
  5 +labels: '技术咨询'
  6 +assignees: ''
  7 +
  8 +---
  9 +
  10 +**环境信息:**
  11 +
  12 + - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/
  13 + - 2. 部署环境 windows / ubuntu/ centos ...
  14 + - 3. 端口开放情况
  15 + - 4. 是否是公网部署
  16 + - 5. 是否使用https
  17 + - 6. 方便的话提供下使用的设备品牌或平台
  18 + - 7. 你做过哪些尝试
  19 + - 8. 代码更新时间
  20 +
  21 +
  22 +**内容描述:**
  23 +
  24 +**截图**
  25 +
  26 +**抓包文件**
  27 +
  28 +**日志**
  29 +```
  30 +日志内容放这里, 文件的话请直接上传
  31 +```
... ...
README.md
... ... @@ -15,17 +15,21 @@ WEB VIDEO PLATFORM銝銝芸鈭B28181-2016蝞勗
15 15 垢憿菟鈭Kyle MediaServerUI [https://gitee.com/kkkkk5G/MediaServerUI](https://gitee.com/kkkkk5G/MediaServerUI) 餈耨.
16 16  
17 17 # 摨嚗
18   -辣仍閫
19   -像VR蝑挽憭
  18 +辣仍閫
  19 +挽憭(像VR蝑)霈曉
  20 +(onvif, rtsp, rtmp嚗霈曉)霈曉嚗
20 21 漣像蝥扯楊蝵
21   -tsp/rtmp蝑蓮像
22   -tsp/rtmp蝑瘚蓮像
  22 +楊蝵撟喳鈭
23 23  
24   -# 憿寧
25   -銝芣蔭,蝙,靘蹂輕28181縑隞斤頂蝏, 靘皞獢ZLMediaKit, 摰銝銝芸GB28181撟喳.
26 24  
27   -# 蝵脫﹝
28   -[doc.wvp-pro.cn](https://doc.wvp-pro.cn)
  25 +# ﹝
  26 +wvp雿輻﹝ [https://doc.wvp-pro.cn](https://doc.wvp-pro.cn)
  27 +ZLM雿輻﹝ [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
  28 +> wvp﹝gitee嚗霂瑕活
  29 +
  30 +# 蝷曄黎
  31 +[![蝷曄黎](doc/_media/shequ.png "shequ")](https://t.zsxq.com/0d8VAD3Dm)
  32 +> 韐寞銝箔憟賜嚗撖嫣憭抒銝予隞亦縑凝靽∪嚗之摰嗅蝢扎銝予說隞亦甈橘之摰嗡閬▽憳予銋銝隞乓
29 33  
30 34 # gitee郊隞
31 35 https://gitee.com/pan648540858/wvp-GB28181-pro.git
... ... @@ -100,23 +104,17 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
100 104 - [X] 鈭垢敶瘚/隞/隞亙鈭垢嚗蝸
101 105 - [X] 銵arar
102 106 - [X] 楊窈瘙垢氖蝵
103   -
104   -
105   -# 憸圾
106   -暻餌鈭挽憭摰寞改隞仿閬之挽憭瘚挽憭偌撟單隞仿憸
107   -1. ﹝蝵粉隞亙葬雿憸
108   -2. 揣issues嚗之
109   -3. Q蝢歹901799015嚗之敹撈嚗撣歇蝏粉鈭iki揣鈭ssues
110   -4. 雿隞亥窈雿蛹雿圾蝑晶
111   -5. 雿隞交憸挽憭隞交摰寞摰寡挽憭圾憸
112   -
113   -# 雿輻撣桀
114   -QQ蝢: 901799015, ZLM雿輻﹝[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
115   -QQ蝘縑銝銝, 蝎曉.甈Z之摰嗅蝢日悄霈.閫★撖嫣葬嚗洽餈tar漱pr
116 107  
117 108 # 悅
118 109 憿寧誨蝙摰賣IT悅嚗靽縑銝隞亥摨鈭★ 雿憿寧銋蝣蝙鈭鈭隞皞誨銝窈銵隞嚗 鈭蝙憿寧漣熒噩蛹銝璁憿寧嚗窈銵 雿輻憿寧隞嚗砲悅銝剖銵冽憿寧靘洵銝摨悅
119 110  
  111 +#
  112 +
  113 +[霂(https://t.zsxq.com/0d8VAD3Dm)銝”嚗
  114 +- [雿輻蝟餃嚗VP-PRO銋(https://t.zsxq.com/0dLguVoSp)
  115 +
  116 +窈隞嗅648540858@qq.com
  117 +
120 118 # 靚
121 119 陝雿憭(https://github.com/xia-chu) 皞獢,撟嗅撘葉蝏葬
122 120 陝雿dexter langhuihui](https://github.com/langhuihui) 撘皞末EB
... ... @@ -128,7 +126,6 @@ QQ蝘縑銝銝, 蝎曉.甈Z之摰嗅蝢日悄霈.閫★撖嫣
128 126 [ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666)
129 127 [mk1990](https://github.com/mk1990) [SaltFish001](https://github.com/SaltFish001)
130 128  
131   -ps: 葵摰鈭之雿穿洽餈之雿祈頂溶
132 129  
133 130 ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1 -f rtsp rtsp://192.168.1.3:30554/broadcast/34020000001320000101_34020000001310000001
134 131  
... ...
doc/README.md
... ... @@ -14,6 +14,10 @@
14 14 - 完全开源,且使用MIT许可协议。保留版权的情况下可以用于商业项目。
15 15 - 支持多流媒体节点负载均衡。
16 16  
  17 +# 社群
  18 +[![社群](_media/shequ.png "shequ")](https://t.zsxq.com/0d8VAD3Dm)
  19 +> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。
  20 +
17 21 # 我们实现了哪些国标功能
18 22 **作为上级平台**
19 23 - [X] 注册
... ...
doc/_content/ability/_media/img_16.png

41.5 KB | W: | H:

112 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
doc/_content/qa/bug.md
... ... @@ -2,18 +2,11 @@
2 2 # 反馈bug
3 3 代码是在不断的完善的,不断修改会修复旧的问题也有可能引入新的问题,所以遇到BUG是很正常的一件事。所以遇到问题不要烦燥,咱们就事论事就好了。
4 4 ## 如何反馈
5   -1. 更新代码,很可能你遇到问题别人已经更早的遇到了,或者是作者自己发现了,已经解决了,所以你可以更新代码再次进行测试;
6   -2. 可以在github提ISSUE,我几乎每天都会去看issue,你的问题我会尽快给予答复;
7   -3. 你可以来我的QQ群里,询问群友看看是否遇到了同样的问题;
8   -4. 你可以私聊我的QQ,如果我有时间我会给你答复,但是除非你有明确的复现步骤或者修复方案,否则你可能等不到我的答复。
9   -
10   -## 如何快速解决BUG
11   -目前解决BUG有三种方式:
12   -1. 作者验证以及修复;
13   -2. 热心开发者提来的PR;
14   -3. 使用运维手段屏蔽BUG的影响。
15   -
16   -- 对于第一种:详细的复现步骤,完整的抓包文件,有条理的错误分析都可以帮助作者复现问题,进而解决问题。解决问题往往不是最难的,复现才是。
17   -- 对于第二种:如果你是开发者,你已经发现了造成BUG的原因以及知道如何正确的修复,那么我很希望你PR,SRS的大佬经常说的,开源不是一个人的事。所以你的参与就是最大的鼓励。
18   -- 对于第三种:如果你有一个有经验的运维伙伴,那么部分问题是可以通过运维的手段暂时屏蔽的,在等待修复的这段时间了以保证项目的运行。
  5 +1. 在知识星球提问。
  6 +2. 更新代码,很可能你遇到问题别人已经更早的遇到了,或者是作者自己发现了,已经解决了,所以你可以更新代码再次进行测试;
  7 +3. 可以在github提ISSUE,我几乎每天都会去看issue,你的问题我会尽快给予答复;
  8 +> 有偿支持可以给我发邮件, 648540858@qq.com
19 9  
  10 +## 社群
  11 +[![社群](../../_media/shequ.png "shequ")](https://t.zsxq.com/0d8VAD3Dm)
  12 +> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。
20 13 \ No newline at end of file
... ...
doc/_media/shequ.png 0 → 100644

35.3 KB

src/main/java/com/genersoft/iot/vmp/common/CommonCallback.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +public interface CommonCallback<T>{
  4 + public void run(T t);
  5 +}
... ...
src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
  4 +
  5 +/**
  6 + * 记录每次发送invite消息的状态
  7 + */
  8 +public class InviteInfo {
  9 +
  10 + private String deviceId;
  11 +
  12 + private String channelId;
  13 +
  14 + private String stream;
  15 +
  16 + private SSRCInfo ssrcInfo;
  17 +
  18 + private String receiveIp;
  19 +
  20 + private Integer receivePort;
  21 +
  22 + private String streamMode;
  23 +
  24 + private InviteSessionType type;
  25 +
  26 + private InviteSessionStatus status;
  27 +
  28 + private StreamInfo streamInfo;
  29 +
  30 +
  31 + public static InviteInfo getinviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo,
  32 + String receiveIp, Integer receivePort, String streamMode,
  33 + InviteSessionType type, InviteSessionStatus status) {
  34 + InviteInfo inviteInfo = new InviteInfo();
  35 + inviteInfo.setDeviceId(deviceId);
  36 + inviteInfo.setChannelId(channelId);
  37 + inviteInfo.setStream(stream);
  38 + inviteInfo.setSsrcInfo(ssrcInfo);
  39 + inviteInfo.setReceiveIp(receiveIp);
  40 + inviteInfo.setReceivePort(receivePort);
  41 + inviteInfo.setStreamMode(streamMode);
  42 + inviteInfo.setType(type);
  43 + inviteInfo.setStatus(status);
  44 + return inviteInfo;
  45 + }
  46 +
  47 + public String getDeviceId() {
  48 + return deviceId;
  49 + }
  50 +
  51 + public void setDeviceId(String deviceId) {
  52 + this.deviceId = deviceId;
  53 + }
  54 +
  55 + public String getChannelId() {
  56 + return channelId;
  57 + }
  58 +
  59 + public void setChannelId(String channelId) {
  60 + this.channelId = channelId;
  61 + }
  62 +
  63 + public InviteSessionType getType() {
  64 + return type;
  65 + }
  66 +
  67 + public void setType(InviteSessionType type) {
  68 + this.type = type;
  69 + }
  70 +
  71 + public InviteSessionStatus getStatus() {
  72 + return status;
  73 + }
  74 +
  75 + public void setStatus(InviteSessionStatus status) {
  76 + this.status = status;
  77 + }
  78 +
  79 + public StreamInfo getStreamInfo() {
  80 + return streamInfo;
  81 + }
  82 +
  83 + public void setStreamInfo(StreamInfo streamInfo) {
  84 + this.streamInfo = streamInfo;
  85 + }
  86 +
  87 + public String getStream() {
  88 + return stream;
  89 + }
  90 +
  91 + public void setStream(String stream) {
  92 + this.stream = stream;
  93 + }
  94 +
  95 + public SSRCInfo getSsrcInfo() {
  96 + return ssrcInfo;
  97 + }
  98 +
  99 + public void setSsrcInfo(SSRCInfo ssrcInfo) {
  100 + this.ssrcInfo = ssrcInfo;
  101 + }
  102 +
  103 + public String getReceiveIp() {
  104 + return receiveIp;
  105 + }
  106 +
  107 + public void setReceiveIp(String receiveIp) {
  108 + this.receiveIp = receiveIp;
  109 + }
  110 +
  111 + public Integer getReceivePort() {
  112 + return receivePort;
  113 + }
  114 +
  115 + public void setReceivePort(Integer receivePort) {
  116 + this.receivePort = receivePort;
  117 + }
  118 +
  119 + public String getStreamMode() {
  120 + return streamMode;
  121 + }
  122 +
  123 + public void setStreamMode(String streamMode) {
  124 + this.streamMode = streamMode;
  125 + }
  126 +}
... ...
src/main/java/com/genersoft/iot/vmp/common/InviteSessionStatus.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +/**
  4 + * 标识invite消息发出后的各个状态,
  5 + * 收到ok钱停止invite发送cancel,
  6 + * 收到200ok后发送BYE停止invite
  7 + */
  8 +public enum InviteSessionStatus {
  9 + ready,
  10 + ok,
  11 +}
... ...
src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +public enum InviteSessionType {
  4 + PLAY,
  5 + PLAYBACK,
  6 + DOWNLOAD,
  7 + BROADCAST,
  8 + TALK
  9 +}
... ...
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -16,8 +16,6 @@ public class VideoManagerConstants {
16 16  
17 17 public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_";
18 18  
19   - public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";
20   -
21 19 public static final String DEVICE_PREFIX = "VMP_DEVICE_";
22 20  
23 21 // 设备同步完成
... ... @@ -28,9 +26,10 @@ public class VideoManagerConstants {
28 26 public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_";
29 27  
30 28 // TODO 此处多了一个_,暂不修改
31   - public static final String PLAYER_PREFIX = "VMP_PLAYER_";
32   - public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
33   - public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
  29 + public static final String INVITE_PREFIX = "VMP_INVITE";
  30 + public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_";
  31 + public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_";
  32 + public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_";
34 33  
35 34 public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_";
36 35  
... ... @@ -123,6 +122,7 @@ public class VideoManagerConstants {
123 122 */
124 123 public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm";
125 124  
  125 +
126 126 /**
127 127 * 报警通知的发送 (收到redis发出的通知,转发给其他平台)
128 128 */
... ...
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
... ... @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.conf;
2 2  
3 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
4 4 import com.genersoft.iot.vmp.service.IMediaServerService;
5   -import org.apache.catalina.connector.ClientAbortException;
6 5 import org.apache.http.HttpHost;
7 6 import org.apache.http.HttpRequest;
8 7 import org.apache.http.HttpResponse;
... ... @@ -194,11 +193,11 @@ public class ProxyServletConfig {
194 193 } catch (IOException ioException) {
195 194 if (ioException instanceof ConnectException) {
196 195 logger.error("录像服务 连接失败");
197   - }else if (ioException instanceof ClientAbortException) {
198   - /**
199   - * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常,
200   - * TODO 暂时去除异常处理。后续使用其他代理框架修改测试
201   - */
  196 +// }else if (ioException instanceof ClientAbortException) {
  197 +// /**
  198 +// * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常,
  199 +// * TODO 暂时去除异常处理。后续使用其他代理框架修改测试
  200 +// */
202 201  
203 202 }else {
204 203 logger.error("录像服务 代理失败: ", e);
... ...
src/main/java/com/genersoft/iot/vmp/conf/ScheduleConfig.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf;
  2 +
  3 +import org.apache.commons.lang3.concurrent.BasicThreadFactory;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.scheduling.annotation.SchedulingConfigurer;
  6 +import org.springframework.scheduling.config.ScheduledTaskRegistrar;
  7 +
  8 +import java.util.concurrent.ScheduledThreadPoolExecutor;
  9 +import java.util.concurrent.ThreadPoolExecutor;
  10 +
  11 +/**
  12 + * "@Scheduled"是Spring框架提供的一种定时任务执行机制,默认情况下它是单线程的,在同时执行多个定时任务时可能会出现阻塞和性能问题。
  13 + * 为了解决这种单线程瓶颈问题,可以将定时任务的执行机制改为支持多线程
  14 + */
  15 +@Configuration
  16 +public class ScheduleConfig implements SchedulingConfigurer {
  17 +
  18 + public static final int cpuNum = Runtime.getRuntime().availableProcessors();
  19 +
  20 + private static final int corePoolSize = cpuNum;
  21 +
  22 + private static final String threadNamePrefix = "scheduled-task-pool-%d";
  23 +
  24 + @Override
  25 + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
  26 + taskRegistrar.setScheduler(new ScheduledThreadPoolExecutor(corePoolSize,
  27 + new BasicThreadFactory.Builder().namingPattern(threadNamePrefix).daemon(true).build(),
  28 + new ThreadPoolExecutor.CallerRunsPolicy()));
  29 + }
  30 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
... ... @@ -48,10 +48,13 @@ public class SipPlatformRunner implements CommandLineRunner {
48 48 parentPlatformCatch.setParentPlatform(parentPlatform);
49 49 parentPlatformCatch.setId(parentPlatform.getServerGBId());
50 50 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
51   - // 取消订阅
52   - sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
53   - platformService.login(parentPlatform);
54   - });
  51 + if (parentPlatformCatchOld != null) {
  52 + // 取消订阅
  53 + sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
  54 + platformService.login(parentPlatform);
  55 + });
  56 + }
  57 +
55 58 // 设置所有平台离线
56 59 platformService.offline(parentPlatform, true);
57 60 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
... ... @@ -54,6 +54,9 @@ public class UserSetting {
54 54  
55 55 private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE;
56 56  
  57 + private Boolean deviceStatusNotify = Boolean.FALSE;
  58 + private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
  59 +
57 60 private String serverId = "000000";
58 61  
59 62 private String recordPath = null;
... ... @@ -66,6 +69,8 @@ public class UserSetting {
66 69  
67 70 private List<String> allowedOrigins = new ArrayList<>();
68 71  
  72 + private int maxNotifyCountQueue = 10000;
  73 +
69 74 public Boolean getSavePositionHistory() {
70 75 return savePositionHistory;
71 76 }
... ... @@ -277,4 +282,28 @@ public class UserSetting {
277 282 public void setRecordPath(String recordPath) {
278 283 this.recordPath = recordPath;
279 284 }
  285 +
  286 + public int getMaxNotifyCountQueue() {
  287 + return maxNotifyCountQueue;
  288 + }
  289 +
  290 + public void setMaxNotifyCountQueue(int maxNotifyCountQueue) {
  291 + this.maxNotifyCountQueue = maxNotifyCountQueue;
  292 + }
  293 +
  294 + public Boolean getDeviceStatusNotify() {
  295 + return deviceStatusNotify;
  296 + }
  297 +
  298 + public void setDeviceStatusNotify(Boolean deviceStatusNotify) {
  299 + this.deviceStatusNotify = deviceStatusNotify;
  300 + }
  301 +
  302 + public Boolean getUseCustomSsrcForParentInvite() {
  303 + return useCustomSsrcForParentInvite;
  304 + }
  305 +
  306 + public void setUseCustomSsrcForParentInvite(Boolean useCustomSsrcForParentInvite) {
  307 + this.useCustomSsrcForParentInvite = useCustomSsrcForParentInvite;
  308 + }
280 309 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java
1   -package com.genersoft.iot.vmp.conf.redis;
2   -
3   -
4   -import com.genersoft.iot.vmp.common.VideoManagerConstants;
5   -import com.genersoft.iot.vmp.service.redisMsg.*;
6   -import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
7   -import org.springframework.beans.factory.annotation.Autowired;
8   -import org.springframework.cache.annotation.CachingConfigurerSupport;
9   -import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer;
10   -import org.springframework.context.annotation.Bean;
11   -import org.springframework.context.annotation.Configuration;
12   -import org.springframework.core.annotation.Order;
13   -import org.springframework.data.redis.connection.RedisConnectionFactory;
14   -import org.springframework.data.redis.core.RedisTemplate;
15   -import org.springframework.data.redis.serializer.StringRedisSerializer;
16   -
17   -
18   -/**
19   - * Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
20   - * swwheihei
21   - * 2019年5月30日 上午10:58:25
22   - *
23   - */
24   -@Configuration
25   -@Order(value=1)
26   -public class RedisConfig {
27   -
28   -
29   - @Bean
30   - public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
31   -
32   - RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
33   - // 使用fastJson序列化
34   - GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
35   - // value值的序列化采用fastJsonRedisSerializer
36   - redisTemplate.setValueSerializer(fastJsonRedisSerializer);
37   - redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
38   -
39   - // key的序列化采用StringRedisSerializer
40   - redisTemplate.setKeySerializer(new StringRedisSerializer());
41   - redisTemplate.setHashKeySerializer(new StringRedisSerializer());
42   - redisTemplate.setConnectionFactory(redisConnectionFactory);
43   - return redisTemplate;
44   - }
45   -}
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.redis;
  2 +
  3 +import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.context.annotation.Configuration;
  6 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  7 +import org.springframework.data.redis.core.RedisTemplate;
  8 +import org.springframework.data.redis.serializer.StringRedisSerializer;
  9 +
  10 +@Configuration
  11 +public class RedisTemplateConfig {
  12 +
  13 + @Bean
  14 + public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  15 + RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
  16 + // 使用fastJson序列化
  17 + GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
  18 + // value值的序列化采用fastJsonRedisSerializer
  19 + redisTemplate.setValueSerializer(fastJsonRedisSerializer);
  20 + redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
  21 +
  22 + // key的序列化采用StringRedisSerializer
  23 + redisTemplate.setKeySerializer(new StringRedisSerializer());
  24 + redisTemplate.setHashKeySerializer(new StringRedisSerializer());
  25 + redisTemplate.setConnectionFactory(redisConnectionFactory);
  26 + return redisTemplate;
  27 + }
  28 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java
... ... @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.conf.security;
2 2  
3 3 import com.genersoft.iot.vmp.conf.UserSetting;
4 4 import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
  5 +import com.genersoft.iot.vmp.storager.dao.dto.Role;
  6 +import com.genersoft.iot.vmp.storager.dao.dto.User;
5 7 import org.apache.commons.lang3.StringUtils;
6 8 import org.springframework.beans.factory.annotation.Autowired;
7 9 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
... ... @@ -38,7 +40,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
38 40 return;
39 41 }
40 42 if (!userSetting.isInterfaceAuthentication()) {
41   - // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
42 43 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
43 44 SecurityContextHolder.getContext().setAuthentication(token);
44 45 chain.doFilter(request, response);
... ... @@ -76,7 +77,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
76 77 }
77 78  
78 79 // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
79   - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword(), new ArrayList<>() );
  80 + User user = new User();
  81 + user.setUsername(jwtUser.getUserName());
  82 + user.setPassword(jwtUser.getPassword());
  83 + Role role = new Role();
  84 + role.setId(jwtUser.getRoleId());
  85 + user.setRole(role);
  86 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, jwtUser.getPassword(), new ArrayList<>() );
80 87 SecurityContextHolder.getContext().setAuthentication(token);
81 88 chain.doFilter(request, response);
82 89 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java
... ... @@ -37,7 +37,7 @@ public class JwtUtils {
37 37 */
38 38 public static final long expirationTime = 30;
39 39  
40   - public static String createToken(String username, String password) {
  40 + public static String createToken(String username, String password, Integer roleId) {
41 41 try {
42 42 /**
43 43 * “iss” (issuer) 发行人
... ... @@ -64,6 +64,7 @@ public class JwtUtils {
64 64 //添加自定义参数,必须是字符串类型
65 65 claims.setClaim("username", username);
66 66 claims.setClaim("password", password);
  67 + claims.setClaim("roleId", roleId);
67 68  
68 69 //jws
69 70 JsonWebSignature jws = new JsonWebSignature();
... ... @@ -118,8 +119,10 @@ public class JwtUtils {
118 119  
119 120 String username = (String) claims.getClaimValue("username");
120 121 String password = (String) claims.getClaimValue("password");
  122 + Long roleId = (Long) claims.getClaimValue("roleId");
121 123 jwtUser.setUserName(username);
122 124 jwtUser.setPassword(password);
  125 + jwtUser.setRoleId(roleId.intValue());
123 126  
124 127 return jwtUser;
125 128 } catch (InvalidJwtException e) {
... ...
src/main/java/com/genersoft/iot/vmp/conf/security/LoginFailureHandler.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.conf.security;
2   -
3   -import com.fasterxml.jackson.databind.ObjectMapper;
4   -import org.slf4j.Logger;
5   -import org.slf4j.LoggerFactory;
6   -import org.springframework.beans.factory.annotation.Autowired;
7   -import org.springframework.security.authentication.*;
8   -import org.springframework.security.core.AuthenticationException;
9   -import org.springframework.security.web.authentication.AuthenticationFailureHandler;
10   -import org.springframework.stereotype.Component;
11   -
12   -import javax.servlet.ServletException;
13   -import javax.servlet.http.HttpServletRequest;
14   -import javax.servlet.http.HttpServletResponse;
15   -import java.io.IOException;
16   -import java.util.HashMap;
17   -import java.util.Map;
18   -
19   -@Component
20   -public class LoginFailureHandler implements AuthenticationFailureHandler {
21   -
22   - private final static Logger logger = LoggerFactory.getLogger(LoginFailureHandler.class);
23   -
24   - @Autowired
25   - private ObjectMapper objectMapper;
26   -
27   - @Override
28   - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
29   -
30   - String username = request.getParameter("username");
31   - if (e instanceof AccountExpiredException) {
32   - // 账号过期
33   - logger.info("[登录失败] - 用户[{}]账号过期", username);
34   -
35   - } else if (e instanceof BadCredentialsException) {
36   - // 密码错误
37   - logger.info("[登录失败] - 用户[{}]密码/SIP服务器ID 错误", username);
38   -
39   - } else if (e instanceof CredentialsExpiredException) {
40   - // 密码过期
41   - logger.info("[登录失败] - 用户[{}]密码过期", username);
42   -
43   - } else if (e instanceof DisabledException) {
44   - // 用户被禁用
45   - logger.info("[登录失败] - 用户[{}]被禁用", username);
46   -
47   - } else if (e instanceof LockedException) {
48   - // 用户被锁定
49   - logger.info("[登录失败] - 用户[{}]被锁定", username);
50   -
51   - } else if (e instanceof InternalAuthenticationServiceException) {
52   - // 内部错误
53   - logger.error(String.format("[登录失败] - [%s]内部错误", username), e);
54   -
55   - } else {
56   - // 其他错误
57   - logger.error(String.format("[登录失败] - [%s]其他错误", username), e);
58   - }
59   - Map<String, Object> map = new HashMap<>();
60   - map.put("code","0");
61   - map.put("msg","登录失败");
62   - response.setContentType("application/json;charset=UTF-8");
63   - response.getWriter().write(objectMapper.writeValueAsString(map));
64   - }
65   -}
src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.conf.security;
2   -
3   -import org.slf4j.Logger;
4   -import org.slf4j.LoggerFactory;
5   -import org.springframework.security.core.Authentication;
6   -import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
7   -import org.springframework.stereotype.Component;
8   -
9   -import javax.servlet.ServletException;
10   -import javax.servlet.http.HttpServletRequest;
11   -import javax.servlet.http.HttpServletResponse;
12   -import java.io.IOException;
13   -
14   -/**
15   - * @author lin
16   - */
17   -@Component
18   -public class LoginSuccessHandler implements AuthenticationSuccessHandler {
19   -
20   - private final static Logger logger = LoggerFactory.getLogger(LoginSuccessHandler.class);
21   -
22   - @Override
23   - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
24   -// String username = request.getParameter("username");
25   -// httpServletResponse.setContentType("application/json;charset=UTF-8");
26   -// // 生成JWT,并放置到请求头中
27   -// String jwt = JwtUtils.createToken(authentication.getName(), );
28   -// httpServletResponse.setHeader(JwtUtils.getHeader(), jwt);
29   -// ServletOutputStream outputStream = httpServletResponse.getOutputStream();
30   -// outputStream.write(JSON.toJSONString(ErrorCode.SUCCESS).getBytes(StandardCharsets.UTF_8));
31   -// outputStream.flush();
32   -// outputStream.close();
33   -
34   -// logger.info("[登录成功] - [{}]", username);
35   - }
36   -}
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
... ... @@ -53,14 +53,10 @@ public class SecurityUtils {
53 53 Authentication authentication = getAuthentication();
54 54 if(authentication!=null){
55 55 Object principal = authentication.getPrincipal();
56   - if(principal!=null && !"anonymousUser".equals(principal)){
57   -// LoginUser user = (LoginUser) authentication.getPrincipal();
  56 + if(principal!=null && !"anonymousUser".equals(principal.toString())){
58 57  
59   - String username = (String) principal;
60   - User user = new User();
61   - user.setUsername(username);
62   - LoginUser loginUser = new LoginUser(user, LocalDateTime.now());
63   - return loginUser;
  58 + User user = (User) principal;
  59 + return new LoginUser(user, LocalDateTime.now());
64 60 }
65 61 }
66 62 return null;
... ...
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
... ... @@ -47,16 +47,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
47 47 * 登出成功的处理
48 48 */
49 49 @Autowired
50   - private LoginFailureHandler loginFailureHandler;
51   - /**
52   - * 登录成功的处理
53   - */
54   - @Autowired
55   - private LoginSuccessHandler loginSuccessHandler;
56   - /**
57   - * 登出成功的处理
58   - */
59   - @Autowired
60 50 private LogoutHandler logoutHandler;
61 51 /**
62 52 * 未登录的处理
... ...
src/main/java/com/genersoft/iot/vmp/conf/security/dto/JwtUser.java
... ... @@ -25,6 +25,8 @@ public class JwtUser {
25 25  
26 26 private String password;
27 27  
  28 + private int roleId;
  29 +
28 30 private TokenStatus status;
29 31  
30 32 public String getUserName() {
... ... @@ -50,4 +52,12 @@ public class JwtUser {
50 52 public void setPassword(String password) {
51 53 this.password = password;
52 54 }
  55 +
  56 + public int getRoleId() {
  57 + return roleId;
  58 + }
  59 +
  60 + public void setRoleId(int roleId) {
  61 + this.roleId = roleId;
  62 + }
53 63 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
... ... @@ -36,8 +36,6 @@ public class SipLayer implements CommandLineRunner {
36 36 private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
37 37 private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
38 38  
39   - private SipFactory sipFactory;
40   -
41 39 @Override
42 40 public void run(String... args) {
43 41 List<String> monitorIps = new ArrayList<>();
... ... @@ -50,8 +48,7 @@ public class SipLayer implements CommandLineRunner {
50 48 monitorIps.add(sipConfig.getIp());
51 49 }
52 50  
53   - sipFactory = SipFactory.getInstance();
54   - sipFactory.setPathName("gov.nist");
  51 + SipFactory.getInstance().setPathName("gov.nist");
55 52 if (monitorIps.size() > 0) {
56 53 for (String monitorIp : monitorIps) {
57 54 addListeningPoint(monitorIp, sipConfig.getPort());
... ... @@ -65,7 +62,7 @@ public class SipLayer implements CommandLineRunner {
65 62 private void addListeningPoint(String monitorIp, int port){
66 63 SipStackImpl sipStack;
67 64 try {
68   - sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog()));
  65 + sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog()));
69 66 } catch (PeerUnavailableException e) {
70 67 logger.error("[Sip Server] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);
71 68 return;
... ... @@ -106,10 +103,6 @@ public class SipLayer implements CommandLineRunner {
106 103 }
107 104 }
108 105  
109   - public SipFactory getSipFactory() {
110   - return sipFactory;
111   - }
112   -
113 106 public SipProviderImpl getUdpSipProvider(String ip) {
114 107 if (ObjectUtils.isEmpty(ip)) {
115 108 return null;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CmdSendFailEvent.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.bean;
2   -
3   -import javax.sip.Dialog;
4   -import java.util.EventObject;
5   -
6   -public class CmdSendFailEvent extends EventObject {
7   -
8   - private String callId;
9   -
10   - /**
11   - * Constructs a prototypical Event.
12   - *
13   - * @param dialog
14   - * @throws IllegalArgumentException if source is null.
15   - */
16   - public CmdSendFailEvent(Dialog dialog) {
17   - super(dialog);
18   - }
19   -
20   - public String getCallId() {
21   - return callId;
22   - }
23   -
24   - public void setCallId(String callId) {
25   - this.callId = callId;
26   - }
27   -}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -247,6 +247,17 @@ public class Device {
247 247 return streamMode;
248 248 }
249 249  
  250 + public Integer getStreamModeForParam() {
  251 + if (streamMode.equalsIgnoreCase("UDP")) {
  252 + return 0;
  253 + }else if (streamMode.equalsIgnoreCase("TCP-PASSIVE")) {
  254 + return 1;
  255 + }else if (streamMode.equalsIgnoreCase("TCP-ACTIVE")) {
  256 + return 2;
  257 + }
  258 + return 0;
  259 + }
  260 +
250 261 public void setStreamMode(String streamMode) {
251 262 this.streamMode = streamMode;
252 263 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java
... ... @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3 3 public enum InviteStreamType {
4 4  
5   - PLAY,PLAYBACK,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY,BROADCAST,TALK
  5 + PLAY,PLAYBACK,DOWNLOAD,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY,BROADCAST,TALK
6 6  
7 7  
8 8 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3   -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  3 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 4  
5 5 public class SsrcTransaction {
6 6  
... ... @@ -13,7 +13,7 @@ public class SsrcTransaction {
13 13  
14 14 private SipTransactionInfo sipTransactionInfo;
15 15  
16   - private VideoStreamSessionManager.SessionType type;
  16 + private InviteSessionType type;
17 17  
18 18 public String getDeviceId() {
19 19 return deviceId;
... ... @@ -63,11 +63,11 @@ public class SsrcTransaction {
63 63 this.ssrc = ssrc;
64 64 }
65 65  
66   - public VideoStreamSessionManager.SessionType getType() {
  66 + public InviteSessionType getType() {
67 67 return type;
68 68 }
69 69  
70   - public void setType(VideoStreamSessionManager.SessionType type) {
  70 + public void setType(InviteSessionType type) {
71 71 this.type = type;
72 72 }
73 73  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java
... ... @@ -27,7 +27,7 @@ public class ServerLoggerImpl implements ServerLogger {
27 27 return;
28 28 }
29 29 StringBuilder stringBuilder = new StringBuilder();
30   - stringBuilder.append(!sender? "发送:目标--->" + from:"接收:来自--->" + to)
  30 + stringBuilder.append(sender? "发送:目标--->" + from:"接收:来自--->" + to)
31 31 .append("\r\n")
32 32 .append(message);
33 33 this.stackLogger.logInfo(stringBuilder.toString());
... ... @@ -40,7 +40,7 @@ public class ServerLoggerImpl implements ServerLogger {
40 40 return;
41 41 }
42 42 StringBuilder stringBuilder = new StringBuilder();
43   - stringBuilder.append(!sender? "发送: 目标->" + from :"接收:来自->" + to)
  43 + stringBuilder.append(sender? "发送: 目标->" + from :"接收:来自->" + to)
44 44 .append("\r\n")
45 45 .append(message);
46 46 this.stackLogger.logInfo(stringBuilder.toString());
... ... @@ -52,7 +52,7 @@ public class ServerLoggerImpl implements ServerLogger {
52 52 return;
53 53 }
54 54 StringBuilder stringBuilder = new StringBuilder();
55   - stringBuilder.append(!sender? "发送: 目标->" + from :"接收:来自->" + to)
  55 + stringBuilder.append(sender? "发送: 目标->" + from :"接收:来自->" + to)
56 56 .append("\r\n")
57 57 .append(message);
58 58 this.stackLogger.logInfo(stringBuilder.toString());
... ... @@ -87,6 +87,4 @@ public class ServerLoggerImpl implements ServerLogger {
87 87 this.stackLogger = this.sipStack.getStackLogger();
88 88 }
89 89 }
90   -
91   -
92 90 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
... ... @@ -76,7 +76,11 @@ public class SipSubscribe {
76 76 // 会话已结束
77 77 dialogTerminated,
78 78 // 设备未找到
79   - deviceNotFoundEvent
  79 + deviceNotFoundEvent,
  80 + // 消息发送失败
  81 + cmdSendFailEvent,
  82 + // 消息发送失败
  83 + failedToGetPort
80 84 }
81 85  
82 86 public static class EventResult<EventObject>{
... ... @@ -86,9 +90,7 @@ public class SipSubscribe {
86 90 public String callId;
87 91 public EventObject event;
88 92  
89   - public EventResult(int statusCode, String msg) {
90   - this.statusCode = statusCode;
91   - this.msg = msg;
  93 + public EventResult() {
92 94 }
93 95  
94 96 public EventResult(EventObject event) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
1 1 package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
2 2  
3   -import com.genersoft.iot.vmp.common.VideoManagerConstants;
4   -import com.genersoft.iot.vmp.conf.SipConfig;
5 3 import com.genersoft.iot.vmp.conf.UserSetting;
6 4 import com.genersoft.iot.vmp.gb28181.bean.*;
7 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
8   -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
9 6 import com.genersoft.iot.vmp.service.IGbStreamService;
10   -import com.genersoft.iot.vmp.service.IMediaServerService;
11   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
13 8 import org.slf4j.Logger;
14 9 import org.slf4j.LoggerFactory;
... ... @@ -16,12 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired;
16 11 import org.springframework.context.ApplicationListener;
17 12 import org.springframework.stereotype.Component;
18 13 import org.springframework.util.ObjectUtils;
19   -import org.springframework.util.StringUtils;
20 14  
21 15 import javax.sip.InvalidArgumentException;
22 16 import javax.sip.SipException;
23 17 import java.text.ParseException;
24   -import java.util.*;
  18 +import java.util.ArrayList;
  19 +import java.util.HashMap;
  20 +import java.util.List;
  21 +import java.util.Map;
25 22  
26 23 /**
27 24 * catalog事件
... ... @@ -43,6 +40,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
43 40 @Autowired
44 41 private SubscribeHolder subscribeHolder;
45 42  
  43 + @Autowired
  44 + private UserSetting userSetting;
  45 +
46 46 @Override
47 47 public void onApplicationEvent(CatalogEvent event) {
48 48 SubscribeInfo subscribe = null;
... ... @@ -93,6 +93,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
93 93 }
94 94 if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
95 95 for (GbStream gbStream : event.getGbStreams()) {
  96 + if (gbStream.getStreamType().equals("push") && !userSetting.isUsePushingAsStatus()) {
  97 + continue;
  98 + }
96 99 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
97 100 deviceChannelList.add(deviceChannelByStream);
98 101 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.session;
  2 +
  3 +import com.genersoft.iot.vmp.conf.SipConfig;
  4 +import org.springframework.beans.factory.annotation.Autowired;
  5 +import org.springframework.data.redis.core.StringRedisTemplate;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.util.ArrayList;
  9 +import java.util.List;
  10 +import java.util.Set;
  11 +
  12 +/**
  13 + * ssrc使用
  14 + */
  15 +@Component
  16 +public class SSRCFactory {
  17 +
  18 + /**
  19 + * 播流最大并发个数
  20 + */
  21 + private static final Integer MAX_STREAM_COUNT = 10000;
  22 +
  23 + /**
  24 + * 播流最大并发个数
  25 + */
  26 + private static final String SSRC_INFO_KEY = "VMP_SSRC_INFO_";
  27 +
  28 + @Autowired
  29 + private StringRedisTemplate redisTemplate;
  30 +
  31 + @Autowired
  32 + private SipConfig sipConfig;
  33 +
  34 +
  35 + public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
  36 + String ssrcPrefix = sipConfig.getDomain().substring(3, 8);
  37 + String redisKey = SSRC_INFO_KEY + mediaServerId;
  38 + List<String> ssrcList = new ArrayList<>();
  39 + for (int i = 1; i < MAX_STREAM_COUNT; i++) {
  40 + String ssrc = String.format("%s%04d", ssrcPrefix, i);
  41 +
  42 + if (null == usedSet || !usedSet.contains(ssrc)) {
  43 + ssrcList.add(ssrc);
  44 +
  45 + }
  46 + }
  47 + if (redisTemplate.opsForSet().size(redisKey) != null) {
  48 + redisTemplate.delete(redisKey);
  49 + }
  50 + redisTemplate.opsForSet().add(redisKey, ssrcList.toArray(new String[0]));
  51 + }
  52 +
  53 +
  54 + /**
  55 + * 获取视频预览的SSRC值,第一位固定为0
  56 + *
  57 + * @return ssrc
  58 + */
  59 + public String getPlaySsrc(String mediaServerId) {
  60 + return "0" + getSN(mediaServerId);
  61 + }
  62 +
  63 + /**
  64 + * 获取录像回放的SSRC值,第一位固定为1
  65 + */
  66 + public String getPlayBackSsrc(String mediaServerId) {
  67 + return "1" + getSN(mediaServerId);
  68 + }
  69 +
  70 + /**
  71 + * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
  72 + *
  73 + * @param ssrc 需要重置的ssrc
  74 + */
  75 + public void releaseSsrc(String mediaServerId, String ssrc) {
  76 + if (ssrc == null) {
  77 + return;
  78 + }
  79 + String sn = ssrc.substring(1);
  80 + String redisKey = SSRC_INFO_KEY + mediaServerId;
  81 + redisTemplate.opsForSet().add(redisKey, sn);
  82 + }
  83 +
  84 + /**
  85 + * 获取后四位数SN,随机数
  86 + */
  87 + private String getSN(String mediaServerId) {
  88 + String sn = null;
  89 + String redisKey = SSRC_INFO_KEY + mediaServerId;
  90 + Long size = redisTemplate.opsForSet().size(redisKey);
  91 + if (size == null || size == 0) {
  92 + throw new RuntimeException("ssrc已经用完");
  93 + } else {
  94 + // 在集合中移除并返回一个随机成员。
  95 + sn = (String) redisTemplate.opsForSet().pop(redisKey);
  96 + redisTemplate.opsForSet().remove(redisKey, sn);
  97 + }
  98 + return sn;
  99 + }
  100 +
  101 + /**
  102 + * 重置一个流媒体服务的所有ssrc
  103 + *
  104 + * @param mediaServerId 流媒体服务ID
  105 + */
  106 + public void reset(String mediaServerId) {
  107 + this.initMediaServerSSRC(mediaServerId, null);
  108 + }
  109 +
  110 + /**
  111 + * 是否已经存在了某个MediaServer的SSRC信息
  112 + *
  113 + * @param mediaServerId 流媒体服务ID
  114 + */
  115 + public boolean hasMediaServerSSRC(String mediaServerId) {
  116 + String redisKey = SSRC_INFO_KEY + mediaServerId;
  117 + return redisTemplate.opsForSet().members(redisKey) != null;
  118 + }
  119 +
  120 + /**
  121 + * 查询ssrc是否可用
  122 + *
  123 + * @param mediaServerId
  124 + * @param ssrc
  125 + * @return
  126 + */
  127 + public boolean checkSsrc(String mediaServerId, String ssrc) {
  128 + String sn = ssrc.substring(1);
  129 + String redisKey = SSRC_INFO_KEY + mediaServerId;
  130 + return redisTemplate.opsForSet().isMember(redisKey, sn) != null;
  131 + }
  132 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.session;
2   -
3   -import com.genersoft.iot.vmp.utils.ConfigConst;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5   -
6   -import java.util.ArrayList;
7   -import java.util.List;
8   -import java.util.Random;
9   -import java.util.Set;
10   -
11   -@Schema(description = "ssrc信息")
12   -public class SsrcConfig {
13   -
14   - /**
15   - * zlm流媒体服务器Id
16   - */
17   - @Schema(description = "流媒体服务器Id")
18   - private String mediaServerId;
19   -
20   - @Schema(description = "SSRC前缀")
21   - private String ssrcPrefix;
22   -
23   - /**
24   - * zlm流媒体服务器已用会话句柄
25   - */
26   - @Schema(description = "zlm流媒体服务器已用会话句柄")
27   - private List<String> isUsed;
28   -
29   - /**
30   - * zlm流媒体服务器可用会话句柄
31   - */
32   - @Schema(description = "zlm流媒体服务器可用会话句柄")
33   - private List<String> notUsed;
34   -
35   - public SsrcConfig() {
36   - }
37   -
38   - public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) {
39   - this.mediaServerId = mediaServerId;
40   - this.isUsed = new ArrayList<>();
41   - this.ssrcPrefix = sipDomain.substring(3, 8);
42   - this.notUsed = new ArrayList<>();
43   - for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) {
44   - String ssrc;
45   - if (i < 10) {
46   - ssrc = "000" + i;
47   - } else if (i < 100) {
48   - ssrc = "00" + i;
49   - } else if (i < 1000) {
50   - ssrc = "0" + i;
51   - } else {
52   - ssrc = String.valueOf(i);
53   - }
54   - if (null == usedSet || !usedSet.contains(ssrc)) {
55   - this.notUsed.add(ssrc);
56   - } else {
57   - this.isUsed.add(ssrc);
58   - }
59   - }
60   - }
61   -
62   -
63   - /**
64   - * 获取视频预览的SSRC值,第一位固定为0
65   - * @return ssrc
66   - */
67   - public String getPlaySsrc() {
68   - return "0" + getSsrcPrefix() + getSN();
69   - }
70   -
71   - /**
72   - * 获取录像回放的SSRC值,第一位固定为1
73   - *
74   - */
75   - public String getPlayBackSsrc() {
76   - return "1" + getSsrcPrefix() + getSN();
77   - }
78   -
79   - /**
80   - * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
81   - * @param ssrc 需要重置的ssrc
82   - */
83   - public void releaseSsrc(String ssrc) {
84   - if (ssrc == null) {
85   - return;
86   - }
87   - String sn = ssrc.substring(6);
88   - try {
89   - isUsed.remove(sn);
90   - notUsed.add(sn);
91   - }catch (NullPointerException e){
92   - }
93   - }
94   -
95   - /**
96   - * 获取后四位数SN,随机数
97   - *
98   - */
99   - private String getSN() {
100   - String sn = null;
101   - int index = 0;
102   - if (notUsed.size() == 0) {
103   - throw new RuntimeException("ssrc已经用完");
104   - } else if (notUsed.size() == 1) {
105   - sn = notUsed.get(0);
106   - } else {
107   - index = new Random().nextInt(notUsed.size() - 1);
108   - sn = notUsed.get(index);
109   - }
110   - notUsed.remove(index);
111   - isUsed.add(sn);
112   - return sn;
113   - }
114   -
115   - public String getSsrcPrefix() {
116   - return ssrcPrefix;
117   - }
118   -
119   - public String getMediaServerId() {
120   - return mediaServerId;
121   - }
122   -
123   - public void setMediaServerId(String mediaServerId) {
124   - this.mediaServerId = mediaServerId;
125   - }
126   -
127   - public void setSsrcPrefix(String ssrcPrefix) {
128   - this.ssrcPrefix = ssrcPrefix;
129   - }
130   -
131   - public List<String> getIsUsed() {
132   - return isUsed;
133   - }
134   -
135   - public void setIsUsed(List<String> isUsed) {
136   - this.isUsed = isUsed;
137   - }
138   -
139   - public List<String> getNotUsed() {
140   - return notUsed;
141   - }
142   -
143   - public void setNotUsed(List<String> notUsed) {
144   - this.notUsed = notUsed;
145   - }
146   -
147   - public boolean checkSsrc(String ssrcInResponse) {
148   - return !isUsed.contains(ssrcInResponse);
149   - }
150   -}
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
1 1 package com.genersoft.iot.vmp.gb28181.session;
2 2  
  3 +import com.genersoft.iot.vmp.common.InviteSessionType;
3 4 import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 5 import com.genersoft.iot.vmp.conf.UserSetting;
5 6 import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
... ... @@ -27,14 +28,6 @@ public class VideoStreamSessionManager {
27 28 @Autowired
28 29 private RedisTemplate<Object, Object> redisTemplate;
29 30  
30   - public enum SessionType {
31   - play,
32   - playback,
33   - download,
34   - broadcast,
35   - talk
36   - }
37   -
38 31 /**
39 32 * 添加一个点播/回放的事务信息
40 33 * 后续可以通过流Id/callID
... ... @@ -45,7 +38,7 @@ public class VideoStreamSessionManager {
45 38 * @param mediaServerId 所使用的流媒体ID
46 39 * @param response 回复
47 40 */
48   - public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, SessionType type){
  41 + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){
49 42 SsrcTransaction ssrcTransaction = new SsrcTransaction();
50 43 ssrcTransaction.setDeviceId(deviceId);
51 44 ssrcTransaction.setChannelId(channelId);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
... ... @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
5 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  8 +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
8 9 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 10 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
10 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
... ... @@ -38,6 +39,9 @@ public class SipRunner implements CommandLineRunner {
38 39 private IRedisCatchStorage redisCatchStorage;
39 40  
40 41 @Autowired
  42 + private SSRCFactory ssrcFactory;
  43 +
  44 + @Autowired
41 45 private UserSetting userSetting;
42 46  
43 47 @Autowired
... ... @@ -96,6 +100,7 @@ public class SipRunner implements CommandLineRunner {
96 100 MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId());
97 101 redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream());
98 102 if (mediaServerItem != null) {
  103 + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
99 104 Map<String, Object> param = new HashMap<>();
100 105 param.put("vhost","__defaultVhost__");
101 106 param.put("app",sendRtpItem.getApp());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
... ... @@ -46,8 +46,7 @@ public class SIPSender {
46 46 transmitRequest(ip, message, errorEvent, null);
47 47 }
48 48  
49   - public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
50   - try {
  49 + public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException {
51 50 ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);
52 51 String transport = "UDP";
53 52 if (viaHeader == null) {
... ... @@ -57,7 +56,7 @@ public class SIPSender {
57 56 }
58 57 if (message.getHeader(UserAgentHeader.NAME) == null) {
59 58 try {
60   - message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  59 + message.addHeader(SipUtils.createUserAgentHeader(gitUtil));
61 60 } catch (ParseException e) {
62 61 logger.error("添加UserAgentHeader失败", e);
63 62 }
... ... @@ -104,9 +103,6 @@ public class SIPSender {
104 103 sipProvider.sendResponse((Response)message);
105 104 }
106 105 }
107   - } finally {
108   -// logger.info("[SEND]:SUCCESS:{}", message);
109   - }
110 106 }
111 107  
112 108 public CallIdHeader getNewCallIdHeader(String ip, String transport){
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 5 import com.genersoft.iot.vmp.gb28181.bean.*;
  6 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  7 +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
6 8 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 9 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
8 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
... ... @@ -107,7 +109,7 @@ public interface ISIPCommander {
107 109 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
108 110 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
109 111 */
110   - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
  112 + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
111 113  
112 114 /**
113 115 * 请求历史媒体下载
... ... @@ -119,7 +121,7 @@ public interface ISIPCommander {
119 121 * @param downloadSpeed 下载倍速参数
120 122 */
121 123 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
122   - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  124 + String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent,
123 125 SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
124 126  
125 127  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -17,6 +17,7 @@ import org.springframework.util.DigestUtils;
17 17  
18 18 import javax.sip.InvalidArgumentException;
19 19 import javax.sip.PeerUnavailableException;
  20 +import javax.sip.SipFactory;
20 21 import javax.sip.address.Address;
21 22 import javax.sip.address.SipURI;
22 23 import javax.sip.header.*;
... ... @@ -50,39 +51,39 @@ public class SIPRequestHeaderPlarformProvider {
50 51 Request request = null;
51 52 String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort();
52 53 //请求行
53   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(),
  54 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(),
54 55 parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
55 56 //via
56 57 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
57   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(),
  58 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(),
58 59 parentPlatform.getServerPort(), parentPlatform.getTransport(), SipUtils.getNewViaTag());
59 60 viaHeader.setRPort();
60 61 viaHeaders.add(viaHeader);
61 62 //from
62   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
63   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
64   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag);
  63 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
  64 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  65 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag);
65 66 //to
66   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
67   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
68   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,toTag);
  67 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
  68 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  69 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,toTag);
69 70  
70 71 //Forwards
71   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  72 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
72 73  
73 74 //ceq
74   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(CSeq, Request.REGISTER);
75   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.REGISTER, callIdHeader,
  75 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(CSeq, Request.REGISTER);
  76 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.REGISTER, callIdHeader,
76 77 cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
77 78  
78   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory()
  79 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory()
79 80 .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
80   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  81 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
81 82  
82   - ExpiresHeader expiresHeader = sipLayer.getSipFactory().createHeaderFactory().createExpiresHeader(expires);
  83 + ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires);
83 84 request.addHeader(expiresHeader);
84 85  
85   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  86 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
86 87  
87 88 return request;
88 89 }
... ... @@ -92,9 +93,9 @@ public class SIPRequestHeaderPlarformProvider {
92 93  
93 94  
94 95 Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, toTag, callIdHeader, expires);
95   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
  96 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
96 97 if (www == null) {
97   - AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader("Digest");
  98 + AuthorizationHeader authorizationHeader = SipFactory.getInstance().createHeaderFactory().createAuthorizationHeader("Digest");
98 99 String username = parentPlatform.getUsername();
99 100 if ( username == null || username == "" )
100 101 {
... ... @@ -147,7 +148,7 @@ public class SIPRequestHeaderPlarformProvider {
147 148  
148 149 String RESPONSE = DigestUtils.md5DigestAsHex(reStr.toString().getBytes());
149 150  
150   - AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader(scheme);
  151 + AuthorizationHeader authorizationHeader = SipFactory.getInstance().createHeaderFactory().createAuthorizationHeader(scheme);
151 152 authorizationHeader.setUsername(parentPlatform.getDeviceGBId());
152 153 authorizationHeader.setRealm(realm);
153 154 authorizationHeader.setNonce(nonce);
... ... @@ -165,7 +166,7 @@ public class SIPRequestHeaderPlarformProvider {
165 166 }
166 167  
167 168 public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
168   - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
  169 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
169 170 return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader);
170 171 }
171 172  
... ... @@ -178,36 +179,36 @@ public class SIPRequestHeaderPlarformProvider {
178 179 Request request = null;
179 180 String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort();
180 181 // sipuri
181   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
  182 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
182 183 // via
183 184 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
184   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(),
  185 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(),
185 186 parentPlatform.getTransport(), viaTag);
186 187 viaHeader.setRPort();
187 188 viaHeaders.add(viaHeader);
188 189 // from
189   - // SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getDeviceIp() + ":" + parentPlatform.getDeviceIp());
190   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
191   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
192   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag);
  190 + // SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getDeviceIp() + ":" + parentPlatform.getDeviceIp());
  191 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
  192 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  193 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag);
193 194 // to
194   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
195   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
196   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, toTag);
  195 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
  196 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  197 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag);
197 198  
198 199 // Forwards
199   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  200 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
200 201 // ceq
201   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
202   - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory();
  202 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
  203 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory();
203 204 // 设置编码, 防止中文乱码
204 205 messageFactory.setDefaultContentEncodingCharset(parentPlatform.getCharacterSet());
205 206 request = messageFactory.createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
206 207 toHeader, viaHeaders, maxForwards);
207 208  
208   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  209 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
209 210  
210   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  211 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
211 212 request.setContent(content, contentTypeHeader);
212 213 return request;
213 214 }
... ... @@ -215,54 +216,54 @@ public class SIPRequestHeaderPlarformProvider {
215 216 public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
216 217 SIPRequest request = null;
217 218 // sipuri
218   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
  219 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
219 220 // via
220 221 ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
221   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(),
  222 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(),
222 223 parentPlatform.getTransport(), SipUtils.getNewViaTag());
223 224 viaHeader.setRPort();
224 225 viaHeaders.add(viaHeader);
225 226 // from
226   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
  227 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
227 228 parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
228   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
229   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
  229 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  230 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
230 231 // to
231   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
232   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
233   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
  232 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
  233 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  234 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
234 235  
235 236 // Forwards
236   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  237 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
237 238 // ceq
238   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY);
239   - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory();
  239 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY);
  240 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory();
240 241 // 设置编码, 防止中文乱码
241 242 messageFactory.setDefaultContentEncodingCharset("gb2312");
242 243  
243   - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
  244 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
244 245  
245 246 request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
246 247 toHeader, viaHeaders, maxForwards);
247 248  
248   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  249 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
249 250  
250   - EventHeader event = sipLayer.getSipFactory().createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  251 + EventHeader event = SipFactory.getInstance().createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
251 252 if (subscribeInfo.getEventId() != null) {
252 253 event.setEventId(subscribeInfo.getEventId());
253 254 }
254 255  
255 256 request.addHeader(event);
256 257  
257   - SubscriptionStateHeader active = sipLayer.getSipFactory().createHeaderFactory().createSubscriptionStateHeader("active");
  258 + SubscriptionStateHeader active = SipFactory.getInstance().createHeaderFactory().createSubscriptionStateHeader("active");
258 259 request.setHeader(active);
259 260  
260 261 String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort();
261   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory()
  262 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory()
262 263 .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
263   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  264 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
264 265  
265   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  266 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
266 267 request.setContent(content, contentTypeHeader);
267 268 return request;
268 269 }
... ... @@ -275,42 +276,42 @@ public class SIPRequestHeaderPlarformProvider {
275 276  
276 277 SIPRequest request = null;
277 278 // sipuri
278   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort());
  279 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort());
279 280 // via
280 281 ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
281   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(platform.getDeviceIp(), platform.getDevicePort(),
  282 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(platform.getDeviceIp(), platform.getDevicePort(),
282 283 platform.getTransport(), SipUtils.getNewViaTag());
283 284 viaHeader.setRPort();
284 285 viaHeaders.add(viaHeader);
285 286 // from
286   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getDeviceGBId(),
  287 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getDeviceGBId(),
287 288 platform.getDeviceIp() + ":" + platform.getDevicePort());
288   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
289   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag());
  289 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  290 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag());
290 291 // to
291   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain());
292   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
293   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag());
  292 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain());
  293 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  294 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag());
294 295  
295 296 // Forwards
296   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  297 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
297 298 // ceq
298   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
299   - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory();
  299 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
  300 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory();
300 301 // 设置编码, 防止中文乱码
301 302 messageFactory.setDefaultContentEncodingCharset("gb2312");
302 303  
303   - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
  304 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
304 305  
305 306 request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader,
306 307 toHeader, viaHeaders, maxForwards);
307 308  
308   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  309 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
309 310  
310 311 String sipAddress = platform.getDeviceIp() + ":" + platform.getDevicePort();
311   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory()
  312 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory()
312 313 .createSipURI(platform.getDeviceGBId(), sipAddress));
313   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  314 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
314 315  
315 316 return request;
316 317 }
... ... @@ -320,37 +321,37 @@ public class SIPRequestHeaderPlarformProvider {
320 321 //请求行
321 322 String platformHostAddress = platform.getServerIP() + ":" + platform.getServerPort();
322 323 String localHostAddress = sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort();
323   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, platformHostAddress);
  324 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, platformHostAddress);
324 325 //via
325 326 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
326   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), viaTag);
  327 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), viaTag);
327 328 viaHeader.setRPort();
328 329 viaHeaders.add(viaHeader);
329 330  
330 331 //from
331   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(platform.getDeviceGBId(), sipConfig.getDomain());
332   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
333   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
  332 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getDeviceGBId(), sipConfig.getDomain());
  333 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  334 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
334 335 //to
335   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, platformHostAddress);
336   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
337   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null);
  336 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, platformHostAddress);
  337 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  338 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
338 339  
339 340 //Forwards
340   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  341 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
341 342  
342 343 //ceq
343   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
344   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  344 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
  345 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
345 346  
346   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  347 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
347 348  
348   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),localHostAddress));
349   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  349 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),localHostAddress));
  350 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
350 351 // Subject
351   - SubjectHeader subjectHeader = sipLayer.getSipFactory().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
  352 + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
352 353 request.addHeader(subjectHeader);
353   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
  354 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
354 355 request.setContent(content, contentTypeHeader);
355 356 return request;
356 357 }
... ... @@ -358,35 +359,35 @@ public class SIPRequestHeaderPlarformProvider {
358 359 public Request createByteRequest(ParentPlatform platform, String channelId, SipTransactionInfo transactionInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
359 360 String deviceHostAddress = platform.getDeviceIp() + ":" + platform.getDevicePort();
360 361 Request request = null;
361   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, deviceHostAddress);
  362 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, deviceHostAddress);
362 363  
363 364 // via
364 365 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
365   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), SipUtils.getNewViaTag());
  366 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getDevicePort(), platform.getTransport(), SipUtils.getNewViaTag());
366 367 viaHeaders.add(viaHeader);
367 368 //from
368   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
369   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
370   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isAsSender()?transactionInfo.getFromTag():transactionInfo.getToTag());
  369 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
  370 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  371 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isAsSender()?transactionInfo.getFromTag():transactionInfo.getToTag());
371 372 //to
372   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, deviceHostAddress);
373   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
374   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,transactionInfo.isAsSender()?transactionInfo.getToTag():transactionInfo.getFromTag());
  373 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, deviceHostAddress);
  374 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  375 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,transactionInfo.isAsSender()?transactionInfo.getToTag():transactionInfo.getFromTag());
375 376  
376 377 //Forwards
377   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  378 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
378 379  
379 380 //ceq
380   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
381   - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
382   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  381 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
  382 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
  383 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
383 384  
384   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  385 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
385 386  
386   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort()));
387   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  387 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort()));
  388 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
388 389  
389   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  390 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
390 391  
391 392 return request;
392 393 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component;
16 16 import javax.sip.InvalidArgumentException;
17 17 import javax.sip.PeerUnavailableException;
18 18 import javax.sip.SipException;
  19 +import javax.sip.SipFactory;
19 20 import javax.sip.address.Address;
20 21 import javax.sip.address.SipURI;
21 22 import javax.sip.header.*;
... ... @@ -49,32 +50,32 @@ public class SIPRequestHeaderProvider {
49 50 public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
50 51 Request request = null;
51 52 // sipuri
52   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
  53 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
53 54 // via
54 55 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
55   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
  56 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
56 57 viaHeader.setRPort();
57 58 viaHeaders.add(viaHeader);
58 59 // from
59   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
60   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
61   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag);
  60 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
  61 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  62 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag);
62 63 // to
63   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
64   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
65   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, toTag);
  64 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
  65 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  66 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag);
66 67  
67 68 // Forwards
68   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  69 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
69 70 // ceq
70   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
  71 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
71 72  
72   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
  73 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
73 74 toHeader, viaHeaders, maxForwards);
74 75  
75   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  76 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
76 77  
77   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  78 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
78 79 request.setContent(content, contentTypeHeader);
79 80 return request;
80 81 }
... ... @@ -82,39 +83,39 @@ public class SIPRequestHeaderProvider {
82 83 public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
83 84 Request request = null;
84 85 //请求行
85   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  86 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
86 87 //via
87 88 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
88   - HeaderFactory headerFactory = sipLayer.getSipFactory().createHeaderFactory();
89   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
  89 + HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
  90 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
90 91 viaHeader.setRPort();
91 92 viaHeaders.add(viaHeader);
92 93  
93 94 //from
94   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
95   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
96   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
  95 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
  96 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  97 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
97 98 //to
98   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
99   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
100   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null);
  99 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  100 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  101 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
101 102  
102 103 //Forwards
103   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  104 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
104 105  
105 106 //ceq
106   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
107   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  107 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
  108 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
108 109  
109   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  110 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
110 111  
111   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
112   - // Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
113   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  112 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
  113 + // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
  114 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
114 115 // Subject
115   - SubjectHeader subjectHeader = sipLayer.getSipFactory().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
  116 + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
116 117 request.addHeader(subjectHeader);
117   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
  118 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
118 119 request.setContent(content, contentTypeHeader);
119 120 return request;
120 121 }
... ... @@ -122,69 +123,74 @@ public class SIPRequestHeaderProvider {
122 123 public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
123 124 Request request = null;
124 125 //请求行
125   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  126 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
126 127 // via
127 128 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
128   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
  129 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
129 130 viaHeader.setRPort();
130 131 viaHeaders.add(viaHeader);
131 132 //from
132   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
133   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
134   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
  133 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
  134 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  135 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
135 136 //to
136   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
137   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
138   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null);
  137 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  138 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  139 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
139 140  
140 141 //Forwards
141   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  142 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
142 143  
143 144 //ceq
144   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
145   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  145 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
  146 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
146 147  
147   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
148   - // Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
149   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  148 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
  149 + // Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
  150 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
150 151  
151   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  152 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
152 153  
153 154 // Subject
154   - SubjectHeader subjectHeader = sipLayer.getSipFactory().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
  155 + SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
155 156 request.addHeader(subjectHeader);
156 157  
157   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
  158 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
158 159 request.setContent(content, contentTypeHeader);
159 160 return request;
160 161 }
161 162  
162 163 public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException {
163 164 Request request = null;
164   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
165   -
  165 + //请求行
  166 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
166 167 // via
167 168 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
168   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
  169 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
169 170 viaHeaders.add(viaHeader);
170 171 //from
171   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
172   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
173   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, !transactionInfo.isAsSender()? transactionInfo.getToTag():transactionInfo.getFromTag());
  172 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
  173 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  174 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
174 175 //to
175   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress());
176   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
177   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, !transactionInfo.isAsSender()? transactionInfo.getToTag(): transactionInfo.getFromTag());
  176 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
  177 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  178 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
178 179  
179 180 //Forwards
180   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  181 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
181 182  
182 183 //ceq
183   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
184   - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
185   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  184 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
  185 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
  186 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  187 +
  188 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
186 189  
187   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  190 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
  191 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
  192 +
  193 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
188 194  
189 195 return request;
190 196 }
... ... @@ -192,50 +198,50 @@ public class SIPRequestHeaderProvider {
192 198 public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
193 199 Request request = null;
194 200 // sipuri
195   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
  201 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
196 202 // via
197 203 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
198   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(),
  204 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(),
199 205 device.getTransport(), SipUtils.getNewViaTag());
200 206 viaHeader.setRPort();
201 207 viaHeaders.add(viaHeader);
202 208 // from
203   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
204   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
205   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
  209 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
  210 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  211 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
206 212 // to
207   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
208   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
209   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
  213 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
  214 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  215 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
210 216  
211 217 // Forwards
212   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  218 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
213 219  
214 220 // ceq
215   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE);
  221 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE);
216 222  
217   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
  223 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
218 224 toHeader, viaHeaders, maxForwards);
219 225  
220 226  
221   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
222   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  227 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
  228 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
223 229  
224 230 // Expires
225   - ExpiresHeader expireHeader = sipLayer.getSipFactory().createHeaderFactory().createExpiresHeader(expires);
  231 + ExpiresHeader expireHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires);
226 232 request.addHeader(expireHeader);
227 233  
228 234 // Event
229   - EventHeader eventHeader = sipLayer.getSipFactory().createHeaderFactory().createEventHeader(event);
  235 + EventHeader eventHeader = SipFactory.getInstance().createHeaderFactory().createEventHeader(event);
230 236  
231 237 int random = (int) Math.floor(Math.random() * 10000);
232 238 eventHeader.setEventId(random + "");
233 239 request.addHeader(eventHeader);
234 240  
235   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  241 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
236 242 request.setContent(content, contentTypeHeader);
237 243  
238   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  244 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
239 245  
240 246 return request;
241 247 }
... ... @@ -247,37 +253,37 @@ public class SIPRequestHeaderProvider {
247 253 }
248 254 SIPRequest request = null;
249 255 //请求行
250   - SipURI requestLine = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  256 + SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
251 257 // via
252 258 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
253   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
  259 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
254 260 viaHeaders.add(viaHeader);
255 261 //from
256   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
257   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
258   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
  262 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
  263 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  264 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
259 265 //to
260   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress());
261   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
262   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
  266 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
  267 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  268 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
263 269  
264 270 //Forwards
265   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  271 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
266 272  
267 273 //ceq
268   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO);
269   - CallIdHeader callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
270   - request = (SIPRequest)sipLayer.getSipFactory().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  274 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO);
  275 + CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
  276 + request = (SIPRequest)SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
271 277  
272   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  278 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
273 279  
274   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
275   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  280 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
  281 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
276 282  
277   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  283 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
278 284  
279 285 if (content != null) {
280   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application",
  286 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application",
281 287 "MANSRTSP");
282 288 request.setContent(content, contentTypeHeader);
283 289 }
... ... @@ -289,56 +295,55 @@ public class SIPRequestHeaderProvider {
289 295  
290 296 // via
291 297 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
292   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
  298 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
293 299 viaHeaders.add(viaHeader);
294 300  
295 301 //Forwards
296   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  302 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
297 303  
298 304 //ceq
299   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
  305 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
300 306  
301   - Request request = sipLayer.getSipFactory().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
  307 + Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
302 308  
303   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  309 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
304 310  
305   - Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort()));
306   - request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
  311 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort()));
  312 + request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
307 313  
308   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  314 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
309 315  
310 316 return request;
311 317 }
312   -
313 318 public Request createBroadcastMessageRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
314 319 Request request = null;
315 320 // sipuri
316   - SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  321 + SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
317 322 // via
318 323 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
319   - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag);
  324 + ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag);
320 325 viaHeader.setRPort();
321 326 viaHeaders.add(viaHeader);
322 327 // from
323   - SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
324   - Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
325   - FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, fromTag);
  328 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
  329 + Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
  330 + FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag);
326 331 // to
327   - SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId, device.getHostAddress());
328   - Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
329   - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, toTag);
  332 + SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  333 + Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
  334 + ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag);
330 335  
331 336 // Forwards
332   - MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
  337 + MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
333 338 // ceq
334   - CSeqHeader cSeqHeader = sipLayer.getSipFactory().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
  339 + CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
335 340  
336   - ContentTypeHeader contentTypeHeader = sipLayer.getSipFactory().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  341 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
337 342  
338   - request = sipLayer.getSipFactory().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
  343 + request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
339 344 toHeader, viaHeaders, maxForwards, contentTypeHeader, content);
340 345  
341   - request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  346 + request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
342 347  
343 348 return request;
344 349 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2  
3 3 import com.alibaba.fastjson2.JSONObject;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 5 import com.genersoft.iot.vmp.common.StreamInfo;
5 6 import com.genersoft.iot.vmp.conf.SipConfig;
6 7 import com.genersoft.iot.vmp.conf.UserSetting;
... ... @@ -36,6 +37,7 @@ import org.springframework.util.ObjectUtils;
36 37 import javax.sip.InvalidArgumentException;
37 38 import javax.sip.ResponseEvent;
38 39 import javax.sip.SipException;
  40 +import javax.sip.SipFactory;
39 41 import javax.sip.header.CallIdHeader;
40 42 import javax.sip.message.Request;
41 43 import java.text.ParseException;
... ... @@ -358,7 +360,7 @@ public class SIPCommander implements ISIPCommander {
358 360 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
359 361 ResponseEvent responseEvent = (ResponseEvent) e.event;
360 362 SIPResponse response = (SIPResponse) responseEvent.getResponse();
361   - streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play);
  363 + streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAY);
362 364 okEvent.response(e);
363 365 });
364 366 }
... ... @@ -373,11 +375,11 @@ public class SIPCommander implements ISIPCommander {
373 375 */
374 376 @Override
375 377 public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
376   - String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  378 + String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent,
377 379 SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
378 380  
379 381  
380   - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort());
  382 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
381 383 String sdpIp;
382 384 if (!ObjectUtils.isEmpty(device.getSdpIp())) {
383 385 sdpIp = device.getSdpIp();
... ... @@ -450,8 +452,7 @@ public class SIPCommander implements ISIPCommander {
450 452 // 添加订阅
451 453 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
452 454 if (hookEvent != null) {
453   - InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream());
454   - hookEvent.call(inviteStreamInfo);
  455 + hookEvent.response(mediaServerItemInUse, json);
455 456 }
456 457 subscribe.removeSubscribe(hookSubscribe);
457 458 });
... ... @@ -460,12 +461,9 @@ public class SIPCommander implements ISIPCommander {
460 461 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
461 462 ResponseEvent responseEvent = (ResponseEvent) event.event;
462 463 SIPResponse response = (SIPResponse) responseEvent.getResponse();
463   - streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback);
  464 + streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK);
464 465 okEvent.response(event);
465 466 });
466   - if (inviteStreamCallback != null) {
467   - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()));
468   - }
469 467 }
470 468  
471 469 /**
... ... @@ -480,10 +478,10 @@ public class SIPCommander implements ISIPCommander {
480 478 @Override
481 479 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
482 480 String startTime, String endTime, int downloadSpeed,
483   - InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  481 + ZlmHttpHookSubscribe.Event hookEvent,
484 482 SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
485 483  
486   - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort());
  484 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
487 485 String sdpIp;
488 486 if (!ObjectUtils.isEmpty(device.getSdpIp())) {
489 487 sdpIp = device.getSdpIp();
... ... @@ -551,13 +549,13 @@ public class SIPCommander implements ISIPCommander {
551 549  
552 550 content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
553 551 logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc());
554   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
  552 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
555 553 // 添加订阅
556 554 CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport());
557   - String callId=newCallIdHeader.getCallId();
  555 + String callId= newCallIdHeader.getCallId();
558 556 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
559 557 logger.debug("sipc 添加订阅===callId {}",callId);
560   - hookEvent.call(new InviteStreamInfo(mediaServerItem, json,callId, "rtp", ssrcInfo.getStream()));
  558 + hookEvent.response(mediaServerItemInUse, json);
561 559 subscribe.removeSubscribe(hookSubscribe);
562 560 hookSubscribe.getContent().put("regist", false);
563 561 hookSubscribe.getContent().put("schema", "rtsp");
... ... @@ -566,7 +564,7 @@ public class SIPCommander implements ISIPCommander {
566 564 (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> {
567 565 logger.info("[录像]下载结束, 发送BYE");
568 566 try {
569   - streamByeCmd(device, channelId, ssrcInfo.getStream(),callId);
  567 + streamByeCmd(device, channelId, ssrcInfo.getStream(), callId);
570 568 } catch (InvalidArgumentException | ParseException | SipException |
571 569 SsrcTransactionNotFoundException e) {
572 570 logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage());
... ... @@ -575,9 +573,6 @@ public class SIPCommander implements ISIPCommander {
575 573 });
576 574  
577 575 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc());
578   - if (inviteStreamCallback != null) {
579   - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,callId, "rtp", ssrcInfo.getStream()));
580   - }
581 576  
582 577 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
583 578 ResponseEvent responseEvent = (ResponseEvent) event.event;
... ... @@ -588,9 +583,7 @@ public class SIPCommander implements ISIPCommander {
588 583 if (ssrcIndex >= 0) {
589 584 ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
590 585 }
591   - logger.debug("接收到的下载响应ssrc====>{}",ssrcInfo.getSsrc());
592   - logger.debug("接收到的下载响应ssrc====>{}",ssrc);
593   - streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
  586 + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD);
594 587 okEvent.response(event);
595 588 });
596 589 }
... ... @@ -654,7 +647,7 @@ public class SIPCommander implements ISIPCommander {
654 647 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
655 648 ResponseEvent responseEvent = (ResponseEvent) e.event;
656 649 SIPResponse response = (SIPResponse) responseEvent.getResponse();
657   - streamSession.put(device.getDeviceId(), channelId, "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.talk);
  650 + streamSession.put(device.getDeviceId(), channelId, "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK);
658 651 okEvent.response(e);
659 652 });
660 653 }
... ... @@ -1247,7 +1240,7 @@ public class SIPCommander implements ISIPCommander {
1247 1240 CallIdHeader callIdHeader;
1248 1241  
1249 1242 if (requestOld != null) {
1250   - callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
  1243 + callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1251 1244 } else {
1252 1245 callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport());
1253 1246 }
... ... @@ -1322,7 +1315,7 @@ public class SIPCommander implements ISIPCommander {
1322 1315 CallIdHeader callIdHeader;
1323 1316  
1324 1317 if (requestOld != null) {
1325   - callIdHeader = sipLayer.getSipFactory().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
  1318 + callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1326 1319 } else {
1327 1320 callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport());
1328 1321 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2  
3 3 import com.alibaba.fastjson2.JSON;
4 4 import com.alibaba.fastjson2.JSONObject;
  5 +import com.genersoft.iot.vmp.common.InviteSessionType;
5 6 import com.genersoft.iot.vmp.conf.DynamicTask;
6 7 import com.genersoft.iot.vmp.conf.UserSetting;
7 8 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
... ... @@ -39,6 +40,7 @@ import org.springframework.util.ObjectUtils;
39 40 import javax.sip.InvalidArgumentException;
40 41 import javax.sip.ResponseEvent;
41 42 import javax.sip.SipException;
  43 +import javax.sip.SipFactory;
42 44 import javax.sip.header.CallIdHeader;
43 45 import javax.sip.header.WWWAuthenticateHeader;
44 46 import javax.sip.message.Request;
... ... @@ -518,7 +520,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
518 520 private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
519 521 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
520 522 throws SipException, ParseException, InvalidArgumentException {
521   - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory();
  523 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory();
522 524 String characterSet = parentPlatform.getCharacterSet();
523 525 // 设置编码, 防止中文乱码
524 526 messageFactory.setDefaultContentEncodingCharset(characterSet);
... ... @@ -854,7 +856,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
854 856 }), e -> {
855 857 ResponseEvent responseEvent = (ResponseEvent) e.event;
856 858 SIPResponse response = (SIPResponse) responseEvent.getResponse();
857   - streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(), stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.broadcast);
  859 + streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(), stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.BROADCAST);
858 860 okEvent.response(e);
859 861 });
860 862 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2  
3   -import com.genersoft.iot.vmp.common.StreamInfo;
  3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 5 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 6 import com.genersoft.iot.vmp.gb28181.bean.*;
6 7 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
  8 +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
7 9 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
8 10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
9 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
... ... @@ -13,6 +15,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP
13 15 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
14 16 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
15 17 import com.genersoft.iot.vmp.service.IDeviceService;
  18 +import com.genersoft.iot.vmp.service.IInviteStreamService;
16 19 import com.genersoft.iot.vmp.service.IMediaServerService;
17 20 import com.genersoft.iot.vmp.service.IPlayService;
18 21 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
... ... @@ -29,6 +32,7 @@ import javax.sip.InvalidArgumentException;
29 32 import javax.sip.RequestEvent;
30 33 import javax.sip.SipException;
31 34 import javax.sip.address.SipURI;
  35 +import javax.sip.header.CallIdHeader;
32 36 import javax.sip.header.FromHeader;
33 37 import javax.sip.header.HeaderAddress;
34 38 import javax.sip.header.ToHeader;
... ... @@ -57,6 +61,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
57 61 private IRedisCatchStorage redisCatchStorage;
58 62  
59 63 @Autowired
  64 + private IInviteStreamService inviteStreamService;
  65 +
  66 + @Autowired
60 67 private IDeviceService deviceService;
61 68  
62 69 @Autowired
... ... @@ -69,6 +76,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
69 76 private ZLMRTPServerFactory zlmrtpServerFactory;
70 77  
71 78 @Autowired
  79 + private SSRCFactory ssrcFactory;
  80 +
  81 + @Autowired
72 82 private IMediaServerService mediaServerService;
73 83  
74 84 @Autowired
... ... @@ -100,92 +110,89 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
100 110 } catch (SipException | InvalidArgumentException | ParseException e) {
101 111 logger.error("[回复BYE信息失败],{}", e.getMessage());
102 112 }
103   -
104   - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, request.getCallIdHeader().getCallId());
105   -
106   - if (sendRtpItem != null){
107   - logger.info("[收到bye] {}/{}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId());
108   - String streamId = sendRtpItem.getStream();
109   - MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId());
110   - if (mediaServerItem == null) {
111   - return;
112   - }
113   -
114   - Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), streamId);
115   - if (!ready) {
116   - logger.info("[收到bye] 发现流{}/{}已经结束,不需处理", sendRtpItem.getApp(), sendRtpItem.getStream());
117   - return;
118   - }
119   - Map<String, Object> param = new HashMap<>();
120   - param.put("vhost","__defaultVhost__");
121   - param.put("app",sendRtpItem.getApp());
122   - param.put("stream",streamId);
123   - param.put("ssrc",sendRtpItem.getSsrc());
124   - logger.info("[收到bye] 停止推流:{}", streamId);
125   - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
126   - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), request.getCallIdHeader().getCallId(), null);
127   - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
128   -
129   - int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
130   - if (totalReaderCount <= 0) {
131   - logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
132   - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
133   - Device device = deviceService.getDevice(sendRtpItem.getDeviceId());
134   - if (device == null) {
135   - logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
  113 + CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
  114 + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
  115 + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
  116 + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
  117 + logger.info("[收到bye] {}/{}", platformGbId, channelId);
  118 + if (sendRtpItem != null){
  119 + String streamId = sendRtpItem.getStream();
  120 + Map<String, Object> param = new HashMap<>();
  121 + param.put("vhost","__defaultVhost__");
  122 + param.put("app",sendRtpItem.getApp());
  123 + param.put("stream",streamId);
  124 + param.put("ssrc",sendRtpItem.getSsrc());
  125 + logger.info("[收到bye] 停止向上级推流:{}", streamId);
  126 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  127 + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
  128 + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
  129 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
  130 + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
  131 + if (totalReaderCount <= 0) {
  132 + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
  133 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
  134 + Device device = deviceService.getDevice(sendRtpItem.getDeviceId());
  135 + if (device == null) {
  136 + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
  137 + }
  138 + try {
  139 + logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), channelId);
  140 + cmder.streamByeCmd(device, channelId, streamId, null);
  141 + } catch (InvalidArgumentException | ParseException | SipException |
  142 + SsrcTransactionNotFoundException e) {
  143 + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
  144 + }
136 145 }
137   - try {
138   - logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
139   - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null);
140   - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
141   - logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
  146 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
  147 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  148 + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(),
  149 + sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
  150 + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
142 151 }
143 152 }
144   -
145   - if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
146   - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
147   - sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(),
148   - sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
149   - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
150   - }
151 153 }
  154 + // 可能是设备主动停止
  155 + Device device = storager.queryVideoDeviceByChannelId(platformGbId);
  156 + if (device != null) {
  157 + storager.stopPlay(device.getDeviceId(), channelId);
  158 + SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
  159 + if (ssrcTransactionForPlay != null){
  160 + if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){
  161 + // 释放ssrc
  162 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
  163 + if (mediaServerItem != null) {
  164 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
  165 + }
  166 + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
  167 + }
  168 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
152 169  
153   - playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
154   - }
155   -
156   - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
157   - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
158   -
159   - // 可能是设备主动停止
160   - Device device = storager.queryVideoDeviceByChannelId(platformGbId);
161   - if (device != null) {
162   - storager.stopPlay(device.getDeviceId(), channelId);
163   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
164   - if (streamInfo != null) {
165   - redisCatchStorage.stopPlay(streamInfo);
166   - mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
167   - }
168   - SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
169   - if (ssrcTransactionForPlay != null){
170   - if (ssrcTransactionForPlay.getCallId().equals(request.getCallIdHeader().getCallId())){
  170 + if (inviteInfo != null) {
  171 + inviteStreamService.removeInviteInfo(inviteInfo);
  172 + if (inviteInfo.getStreamInfo() != null) {
  173 + mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream());
  174 + }
  175 + }
  176 + }
  177 + SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
  178 + if (ssrcTransactionForPlayBack != null) {
171 179 // 释放ssrc
172   - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
  180 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
173 181 if (mediaServerItem != null) {
174   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
  182 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
  183 + }
  184 + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
  185 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, device.getDeviceId(), channelId);
  186 +
  187 + if (inviteInfo != null) {
  188 + inviteStreamService.removeInviteInfo(inviteInfo);
  189 + if (inviteInfo.getStreamInfo() != null) {
  190 + mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream());
  191 + }
175 192 }
176   - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
177   - }
178   - }
179   - SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, request.getCallIdHeader().getCallId(), null);
180   - if (ssrcTransactionForPlayBack != null) {
181   - // 释放ssrc
182   - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
183   - if (mediaServerItem != null) {
184   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
185 193 }
186   - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
187 194 }
188   - }
  195 +
189 196 SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, request.getCallIdHeader().getCallId(), null);
190 197 if (ssrcTransaction != null) {
191 198 // 释放ssrc
... ... @@ -203,7 +210,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
203 210 // break;
204 211 // case download:
205 212 // break;
206   - case broadcast:
  213 + case BROADCAST:
207 214 String channelId1 = ssrcTransaction.getChannelId();
208 215  
209 216 Device deviceFromTransaction = storager.queryVideoDevice(ssrcTransaction.getDeviceId());
... ... @@ -255,7 +262,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
255 262 List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(null, channelId1, null, null);
256 263 if (ssrcTransactions.size() > 0) {
257 264 for (SsrcTransaction transaction : ssrcTransactions) {
258   - if (transaction.getType().equals(VideoStreamSessionManager.SessionType.broadcast)) {
  265 + if (transaction.getType().equals(InviteSessionType.BROADCAST)) {
259 266 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(transaction.getDeviceId());
260 267 if (parentPlatform != null) {
261 268 try {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2  
3   -import com.alibaba.fastjson2.JSONObject;
4 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
  4 +import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 6 import com.genersoft.iot.vmp.conf.SipConfig;
7 7 import com.genersoft.iot.vmp.conf.UserSetting;
8 8 import com.genersoft.iot.vmp.gb28181.bean.*;
9   -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
10 9 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
11   -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
12 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  11 +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
13 12 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
14 13 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
15 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
... ... @@ -23,7 +22,12 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
23 22 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
24 23 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
25 24 import com.genersoft.iot.vmp.media.zlm.dto.*;
26   -import com.genersoft.iot.vmp.service.*;
  25 +import com.genersoft.iot.vmp.service.IMediaServerService;
  26 +import com.genersoft.iot.vmp.service.IPlayService;
  27 +import com.genersoft.iot.vmp.service.IStreamProxyService;
  28 +import com.genersoft.iot.vmp.service.IStreamPushService;
  29 +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
  30 +import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
27 31 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
28 32 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
29 33 import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
... ... @@ -79,6 +83,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
79 83 private IRedisCatchStorage redisCatchStorage;
80 84  
81 85 @Autowired
  86 + private SSRCFactory ssrcFactory;
  87 +
  88 + @Autowired
82 89 private DynamicTask dynamicTask;
83 90  
84 91 @Autowired
... ... @@ -90,8 +97,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
90 97 @Autowired
91 98 private SIPSender sipSender;
92 99  
93   - @Autowired
94   - private AudioBroadcastManager audioBroadcastManager;
  100 + @Autowired
  101 + private AudioBroadcastManager audioBroadcastManager;
95 102  
96 103 @Autowired
97 104 private ZLMRTPServerFactory zlmrtpServerFactory;
... ... @@ -102,8 +109,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
102 109 @Autowired
103 110 private ISIPCommander commander;
104 111  
105   - @Autowired
106   - private ZLMRESTfulUtils zlmresTfulUtils;
  112 + @Autowired
  113 + private ZLMRESTfulUtils zlmresTfulUtils;
107 114  
108 115 @Autowired
109 116 private ZlmHttpHookSubscribe zlmHttpHookSubscribe;
... ... @@ -112,28 +119,24 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
112 119 private SIPProcessorObserver sipProcessorObserver;
113 120  
114 121 @Autowired
115   - private VideoStreamSessionManager sessionManager;
116   -
117   - @Autowired
118 122 private UserSetting userSetting;
119 123  
120 124 @Autowired
121 125 private ZLMMediaListManager mediaListManager;
122 126  
123   - @Autowired
124   - private DeferredResultHolder resultHolder;
  127 + @Autowired
  128 + private DeferredResultHolder resultHolder;
125 129  
126   - @Autowired
127   - private ZlmHttpHookSubscribe subscribe;
  130 + @Autowired
  131 + private ZlmHttpHookSubscribe subscribe;
128 132  
129   - @Autowired
130   - private SipConfig config;
  133 + @Autowired
  134 + private SipConfig config;
131 135  
132 136 @Autowired
133 137 private VideoStreamSessionManager streamSession;
134 138  
135 139  
136   -
137 140 @Autowired
138 141 private RedisGbPlayMsgListener redisGbPlayMsgListener;
139 142  
... ... @@ -153,7 +156,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
153 156 public void process(RequestEvent evt) {
154 157 // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
155 158 try {
156   - SIPRequest request = (SIPRequest)evt.getRequest();
  159 + SIPRequest request = (SIPRequest) evt.getRequest();
157 160 String channelId = SipUtils.getChannelIdFromRequest(request);
158 161 String requesterId = SipUtils.getUserIdFromFromHeader(request);
159 162 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
... ... @@ -167,27 +170,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
167 170 }
168 171 return;
169 172 }
170   - String ssrc = null;
171   - SessionDescription sdp = null;
172   - String ssrcDefault = "0000000000";
173   - if (channelId == null) {
174   - // 解析sdp消息, 使用jainsip 自带的sdp解析方式
175   - String contentString = new String(request.getRawContent());
176   -
177   - // jainSip不支持y=字段, 移除以解析。
178   - int ssrcIndex = contentString.indexOf("y=");
179   -
180   - if (ssrcIndex >= 0) {
181   - //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段
182   - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
183   - String substring = contentString.substring(0, contentString.indexOf("y="));
184   - sdp = SdpFactory.getInstance().createSessionDescription(substring);
185   - } else {
186   - ssrc = ssrcDefault;
187   - sdp = SdpFactory.getInstance().createSessionDescription(contentString);
188   - }
189   - channelId = sdp.getOrigin().getUsername();
190   - }
191 173  
192 174  
193 175 // 查询请求是否来自上级平台\设备
... ... @@ -249,7 +231,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
249 231 }
250 232 return;
251 233 }
252   - }else if("proxy".equals(gbStream.getStreamType())){
  234 + } else if ("proxy".equals(gbStream.getStreamType())) {
253 235 proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
254 236 if (proxyByAppAndStream == null) {
255 237 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
... ... @@ -285,23 +267,21 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
285 267 }
286 268 return;
287 269 }
288   - if (sdp == null || ssrc == null) {
289   - // 解析sdp消息, 使用jainsip 自带的sdp解析方式
290   - String contentString = new String(request.getRawContent());
291   -
292   - // jainSip不支持y=字段, 移除以解析。
293   - int ssrcIndex = contentString.indexOf("y=");
294   - if (ssrcIndex >= 0) {
295   - //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段
296   - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
297   - String substring = contentString.substring(0, contentString.indexOf("y="));
298   - sdp = SdpFactory.getInstance().createSessionDescription(substring);
299   - } else {
300   - ssrc = ssrcDefault;
301   - sdp = SdpFactory.getInstance().createSessionDescription(contentString);
302   - }
303   - }
  270 + // 解析sdp消息, 使用jainsip 自带的sdp解析方式
  271 + String contentString = new String(request.getRawContent());
304 272  
  273 + // jainSip不支持y=字段, 移除以解析。
  274 + // 检查是否有y字段
  275 + int ssrcIndex = contentString.indexOf("y=");
  276 +
  277 + SessionDescription sdp;
  278 + if (ssrcIndex >= 0) {
  279 + //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段
  280 + String substring = contentString.substring(0, ssrcIndex);
  281 + sdp = SdpFactory.getInstance().createSessionDescription(substring);
  282 + } else {
  283 + sdp = SdpFactory.getInstance().createSessionDescription(contentString);
  284 + }
305 285 String sessionName = sdp.getSessionName().getValue();
306 286  
307 287 Long startTime = null;
... ... @@ -363,7 +343,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
363 343 String username = sdp.getOrigin().getUsername();
364 344 String addressStr = sdp.getConnection().getAddress();
365 345  
366   - logger.info("[上级点播]用户:{}, 通道:{}, 地址:{}:{}, ssrc:{}", username, channelId, addressStr, port, ssrc);
  346 +
367 347 Device device = null;
368 348 // 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标
369 349 if (channel != null) {
... ... @@ -387,6 +367,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
387 367 }
388 368 return;
389 369 }
  370 +
  371 + String ssrc;
  372 + if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) {
  373 + // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
  374 + ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
  375 + } else {
  376 + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  377 + }
  378 + String streamTypeStr = null;
  379 + if (mediaTransmissionTCP) {
  380 + if (tcpActive) {
  381 + streamTypeStr = "TCP-ACTIVE";
  382 + } else {
  383 + streamTypeStr = "TCP-PASSIVE";
  384 + }
  385 + } else {
  386 + streamTypeStr = "UDP";
  387 + }
  388 + logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc);
390 389 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
391 390 device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp());
392 391  
... ... @@ -407,11 +406,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
407 406  
408 407 Long finalStartTime = startTime;
409 408 Long finalStopTime = stopTime;
410   - String finalChannelId = channelId;
411   - ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> {
412   - String app = responseJSON.getString("app");
413   - String stream = responseJSON.getString("stream");
414   - logger.info("[上级点播]下级已经开始推流。 回复200OK(SDP), {}/{}", app, stream);
  409 + InviteErrorCallback<Object> hookEvent = (code, msg, data) -> {
  410 + StreamInfo streamInfo = (StreamInfo) data;
  411 + MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId());
  412 + logger.info("[上级Invite]下级已经开始推流。 回复200OK(SDP), {}/{}", streamInfo.getApp(), streamInfo.getStream());
415 413 // * 0 等待设备推流上来
416 414 // * 1 下级已经推流,等待上级平台回复ack
417 415 // * 2 推流中
... ... @@ -420,7 +418,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
420 418  
421 419 StringBuffer content = new StringBuffer(200);
422 420 content.append("v=0\r\n");
423   - content.append("o=" + finalChannelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
  421 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
424 422 content.append("s=" + sessionName + "\r\n");
425 423 content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
426 424 if ("Playback".equalsIgnoreCase(sessionName)) {
... ... @@ -462,111 +460,118 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
462 460 logger.error("[命令发送失败] 国标级联 回复SdpAck", e);
463 461 }
464 462 };
465   - SipSubscribe.Event errorEvent = ((event) -> {
  463 + InviteErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> {
466 464 // 未知错误。直接转发设备点播的错误
467 465 try {
468   - Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
469   - sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
470   - } catch (ParseException | SipException e) {
  466 + if (statusCode > 0) {
  467 + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
  468 + sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
  469 + }
  470 + } catch (ParseException | SipException e) {
471 471 logger.error("未处理的异常 ", e);
472 472 }
473 473 });
474 474 sendRtpItem.setApp("rtp");
475 475 if ("Playback".equalsIgnoreCase(sessionName)) {
476 476 sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
477   - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, device.isSsrcCheck(), true);
  477 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam());
478 478 sendRtpItem.setStream(ssrcInfo.getStream());
479 479 // 写入redis, 超时时回复
480 480 redisCatchStorage.updateSendRTPSever(sendRtpItem);
481 481 playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
482   - DateUtil.formatter.format(end), null, result -> {
483   - if (result.getCode() != 0) {
484   - logger.warn("录像回放失败");
485   - if (result.getEvent() != null) {
486   - errorEvent.response(result.getEvent());
487   - }
488   - redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null);
489   - try {
490   - responseAck(request, Response.REQUEST_TIMEOUT);
491   - } catch (SipException | InvalidArgumentException | ParseException e) {
492   - logger.error("[命令发送失败] 国标级联 录像回放 发送REQUEST_TIMEOUT: {}", e.getMessage());
493   - }
  482 + DateUtil.formatter.format(end),
  483 + (code, msg, data) -> {
  484 + if (code == InviteErrorCode.SUCCESS.getCode()) {
  485 + hookEvent.run(code, msg, data);
  486 + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) {
  487 + logger.info("[录像回放]超时, 用户:{}, 通道:{}", username, channelId);
  488 + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
  489 + errorEvent.run(code, msg, data);
  490 + } else {
  491 + errorEvent.run(code, msg, data);
  492 + }
  493 + });
  494 + } else if ("Download".equalsIgnoreCase(sessionName)) {
  495 + // 获取指定的下载速度
  496 + Vector sdpMediaDescriptions = sdp.getMediaDescriptions(true);
  497 + MediaDescription mediaDescription = null;
  498 + String downloadSpeed = "1";
  499 + if (sdpMediaDescriptions.size() > 0) {
  500 + mediaDescription = (MediaDescription) sdpMediaDescriptions.get(0);
  501 + }
  502 + if (mediaDescription != null) {
  503 + downloadSpeed = mediaDescription.getAttribute("downloadspeed");
  504 + }
  505 +
  506 + sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD);
  507 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam());
  508 + sendRtpItem.setStream(ssrcInfo.getStream());
  509 + // 写入redis, 超时时回复
  510 + redisCatchStorage.updateSendRTPSever(sendRtpItem);
  511 + playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
  512 + DateUtil.formatter.format(end), Integer.parseInt(downloadSpeed),
  513 + (code, msg, data) -> {
  514 + if (code == InviteErrorCode.SUCCESS.getCode()) {
  515 + hookEvent.run(code, msg, data);
  516 + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) {
  517 + logger.info("[录像下载]超时, 用户:{}, 通道:{}", username, channelId);
  518 + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
  519 + errorEvent.run(code, msg, data);
494 520 } else {
495   - if (result.getMediaServerItem() != null) {
496   - hookEvent.response(result.getMediaServerItem(), result.getResponse());
497   - }
  521 + errorEvent.run(code, msg, data);
498 522 }
499 523 });
500 524 } else {
501 525 sendRtpItem.setPlayType(InviteStreamType.PLAY);
502   - SsrcTransaction playTransaction = sessionManager.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
503   - if (playTransaction != null) {
504   - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream());
505   - if (!streamReady) {
506   - boolean hasRtpServer = mediaServerService.checkRtpServer(mediaServerItem, "rtp", playTransaction.getStream());
507   - if (hasRtpServer) {
508   - logger.info("[上级点播]已经开启rtpServer但是尚未收到流,开启监听流的到来");
509   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", playTransaction.getStream(), true, "rtsp", mediaServerItem.getId());
510   - zlmHttpHookSubscribe.addSubscribe(hookSubscribe, hookEvent);
511   - }else {
512   - playTransaction = null;
513   - }
514   - }
515   - }
516   - if (playTransaction == null) {
517   - String streamId = null;
518   - if (mediaServerItem.isRtpEnable()) {
519   - streamId = String.format("%s_%s", device.getDeviceId(), channelId);
520   - }
521   - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
522   - logger.info(JSONObject.toJSONString(ssrcInfo));
523   - sendRtpItem.setStream(ssrcInfo.getStream());
524   - sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc);
525   -
526   - // 写入redis, 超时时回复
527   - redisCatchStorage.updateSendRTPSever(sendRtpItem);
528   - playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> {
529   - logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, finalChannelId);
530   - redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null);
531   - });
  526 + String streamId = null;
  527 + if (mediaServerItem.isRtpEnable()) {
  528 + streamId = String.format("%s_%s", device.getDeviceId(), channelId);
532 529 } else {
533   - sendRtpItem.setStream(playTransaction.getStream());
534   - // 写入redis, 超时时回复
535   - redisCatchStorage.updateSendRTPSever(sendRtpItem);
536   - JSONObject jsonObject = new JSONObject();
537   - jsonObject.put("app", sendRtpItem.getApp());
538   - jsonObject.put("stream", sendRtpItem.getStream());
539   - hookEvent.response(mediaServerItem, jsonObject);
  530 + streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
540 531 }
  532 + sendRtpItem.setStream(streamId);
  533 + redisCatchStorage.updateSendRTPSever(sendRtpItem);
  534 + playService.play(mediaServerItem, device.getDeviceId(), channelId, ((code, msg, data) -> {
  535 + if (code == InviteErrorCode.SUCCESS.getCode()) {
  536 + hookEvent.run(code, msg, data);
  537 + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) {
  538 + logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId);
  539 + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
  540 + errorEvent.run(code, msg, data);
  541 + } else {
  542 + errorEvent.run(code, msg, data);
  543 + }
  544 + }));
  545 +
541 546 }
542 547 } else if (gbStream != null) {
543   - if(ssrc.equals(ssrcDefault))
544   - {
545   - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
546   - if(ssrcConfig != null)
547   - {
548   - ssrc = ssrcConfig.getPlaySsrc();
549   - ssrcConfig.releaseSsrc(ssrc);
550   - }
  548 +
  549 + String ssrc;
  550 + if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) {
  551 + // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
  552 + ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
  553 + } else {
  554 + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
551 555 }
552   - if("push".equals(gbStream.getStreamType())) {
  556 +
  557 + if ("push".equals(gbStream.getStreamType())) {
553 558 if (streamPushItem != null && streamPushItem.isPushIng()) {
554 559 // 推流状态
555 560 pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
556 561 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
557 562 } else {
558 563 // 未推流 拉起
559   - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  564 + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
560 565 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
561 566 }
562   - }else if ("proxy".equals(gbStream.getStreamType())){
  567 + } else if ("proxy".equals(gbStream.getStreamType())) {
563 568 if (null != proxyByAppAndStream) {
564   - if(proxyByAppAndStream.isStatus()){
565   - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  569 + if (proxyByAppAndStream.isStatus()) {
  570 + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
566 571 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
567   - }else{
  572 + } else {
568 573 //开启代理拉流
569   - notifyStreamOnline(evt, request,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
  574 + notifyStreamOnline(evt, request, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
570 575 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
571 576 }
572 577 }
... ... @@ -586,42 +591,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
586 591 * 安排推流
587 592 */
588 593 private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform,
589   - CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
590   - int port, Boolean tcpActive, boolean mediaTransmissionTCP,
591   - String channelId, String addressStr, String ssrc, String requesterId) {
592   - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
593   - if (streamReady) {
594   - // 自平台内容
595   - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
596   - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
597   -
598   - if (sendRtpItem == null) {
599   - logger.warn("服务器端口资源不足");
600   - try {
601   - responseAck(request, Response.BUSY_HERE);
602   - } catch (SipException | InvalidArgumentException | ParseException e) {
603   - logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage());
604   - }
605   - return;
606   - }
607   - if (tcpActive != null) {
608   - sendRtpItem.setTcpActive(tcpActive);
609   - }
610   - sendRtpItem.setPlayType(InviteStreamType.PUSH);
611   - // 写入redis, 超时时回复
612   - sendRtpItem.setStatus(1);
613   - sendRtpItem.setCallId(callIdHeader.getCallId());
614   - sendRtpItem.setFromTag(request.getFromTag());
615   -
616   - SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
617   - if (response != null) {
618   - sendRtpItem.setToTag(response.getToTag());
  594 + CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
  595 + int port, Boolean tcpActive, boolean mediaTransmissionTCP,
  596 + String channelId, String addressStr, String ssrc, String requesterId) {
  597 + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
  598 + if (streamReady != null && streamReady) {
  599 + // 自平台内容
  600 + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
  601 + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
  602 +
  603 + if (sendRtpItem == null) {
  604 + logger.warn("服务器端口资源不足");
  605 + try {
  606 + responseAck(request, Response.BUSY_HERE);
  607 + } catch (SipException | InvalidArgumentException | ParseException e) {
  608 + logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage());
619 609 }
620   - redisCatchStorage.updateSendRTPSever(sendRtpItem);
  610 + return;
  611 + }
  612 + if (tcpActive != null) {
  613 + sendRtpItem.setTcpActive(tcpActive);
  614 + }
  615 + sendRtpItem.setPlayType(InviteStreamType.PUSH);
  616 + // 写入redis, 超时时回复
  617 + sendRtpItem.setStatus(1);
  618 + sendRtpItem.setCallId(callIdHeader.getCallId());
  619 + sendRtpItem.setFromTag(request.getFromTag());
  620 +
  621 + SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
  622 + if (response != null) {
  623 + sendRtpItem.setToTag(response.getToTag());
  624 + }
  625 + redisCatchStorage.updateSendRTPSever(sendRtpItem);
621 626  
622 627 }
623 628  
624 629 }
  630 +
625 631 private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
626 632 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
627 633 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
... ... @@ -629,7 +635,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
629 635 // 推流
630 636 if (streamPushItem.isSelf()) {
631 637 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
632   - if (streamReady) {
  638 + if (streamReady != null && streamReady) {
633 639 // 自平台内容
634 640 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
635 641 gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
... ... @@ -661,7 +667,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
661 667  
662 668 } else {
663 669 // 不在线 拉起
664   - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  670 + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
665 671 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
666 672 }
667 673  
... ... @@ -671,6 +677,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
671 677 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
672 678 }
673 679 }
  680 +
674 681 /**
675 682 * 通知流上线
676 683 */
... ... @@ -688,7 +695,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
688 695 String stream = responseJSON.getString("stream");
689 696 logger.info("[上级点播]拉流代理已经就绪, {}/{}", app, stream);
690 697 dynamicTask.stop(callIdHeader.getCallId());
691   - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  698 + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
692 699 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
693 700 });
694 701 dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
... ... @@ -707,7 +714,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
707 714 }
708 715  
709 716  
710   -
711 717 } else if ("push".equals(gbStream.getStreamType())) {
712 718 if (!platform.isStartOfflinePush()) {
713 719 // 平台设置中关闭了拉起离线的推流则直接回复
... ... @@ -811,7 +817,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
811 817 // 发送redis消息
812 818 redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(),
813 819 streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId,
814   - channelId, mediaTransmissionTCP, platform.isRtcp(),null, responseSendItemMsg -> {
  820 + channelId, mediaTransmissionTCP, platform.isRtcp(), null, responseSendItemMsg -> {
815 821 SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem();
816 822 if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
817 823 logger.warn("服务器端口资源不足");
... ... @@ -836,7 +842,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
836 842 sendRtpItem.setCallId(callIdHeader.getCallId());
837 843  
838 844 sendRtpItem.setFromTag(request.getFromTag());
839   - SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request,sendRtpItem, platform, evt);
  845 + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request, sendRtpItem, platform, evt);
840 846 if (response != null) {
841 847 sendRtpItem.setToTag(response.getToTag());
842 848 }
... ... @@ -877,8 +883,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
877 883 content.append("t=0 0\r\n");
878 884 // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口
879 885 int localPort = sendRtpItem.getLocalPort();
880   - if(localPort == 0)
881   - {
  886 + if (localPort == 0) {
882 887 localPort = new Random().nextInt(65535) + 1;
883 888 }
884 889 content.append("m=video " + localPort + " RTP/AVP 96\r\n");
... ... @@ -953,7 +958,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
953 958 }
954 959 if (device != null) {
955 960 logger.info("收到设备" + requesterId + "的语音广播Invite请求");
956   - String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId() + broadcastCatch.getChannelId();
  961 + String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId() + broadcastCatch.getChannelId();
957 962 dynamicTask.stop(key);
958 963 try {
959 964 responseAck(request, Response.TRYING);
... ... @@ -986,7 +991,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
986 991 boolean mediaTransmissionTCP = false;
987 992 Boolean tcpActive = null;
988 993 for (int i = 0; i < mediaDescriptions.size(); i++) {
989   - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i);
  994 + MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i);
990 995 Media media = mediaDescription.getMedia();
991 996  
992 997 Vector mediaFormats = media.getMediaFormats(false);
... ... @@ -1022,7 +1027,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
1022 1027 }
1023 1028 String addressStr = sdp.getOrigin().getAddress();
1024 1029 logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, ssrc,
1025   - mediaTransmissionTCP ? (tcpActive? "TCP主动":"TCP被动") : "UDP");
  1030 + mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP");
1026 1031  
1027 1032 MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem();
1028 1033 if (mediaServerItem == null) {
... ... @@ -1036,7 +1041,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
1036 1041 return;
1037 1042 }
1038 1043 logger.info("设备{}请求语音流, 收流地址:{}:{},ssrc:{}, {}, 对讲方式:{}", requesterId, addressStr, port, ssrc,
1039   - mediaTransmissionTCP ? (tcpActive? "TCP主动":"TCP被动") : "UDP", sdp.getSessionName().getValue());
  1044 + mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP", sdp.getSessionName().getValue());
1040 1045  
1041 1046 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
1042 1047 device.getDeviceId(), broadcastCatch.getChannelId(),
... ... @@ -1076,7 +1081,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
1076 1081 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream());
1077 1082 if (streamReady) {
1078 1083 sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, ssrc);
1079   - }else {
  1084 + } else {
1080 1085 logger.warn("[语音通话], 未发现待推送的流,app={},stream={}", broadcastCatch.getApp(), broadcastCatch.getStream());
1081 1086 try {
1082 1087 responseAck(request, Response.GONE);
... ... @@ -1093,29 +1098,30 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
1093 1098 } else {
1094 1099 logger.warn("来自无效设备/平台的请求");
1095 1100 try {
1096   - responseAck(request, Response.BAD_REQUEST);; // 不支持的格式,发415
  1101 + responseAck(request, Response.BAD_REQUEST);
  1102 + ; // 不支持的格式,发415
1097 1103 } catch (SipException | InvalidArgumentException | ParseException e) {
1098 1104 logger.error("[命令发送失败] invite 来自无效设备/平台的请求, {}", e.getMessage());
1099 1105 }
1100 1106 }
1101 1107 }
1102 1108  
1103   - SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc){
  1109 + SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc) {
1104 1110 SIPResponse sipResponse = null;
1105 1111 try {
1106 1112 sendRtpItem.setStatus(2);
1107 1113 redisCatchStorage.updateSendRTPSever(sendRtpItem);
1108 1114 StringBuffer content = new StringBuffer(200);
1109 1115 content.append("v=0\r\n");
1110   - content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
  1116 + content.append("o=" + config.getId() + " " + sdp.getOrigin().getSessionId() + " " + sdp.getOrigin().getSessionVersion() + " IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
1111 1117 content.append("s=Play\r\n");
1112   - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
  1118 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
1113 1119 content.append("t=0 0\r\n");
1114 1120  
1115 1121 if (mediaTransmissionTCP) {
1116   - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n");
1117   - }else {
1118   - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n");
  1122 + content.append("m=audio " + sendRtpItem.getLocalPort() + " TCP/RTP/AVP 8\r\n");
  1123 + } else {
  1124 + content.append("m=audio " + sendRtpItem.getLocalPort() + " RTP/AVP 8\r\n");
1119 1125 }
1120 1126  
1121 1127 content.append("a=rtpmap:8 PCMA/8000/1\r\n");
... ... @@ -1125,11 +1131,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
1125 1131 content.append("a=connection:new\r\n");
1126 1132 if (!sendRtpItem.isTcpActive()) {
1127 1133 content.append("a=setup:active\r\n");
1128   - }else {
  1134 + } else {
1129 1135 content.append("a=setup:passive\r\n");
1130 1136 }
1131 1137 }
1132   - content.append("y="+ ssrc + "\r\n");
  1138 + content.append("y=" + ssrc + "\r\n");
1133 1139 content.append("f=v/////a/1/8/1\r\n");
1134 1140  
1135 1141 ParentPlatform parentPlatform = new ParentPlatform();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
  2 +
  3 +import com.genersoft.iot.vmp.conf.DynamicTask;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
  5 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  6 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  7 +import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  8 +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
  9 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
  10 +import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
  11 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  12 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
  13 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  14 +import org.dom4j.DocumentException;
  15 +import org.dom4j.Element;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.stereotype.Component;
  20 +
  21 +import javax.sip.RequestEvent;
  22 +import javax.sip.header.FromHeader;
  23 +import java.util.*;
  24 +import java.util.concurrent.ConcurrentHashMap;
  25 +import java.util.concurrent.CopyOnWriteArrayList;
  26 +
  27 +/**
  28 + * SIP命令类型: NOTIFY请求中的目录请求处理
  29 + */
  30 +@Component
  31 +public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent {
  32 +
  33 +
  34 + private final static Logger logger = LoggerFactory.getLogger(NotifyRequestForCatalogProcessor.class);
  35 +
  36 + private final List<DeviceChannel> updateChannelOnlineList = new CopyOnWriteArrayList<>();
  37 + private final List<DeviceChannel> updateChannelOfflineList = new CopyOnWriteArrayList<>();
  38 + private final Map<String, DeviceChannel> updateChannelMap = new ConcurrentHashMap<>();
  39 +
  40 + private final Map<String, DeviceChannel> addChannelMap = new ConcurrentHashMap<>();
  41 + private final List<DeviceChannel> deleteChannelList = new CopyOnWriteArrayList<>();
  42 +
  43 +
  44 + @Autowired
  45 + private UserSetting userSetting;
  46 +
  47 + @Autowired
  48 + private EventPublisher eventPublisher;
  49 +
  50 + @Autowired
  51 + private IRedisCatchStorage redisCatchStorage;
  52 +
  53 + @Autowired
  54 + private IDeviceChannelService deviceChannelService;
  55 +
  56 + @Autowired
  57 + private DynamicTask dynamicTask;
  58 +
  59 + private final static String talkKey = "notify-request-for-catalog-task";
  60 +
  61 + public void process(RequestEvent evt) {
  62 + try {
  63 + long start = System.currentTimeMillis();
  64 + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
  65 + String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
  66 +
  67 + Device device = redisCatchStorage.getDevice(deviceId);
  68 + if (device == null || device.getOnline() == 0) {
  69 + logger.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" ));
  70 + return;
  71 + }
  72 + Element rootElement = getRootElement(evt, device.getCharset());
  73 + if (rootElement == null) {
  74 + logger.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest());
  75 + return;
  76 + }
  77 + Element deviceListElement = rootElement.element("DeviceList");
  78 + if (deviceListElement == null) {
  79 + return;
  80 + }
  81 + Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
  82 + if (deviceListIterator != null) {
  83 +
  84 + // 遍历DeviceList
  85 + while (deviceListIterator.hasNext()) {
  86 + Element itemDevice = deviceListIterator.next();
  87 + Element channelDeviceElement = itemDevice.element("DeviceID");
  88 + if (channelDeviceElement == null) {
  89 + continue;
  90 + }
  91 + Element eventElement = itemDevice.element("Event");
  92 + String event;
  93 + if (eventElement == null) {
  94 + logger.warn("[收到目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" ));
  95 + event = CatalogEvent.ADD;
  96 + }else {
  97 + event = eventElement.getText().toUpperCase();
  98 + }
  99 + DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
  100 +
  101 + channel.setDeviceId(device.getDeviceId());
  102 + logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
  103 + switch (event) {
  104 + case CatalogEvent.ON:
  105 + // 上线
  106 + logger.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  107 + updateChannelOnlineList.add(channel);
  108 + if (updateChannelOnlineList.size() > 300) {
  109 + executeSaveForOnline();
  110 + }
  111 + if (userSetting.getDeviceStatusNotify()) {
  112 + // 发送redis消息
  113 + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), true);
  114 + }
  115 +
  116 + break;
  117 + case CatalogEvent.OFF :
  118 + // 离线
  119 + logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  120 + if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  121 + logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  122 + }else {
  123 + updateChannelOfflineList.add(channel);
  124 + if (updateChannelOfflineList.size() > 300) {
  125 + executeSaveForOffline();
  126 + }
  127 + if (userSetting.getDeviceStatusNotify()) {
  128 + // 发送redis消息
  129 + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false);
  130 + }
  131 + }
  132 + break;
  133 + case CatalogEvent.VLOST:
  134 + // 视频丢失
  135 + logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  136 + if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  137 + logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  138 + }else {
  139 + updateChannelOfflineList.add(channel);
  140 + if (updateChannelOfflineList.size() > 300) {
  141 + executeSaveForOffline();
  142 + }
  143 + if (userSetting.getDeviceStatusNotify()) {
  144 + // 发送redis消息
  145 + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false);
  146 + }
  147 + }
  148 + break;
  149 + case CatalogEvent.DEFECT:
  150 + // 故障
  151 + logger.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  152 + if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  153 + logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  154 + }else {
  155 + updateChannelOfflineList.add(channel);
  156 + if (updateChannelOfflineList.size() > 300) {
  157 + executeSaveForOffline();
  158 + }
  159 + if (userSetting.getDeviceStatusNotify()) {
  160 + // 发送redis消息
  161 + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false);
  162 + }
  163 + }
  164 + break;
  165 + case CatalogEvent.ADD:
  166 + // 增加
  167 + logger.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  168 + // 判断此通道是否存在
  169 + DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId());
  170 + if (deviceChannel != null) {
  171 + channel.setId(deviceChannel.getId());
  172 + updateChannelMap.put(channel.getChannelId(), channel);
  173 + if (updateChannelMap.keySet().size() > 300) {
  174 + executeSaveForUpdate();
  175 + }
  176 + }else {
  177 + addChannelMap.put(channel.getChannelId(), channel);
  178 + if (addChannelMap.keySet().size() > 300) {
  179 + executeSaveForAdd();
  180 + }
  181 + }
  182 +
  183 + break;
  184 + case CatalogEvent.DEL:
  185 + // 删除
  186 + logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  187 + deleteChannelList.add(channel);
  188 + if (deleteChannelList.size() > 300) {
  189 + executeSaveForDelete();
  190 + }
  191 + break;
  192 + case CatalogEvent.UPDATE:
  193 + // 更新
  194 + logger.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  195 + // 判断此通道是否存在
  196 + DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId());
  197 + if (deviceChannelForUpdate != null) {
  198 + channel.setId(deviceChannelForUpdate.getId());
  199 + updateChannelMap.put(channel.getChannelId(), channel);
  200 + if (updateChannelMap.keySet().size() > 300) {
  201 + executeSaveForUpdate();
  202 + }
  203 + }else {
  204 + addChannelMap.put(channel.getChannelId(), channel);
  205 + if (addChannelMap.keySet().size() > 300) {
  206 + executeSaveForAdd();
  207 + }
  208 + }
  209 + break;
  210 + default:
  211 + logger.warn("[ NotifyCatalog ] event not found : {}", event );
  212 +
  213 + }
  214 + // 转发变化信息
  215 + eventPublisher.catalogEventPublish(null, channel, event);
  216 +
  217 + if (updateChannelMap.keySet().size() > 0
  218 + || addChannelMap.keySet().size() > 0
  219 + || updateChannelOnlineList.size() > 0
  220 + || updateChannelOfflineList.size() > 0
  221 + || deleteChannelList.size() > 0) {
  222 +
  223 + if (!dynamicTask.contains(talkKey)) {
  224 + dynamicTask.startDelay(talkKey, this::executeSave, 1000);
  225 + }
  226 + }
  227 + }
  228 + }
  229 + } catch (DocumentException e) {
  230 + logger.error("未处理的异常 ", e);
  231 + }
  232 + }
  233 +
  234 + private void executeSave(){
  235 + System.out.println("定时存储数据");
  236 + executeSaveForUpdate();
  237 + executeSaveForDelete();
  238 + executeSaveForOnline();
  239 + executeSaveForOffline();
  240 + dynamicTask.stop(talkKey);
  241 + }
  242 +
  243 + private void executeSaveForUpdate(){
  244 + if (updateChannelMap.values().size() > 0) {
  245 + ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values());
  246 + updateChannelMap.clear();
  247 + deviceChannelService.batchUpdateChannel(deviceChannels);
  248 + }
  249 +
  250 + }
  251 +
  252 + private void executeSaveForAdd(){
  253 + if (addChannelMap.values().size() > 0) {
  254 + ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values());
  255 + addChannelMap.clear();
  256 + deviceChannelService.batchAddChannel(deviceChannels);
  257 + }
  258 + }
  259 +
  260 + private void executeSaveForDelete(){
  261 + if (deleteChannelList.size() > 0) {
  262 + deviceChannelService.deleteChannels(deleteChannelList);
  263 + deleteChannelList.clear();
  264 + }
  265 + }
  266 +
  267 + private void executeSaveForOnline(){
  268 + if (updateChannelOnlineList.size() > 0) {
  269 + deviceChannelService.channelsOnline(updateChannelOnlineList);
  270 + updateChannelOnlineList.clear();
  271 + }
  272 + }
  273 +
  274 + private void executeSaveForOffline(){
  275 + if (updateChannelOfflineList.size() > 0) {
  276 + deviceChannelService.channelsOffline(updateChannelOfflineList);
  277 + updateChannelOfflineList.clear();
  278 + }
  279 + }
  280 +
  281 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
... ... @@ -76,12 +76,17 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
76 76 @Autowired
77 77 private IDeviceChannelService deviceChannelService;
78 78  
  79 + @Autowired
  80 + private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor;
  81 +
79 82 private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
80 83  
81 84 @Qualifier("taskExecutor")
82 85 @Autowired
83 86 private ThreadPoolTaskExecutor taskExecutor;
84 87  
  88 + private int maxQueueCount = 30000;
  89 +
85 90 @Override
86 91 public void afterPropertiesSet() throws Exception {
87 92 // 添加消息处理的订阅
... ... @@ -91,43 +96,52 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
91 96 @Override
92 97 public void process(RequestEvent evt) {
93 98 try {
94   - responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null);
  99 +
  100 + if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) {
  101 + responseAck((SIPRequest) evt.getRequest(), Response.BUSY_HERE, null, null);
  102 + logger.error("[notify] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue());
  103 + return;
  104 + }else {
  105 + responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null);
  106 + }
  107 +
95 108 }catch (SipException | InvalidArgumentException | ParseException e) {
96 109 logger.error("未处理的异常 ", e);
97 110 }
98 111 boolean runed = !taskQueue.isEmpty();
  112 + logger.info("[notify] 待处理消息数量: {}", taskQueue.size());
99 113 taskQueue.offer(new HandlerCatchData(evt, null, null));
100 114 if (!runed) {
101 115 taskExecutor.execute(()-> {
102   - try {
103   - while (!taskQueue.isEmpty()) {
104   - try {
105   - HandlerCatchData take = taskQueue.poll();
106   - Element rootElement = getRootElement(take.getEvt());
107   - if (rootElement == null) {
108   - logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest());
109   - continue;
110   - }
111   - String cmd = XmlUtil.getText(rootElement, "CmdType");
112   -
113   - if (CmdType.CATALOG.equals(cmd)) {
114   - logger.info("接收到Catalog通知");
115   - processNotifyCatalogList(take.getEvt());
116   - } else if (CmdType.ALARM.equals(cmd)) {
117   - logger.info("接收到Alarm通知");
118   - processNotifyAlarm(take.getEvt());
119   - } else if (CmdType.MOBILE_POSITION.equals(cmd)) {
120   - logger.info("接收到MobilePosition通知");
121   - processNotifyMobilePosition(take.getEvt());
122   - } else {
123   - logger.info("接收到消息:" + cmd);
124   - }
125   - } catch (DocumentException e) {
126   - logger.error("处理NOTIFY消息时错误", e);
  116 + while (!taskQueue.isEmpty()) {
  117 + try {
  118 + HandlerCatchData take = taskQueue.poll();
  119 + if (take == null) {
  120 + continue;
  121 + }
  122 + Element rootElement = getRootElement(take.getEvt());
  123 + if (rootElement == null) {
  124 + logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest());
  125 + continue;
  126 + }
  127 + String cmd = XmlUtil.getText(rootElement, "CmdType");
  128 +
  129 + if (CmdType.CATALOG.equals(cmd)) {
  130 + logger.info("接收到Catalog通知");
  131 +// processNotifyCatalogList(take.getEvt());
  132 + notifyRequestForCatalogProcessor.process(take.getEvt());
  133 + } else if (CmdType.ALARM.equals(cmd)) {
  134 + logger.info("接收到Alarm通知");
  135 + processNotifyAlarm(take.getEvt());
  136 + } else if (CmdType.MOBILE_POSITION.equals(cmd)) {
  137 + logger.info("接收到MobilePosition通知");
  138 + processNotifyMobilePosition(take.getEvt());
  139 + } else {
  140 + logger.info("接收到消息:" + cmd);
127 141 }
  142 + } catch (DocumentException e) {
  143 + logger.error("处理NOTIFY消息时错误", e);
128 144 }
129   - }catch (Exception e) {
130   - logger.error("处理NOTIFY消息时错误", e);
131 145 }
132 146 });
133 147 }
... ... @@ -135,7 +149,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
135 149  
136 150 /**
137 151 * 处理MobilePosition移动位置Notify
138   - *
  152 + *
139 153 * @param evt
140 154 */
141 155 private void processNotifyMobilePosition(RequestEvent evt) {
... ... @@ -239,7 +253,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
239 253  
240 254 /***
241 255 * 处理alarm设备报警Notify
242   - *
  256 + *
243 257 * @param evt
244 258 */
245 259 private void processNotifyAlarm(RequestEvent evt) {
... ... @@ -349,7 +363,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
349 363  
350 364 /***
351 365 * 处理catalog设备目录列表Notify
352   - *
  366 + *
353 367 * @param evt
354 368 */
355 369 private void processNotifyCatalogList(RequestEvent evt) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
... ... @@ -83,21 +83,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
83 83 public void process(RequestEvent evt) {
84 84 try {
85 85 RequestEventExt evtExt = (RequestEventExt) evt;
86   - String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
87   -
88   -// MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
89   -// QueryExp protocol = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"));
90   -//// ObjectName name = new ObjectName("*:type=Connector,*");
91   -// ObjectName name = new ObjectName("*:*");
92   -// Set<ObjectName> objectNames = beanServer.queryNames(name, protocol);
93   -// for (ObjectName objectName : objectNames) {
94   -// String catalina = objectName.getDomain();
95   -// if ("Catalina".equals(catalina)) {
96   -// System.out.println(objectName.getKeyProperty("port"));
97   -// }
98   -// }
99   -
100   -// System.out.println(ServiceInfo.getServerPort());
  86 +
101 87 SIPRequest request = (SIPRequest)evt.getRequest();
102 88 Response response = null;
103 89 boolean passwordCorrect = false;
... ... @@ -107,12 +93,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
107 93 AddressImpl address = (AddressImpl) fromHeader.getAddress();
108 94 SipUri uri = (SipUri) address.getURI();
109 95 String deviceId = uri.getUser();
110   - logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress);
  96 +
111 97 Device device = deviceService.getDevice(deviceId);
112 98  
113 99 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
114 100 userSetting.getSipUseSourceIpAsRemoteAddress());
115   -
  101 + String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort();
  102 + logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress);
116 103 if (device != null &&
117 104 device.getSipTransactionInfo() != null &&
118 105 request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info;
2 2  
3   -import com.genersoft.iot.vmp.common.StreamInfo;
  3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 7 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
... ... @@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
9 10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
10 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
11 12 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
  13 +import com.genersoft.iot.vmp.service.IInviteStreamService;
12 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
13 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 16 import gov.nist.javax.sip.message.SIPRequest;
... ... @@ -17,10 +19,12 @@ import org.slf4j.LoggerFactory;
17 19 import org.springframework.beans.factory.InitializingBean;
18 20 import org.springframework.beans.factory.annotation.Autowired;
19 21 import org.springframework.stereotype.Component;
  22 +
20 23 import javax.sip.InvalidArgumentException;
21 24 import javax.sip.RequestEvent;
22 25 import javax.sip.SipException;
23   -import javax.sip.header.*;
  26 +import javax.sip.header.CallIdHeader;
  27 +import javax.sip.header.ContentTypeHeader;
24 28 import javax.sip.message.Response;
25 29 import java.text.ParseException;
26 30  
... ... @@ -44,6 +48,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
44 48 private IRedisCatchStorage redisCatchStorage;
45 49  
46 50 @Autowired
  51 + private IInviteStreamService inviteStreamService;
  52 +
  53 + @Autowired
47 54 private IVideoManagerStorage storager;
48 55  
49 56 @Autowired
... ... @@ -103,27 +110,30 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
103 110 if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) {
104 111 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId());
105 112 String streamId = sendRtpItem.getStream();
106   - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
107   - if (null == streamInfo) {
  113 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  114 + if (null == inviteInfo) {
108 115 responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found");
109 116 return;
110 117 }
111   - Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID());
112   - cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> {
113   - // 失败的回复
114   - try {
115   - responseAck(request, eventResult.statusCode, eventResult.msg);
116   - } catch (SipException | InvalidArgumentException | ParseException e) {
117   - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
118   - }
119   - }, eventResult -> {
120   - // 成功的回复
121   - try {
122   - responseAck(request, eventResult.statusCode);
123   - } catch (SipException | InvalidArgumentException | ParseException e) {
124   - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
125   - }
126   - });
  118 + Device device1 = storager.queryVideoDevice(inviteInfo.getDeviceId());
  119 + if (inviteInfo.getStreamInfo() != null) {
  120 + cmder.playbackControlCmd(device1,inviteInfo.getStreamInfo(),new String(evt.getRequest().getRawContent()),eventResult -> {
  121 + // 失败的回复
  122 + try {
  123 + responseAck(request, eventResult.statusCode, eventResult.msg);
  124 + } catch (SipException | InvalidArgumentException | ParseException e) {
  125 + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
  126 + }
  127 + }, eventResult -> {
  128 + // 成功的回复
  129 + try {
  130 + responseAck(request, eventResult.statusCode);
  131 + } catch (SipException | InvalidArgumentException | ParseException e) {
  132 + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
  133 + }
  134 + });
  135 + }
  136 +
127 137 }
128 138 }
129 139 } catch (SipException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -69,6 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
69 69  
70 70 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
71 71 if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
  72 + logger.info("[心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
72 73 device.setPort(remoteAddressInfo.getPort());
73 74 device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
74 75 device.setIp(remoteAddressInfo.getIp());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
2 2  
3   -import com.genersoft.iot.vmp.common.StreamInfo;
  3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 5 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
... ... @@ -12,6 +13,10 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
12 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
13 14 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
14 15 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
  16 +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
  17 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
  18 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
  19 +import com.genersoft.iot.vmp.service.IInviteStreamService;
15 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
17 22 import gov.nist.javax.sip.message.SIPRequest;
... ... @@ -58,6 +63,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
58 63 @Autowired
59 64 private VideoStreamSessionManager sessionManager;
60 65  
  66 + @Autowired
  67 + private ZlmHttpHookSubscribe subscribe;
  68 +
  69 + @Autowired
  70 + private IInviteStreamService inviteStreamService;
  71 +
  72 + @Autowired
  73 + private VideoStreamSessionManager streamSession;
  74 +
61 75 @Override
62 76 public void afterPropertiesSet() throws Exception {
63 77 notifyMessageHandler.addHandler(cmdType, this);
... ... @@ -76,23 +90,24 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
76 90 String NotifyType =getText(rootElement, "NotifyType");
77 91 if ("121".equals(NotifyType)){
78 92 logger.info("[录像流]推送完毕,收到关流通知");
79   - // 查询是设备
80   - StreamInfo streamInfo = redisCatchStorage.queryDownload(null, null, null, callIdHeader.getCallId());
81   - if (streamInfo != null) {
82   - // 设置进度100%
83   - streamInfo.setProgress(1);
84   - redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId());
85   - }
86 93  
87   - // 先从会话内查找
88   - SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
89   - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
  94 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
  95 + if (ssrcTransaction != null) {
  96 + logger.info("[录像流]推送完毕,关流通知, device: {}, channelId: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
  97 + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
  98 + if (inviteInfo.getStreamInfo() != null) {
  99 + inviteInfo.getStreamInfo().setProgress(1);
  100 + inviteStreamService.updateInviteInfo(inviteInfo);
  101 + }
90 102  
91 103 try {
92 104 cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
93 105 } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
94 106 logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage());
95 107 }
  108 + // 去除监听流注销自动停止下载的监听
  109 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcTransaction.getStream(), false, "rtsp", ssrcTransaction.getMediaServerId());
  110 + subscribe.removeSubscribe(hookSubscribe);
96 111  
97 112 // 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定
98 113 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null);
... ... @@ -108,6 +123,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
108 123 logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
109 124 }
110 125 }
  126 + }else {
  127 + logger.info("[录像流]推送完毕,关流通知, 但是未找到对应的下载信息");
111 128 }
112 129 }
113 130 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
... ... @@ -18,6 +18,10 @@ import javax.sdp.SessionDescription;
18 18 import javax.sip.InvalidArgumentException;
19 19 import javax.sip.ResponseEvent;
20 20 import javax.sip.SipException;
  21 +import javax.sip.InvalidArgumentException;
  22 +import javax.sip.ResponseEvent;
  23 +import javax.sip.SipException;
  24 +import javax.sip.SipFactory;
21 25 import javax.sip.address.SipURI;
22 26 import javax.sip.message.Request;
23 27 import javax.sip.message.Response;
... ... @@ -91,7 +95,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
91 95 }
92 96 // 查看是否是来自设备的,此是回复
93 97  
94   - SipURI requestUri = sipLayer.getSipFactory().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
  98 + SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
95 99 Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);
96 100  
97 101 logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
... ... @@ -54,7 +54,7 @@ public class SipUtils {
54 54 return "z9hG4bK" + System.currentTimeMillis();
55 55 }
56 56  
57   - public static UserAgentHeader createUserAgentHeader(SipFactory sipFactory, GitUtil gitUtil) throws PeerUnavailableException, ParseException {
  57 + public static UserAgentHeader createUserAgentHeader(GitUtil gitUtil) throws PeerUnavailableException, ParseException {
58 58 List<String> agentParam = new ArrayList<>();
59 59 agentParam.add("WVP-Pro ");
60 60 if (gitUtil != null ) {
... ... @@ -66,7 +66,7 @@ public class SipUtils {
66 66 agentParam.add(gitUtil.getCommitTime());
67 67 }
68 68 }
69   - return sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
  69 + return SipFactory.getInstance().createHeaderFactory().createUserAgentHeader(agentParam);
70 70 }
71 71  
72 72 public static String getNewFromTag(){
... ... @@ -153,8 +153,9 @@ public class SipUtils {
153 153 String remoteAddress;
154 154 int remotePort;
155 155 if (sipUseSourceIpAsRemoteAddress) {
156   - remoteAddress = request.getRemoteAddress().getHostAddress();
157   - remotePort = request.getRemotePort();
  156 + remoteAddress = request.getPeerPacketSourceAddress().getHostAddress();
  157 + remotePort = request.getPeerPacketSourcePort();
  158 +
158 159 }else {
159 160 // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息
160 161 // 获取到通信地址等信息
... ... @@ -162,8 +163,8 @@ public class SipUtils {
162 163 remotePort = request.getTopmostViaHeader().getRPort();
163 164 // 解析本地地址替代
164 165 if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) {
165   - remoteAddress = request.getTopmostViaHeader().getHost();
166   - remotePort = request.getTopmostViaHeader().getPort();
  166 + remoteAddress = request.getPeerPacketSourceAddress().getHostAddress();
  167 + remotePort = request.getPeerPacketSourcePort();
167 168 }
168 169 }
169 170  
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/annotation/MsgId.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.annotation;
  2 +
  3 +import java.lang.annotation.*;
  4 +
  5 +/**
  6 + * @author QingtaiJiang
  7 + * @date 2023/4/27 18:31
  8 + * @email qingtaij@163.com
  9 + */
  10 +@Target(ElementType.TYPE)
  11 +@Retention(RetentionPolicy.RUNTIME)
  12 +@Documented
  13 +public @interface MsgId {
  14 + String id();
  15 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/cmd/JT1078Template.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.cmd;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.proc.entity.Cmd;
  4 +import com.genersoft.iot.vmp.jt1078.proc.response.*;
  5 +import com.genersoft.iot.vmp.jt1078.session.SessionManager;
  6 +
  7 +import java.util.Random;
  8 +
  9 +/**
  10 + * @author QingtaiJiang
  11 + * @date 2023/4/27 18:58
  12 + * @email qingtaij@163.com
  13 + */
  14 +public class JT1078Template {
  15 +
  16 + private final Random random = new Random();
  17 +
  18 + private static final String H9101 = "9101";
  19 + private static final String H9102 = "9102";
  20 + private static final String H9201 = "9201";
  21 + private static final String H9202 = "9202";
  22 + private static final String H9205 = "9205";
  23 +
  24 + private static final String H0001 = "0001";
  25 + private static final String H1205 = "1205";
  26 +
  27 + /**
  28 + * 开启直播视频
  29 + *
  30 + * @param devId 设备号
  31 + * @param j9101 开启视频参数
  32 + */
  33 + public String startLive(String devId, J9101 j9101, Integer timeOut) {
  34 + Cmd cmd = new Cmd.Builder()
  35 + .setDevId(devId)
  36 + .setPackageNo(randomInt())
  37 + .setMsgId(H9101)
  38 + .setRespId(H0001)
  39 + .setRs(j9101)
  40 + .build();
  41 + return SessionManager.INSTANCE.request(cmd, timeOut);
  42 + }
  43 +
  44 + /**
  45 + * 关闭直播视频
  46 + *
  47 + * @param devId 设备号
  48 + * @param j9102 关闭视频参数
  49 + */
  50 + public String stopLive(String devId, J9102 j9102, Integer timeOut) {
  51 + Cmd cmd = new Cmd.Builder()
  52 + .setDevId(devId)
  53 + .setPackageNo(randomInt())
  54 + .setMsgId(H9102)
  55 + .setRespId(H0001)
  56 + .setRs(j9102)
  57 + .build();
  58 + return SessionManager.INSTANCE.request(cmd, timeOut);
  59 + }
  60 +
  61 + /**
  62 + * 查询音视频列表
  63 + *
  64 + * @param devId 设备号
  65 + * @param j9205 查询音视频列表
  66 + */
  67 + public String queryBackTime(String devId, J9205 j9205, Integer timeOut) {
  68 + Cmd cmd = new Cmd.Builder()
  69 + .setDevId(devId)
  70 + .setPackageNo(randomInt())
  71 + .setMsgId(H9205)
  72 + .setRespId(H1205)
  73 + .setRs(j9205)
  74 + .build();
  75 + return SessionManager.INSTANCE.request(cmd, timeOut);
  76 + }
  77 +
  78 + /**
  79 + * 开启视频回放
  80 + *
  81 + * @param devId 设备号
  82 + * @param j9201 视频回放参数
  83 + */
  84 + public String startBackLive(String devId, J9201 j9201, Integer timeOut) {
  85 + Cmd cmd = new Cmd.Builder()
  86 + .setDevId(devId)
  87 + .setPackageNo(randomInt())
  88 + .setMsgId(H9201)
  89 + .setRespId(H1205)
  90 + .setRs(j9201)
  91 + .build();
  92 + return SessionManager.INSTANCE.request(cmd, timeOut);
  93 + }
  94 +
  95 + /**
  96 + * 视频回放控制
  97 + *
  98 + * @param devId 设备号
  99 + * @param j9202 控制视频回放参数
  100 + */
  101 + public String controlBackLive(String devId, J9202 j9202, Integer timeOut) {
  102 + Cmd cmd = new Cmd.Builder()
  103 + .setDevId(devId)
  104 + .setPackageNo(randomInt())
  105 + .setMsgId(H9202)
  106 + .setRespId(H0001)
  107 + .setRs(j9202)
  108 + .build();
  109 + return SessionManager.INSTANCE.request(cmd, timeOut);
  110 + }
  111 +
  112 + private Long randomInt() {
  113 + return (long) random.nextInt(1000) + 1;
  114 + }
  115 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/codec/decode/Jt808Decoder.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.codec.decode;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.proc.Header;
  4 +import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory;
  5 +import com.genersoft.iot.vmp.jt1078.proc.request.Re;
  6 +import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
  7 +import com.genersoft.iot.vmp.jt1078.session.Session;
  8 +import io.netty.buffer.ByteBuf;
  9 +import io.netty.buffer.ByteBufUtil;
  10 +import io.netty.buffer.CompositeByteBuf;
  11 +import io.netty.buffer.UnpooledByteBufAllocator;
  12 +import io.netty.channel.ChannelHandlerContext;
  13 +import io.netty.handler.codec.ByteToMessageDecoder;
  14 +import org.slf4j.Logger;
  15 +import org.slf4j.LoggerFactory;
  16 +
  17 +import java.util.ArrayList;
  18 +import java.util.List;
  19 +
  20 +/**
  21 + * @author QingtaiJiang
  22 + * @date 2023/4/27 18:10
  23 + * @email qingtaij@163.com
  24 + */
  25 +public class Jt808Decoder extends ByteToMessageDecoder {
  26 + private final static Logger log = LoggerFactory.getLogger(Jt808Decoder.class);
  27 +
  28 + @Override
  29 + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
  30 + Session session = ctx.channel().attr(Session.KEY).get();
  31 + log.info("> {} hex:{}", session, ByteBufUtil.hexDump(in));
  32 +
  33 + try {
  34 + ByteBuf buf = unEscapeAndCheck(in);
  35 +
  36 + Header header = new Header();
  37 + header.setMsgId(ByteBufUtil.hexDump(buf.readSlice(2)));
  38 + header.setMsgPro(buf.readUnsignedShort());
  39 + if (header.is2019Version()) {
  40 + header.setVersion(buf.readUnsignedByte());
  41 + String devId = ByteBufUtil.hexDump(buf.readSlice(10));
  42 + header.setDevId(devId.replaceFirst("^0*", ""));
  43 + } else {
  44 + header.setDevId(ByteBufUtil.hexDump(buf.readSlice(6)).replaceFirst("^0*", ""));
  45 + }
  46 + header.setSn(buf.readUnsignedShort());
  47 +
  48 + Re handler = CodecFactory.getHandler(header.getMsgId());
  49 + if (handler == null) {
  50 + log.error("get msgId is null {}", header.getMsgId());
  51 + return;
  52 + }
  53 + Rs decode = handler.decode(buf, header, session);
  54 + if (decode != null) {
  55 + out.add(decode);
  56 + }
  57 + } finally {
  58 + in.skipBytes(in.readableBytes());
  59 + }
  60 +
  61 +
  62 + }
  63 +
  64 +
  65 + /**
  66 + * 转义与验证校验码
  67 + *
  68 + * @param byteBuf 转义Buf
  69 + * @return 转义好的数据
  70 + */
  71 + public ByteBuf unEscapeAndCheck(ByteBuf byteBuf) throws Exception {
  72 + int low = byteBuf.readerIndex();
  73 + int high = byteBuf.writerIndex();
  74 + byte checkSum = 0;
  75 + int calculationCheckSum = 0;
  76 +
  77 + byte aByte = byteBuf.getByte(high - 2);
  78 + byte protocolEscapeFlag7d = 0x7d;
  79 + //0x7d转义
  80 + byte protocolEscapeFlag01 = 0x01;
  81 + //0x7e转义
  82 + byte protocolEscapeFlag02 = 0x02;
  83 + if (aByte == protocolEscapeFlag7d) {
  84 + byte b2 = byteBuf.getByte(high - 1);
  85 + if (b2 == protocolEscapeFlag01) {
  86 + checkSum = protocolEscapeFlag7d;
  87 + } else if (b2 == protocolEscapeFlag02) {
  88 + checkSum = 0x7e;
  89 + } else {
  90 + log.error("转义1异常:{}", ByteBufUtil.hexDump(byteBuf));
  91 + throw new Exception("转义错误");
  92 + }
  93 + high = high - 2;
  94 + } else {
  95 + high = high - 1;
  96 + checkSum = byteBuf.getByte(high);
  97 + }
  98 + List<ByteBuf> bufList = new ArrayList<>();
  99 + int index = low;
  100 + while (index < high) {
  101 + byte b = byteBuf.getByte(index);
  102 + if (b == protocolEscapeFlag7d) {
  103 + byte c = byteBuf.getByte(index + 1);
  104 + if (c == protocolEscapeFlag01) {
  105 + ByteBuf slice = slice0x01(byteBuf, low, index);
  106 + bufList.add(slice);
  107 + b = protocolEscapeFlag7d;
  108 + } else if (c == protocolEscapeFlag02) {
  109 + ByteBuf slice = slice0x02(byteBuf, low, index);
  110 + bufList.add(slice);
  111 + b = 0x7e;
  112 + } else {
  113 + log.error("转义2异常:{}", ByteBufUtil.hexDump(byteBuf));
  114 + throw new Exception("转义错误");
  115 + }
  116 + index += 2;
  117 + low = index;
  118 + } else {
  119 + index += 1;
  120 + }
  121 + calculationCheckSum = calculationCheckSum ^ b;
  122 + }
  123 +
  124 + if (calculationCheckSum == checkSum) {
  125 + if (bufList.size() == 0) {
  126 + return byteBuf.slice(low, high);
  127 + } else {
  128 + bufList.add(byteBuf.slice(low, high - low));
  129 + return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, bufList.size(), bufList);
  130 + }
  131 + } else {
  132 + log.info("{} 解析校验码:{}--计算校验码:{}", ByteBufUtil.hexDump(byteBuf), checkSum, calculationCheckSum);
  133 + throw new Exception("校验码错误!");
  134 + }
  135 + }
  136 +
  137 +
  138 + private ByteBuf slice0x01(ByteBuf buf, int low, int sign) {
  139 + return buf.slice(low, sign - low + 1);
  140 + }
  141 +
  142 + private ByteBuf slice0x02(ByteBuf buf, int low, int sign) {
  143 + buf.setByte(sign, 0x7e);
  144 + return buf.slice(low, sign - low + 1);
  145 + }
  146 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/codec/encode/Jt808Encoder.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.codec.encode;
  2 +
  3 +
  4 +import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
  5 +import com.genersoft.iot.vmp.jt1078.session.Session;
  6 +import io.netty.buffer.ByteBuf;
  7 +import io.netty.buffer.ByteBufUtil;
  8 +import io.netty.channel.ChannelHandlerContext;
  9 +import io.netty.handler.codec.MessageToByteEncoder;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +
  13 +/**
  14 + * @author QingtaiJiang
  15 + * @date 2023/4/27 18:10
  16 + * @email qingtaij@163.com
  17 + */
  18 +public class Jt808Encoder extends MessageToByteEncoder<Rs> {
  19 + private final static Logger log = LoggerFactory.getLogger(Jt808Encoder.class);
  20 +
  21 + @Override
  22 + protected void encode(ChannelHandlerContext ctx, Rs msg, ByteBuf out) throws Exception {
  23 + Session session = ctx.channel().attr(Session.KEY).get();
  24 +
  25 + ByteBuf encode = Jt808EncoderCmd.encode(msg, session, session.nextSerialNo());
  26 + if(encode!=null){
  27 + log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode));
  28 + out.writeBytes(encode);
  29 + }
  30 + }
  31 +
  32 +
  33 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/codec/encode/Jt808EncoderCmd.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.codec.encode;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
  4 +import com.genersoft.iot.vmp.jt1078.proc.Header;
  5 +import com.genersoft.iot.vmp.jt1078.proc.entity.Cmd;
  6 +import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
  7 +import com.genersoft.iot.vmp.jt1078.session.Session;
  8 +import com.genersoft.iot.vmp.jt1078.util.Bin;
  9 +import io.netty.buffer.ByteBuf;
  10 +import io.netty.buffer.ByteBufUtil;
  11 +import io.netty.buffer.CompositeByteBuf;
  12 +import io.netty.buffer.Unpooled;
  13 +import io.netty.channel.ChannelHandlerContext;
  14 +import io.netty.handler.codec.MessageToByteEncoder;
  15 +import io.netty.util.ByteProcessor;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
  18 +import org.springframework.util.StringUtils;
  19 +
  20 +import java.util.LinkedList;
  21 +
  22 +/**
  23 + * @author QingtaiJiang
  24 + * @date 2023/4/27 18:25
  25 + * @email qingtaij@163.com
  26 + */
  27 +public class Jt808EncoderCmd extends MessageToByteEncoder<Cmd> {
  28 + private final static Logger log = LoggerFactory.getLogger(Jt808EncoderCmd.class);
  29 +
  30 + @Override
  31 + protected void encode(ChannelHandlerContext ctx, Cmd cmd, ByteBuf out) throws Exception {
  32 + Session session = ctx.channel().attr(Session.KEY).get();
  33 + Rs msg = cmd.getRs();
  34 + ByteBuf encode = encode(msg, session, cmd.getPackageNo().intValue());
  35 + if (encode != null) {
  36 + log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode));
  37 + out.writeBytes(encode);
  38 + }
  39 + }
  40 +
  41 +
  42 + public static ByteBuf encode(Rs msg, Session session, Integer packageNo) {
  43 + String id = msg.getClass().getAnnotation(MsgId.class).id();
  44 + if (!StringUtils.hasLength(id)) {
  45 + log.error("Not find msgId");
  46 + return null;
  47 + }
  48 +
  49 + ByteBuf byteBuf = Unpooled.buffer();
  50 +
  51 + byteBuf.writeBytes(ByteBufUtil.decodeHexDump(id));
  52 +
  53 + ByteBuf encode = msg.encode();
  54 +
  55 + Header header = msg.getHeader();
  56 + if (header == null) {
  57 + header = session.getHeader();
  58 + }
  59 +
  60 + if (header.is2019Version()) {
  61 + // 消息体属性
  62 + byteBuf.writeShort(encode.readableBytes() | 1 << 14);
  63 +
  64 + // 版本号
  65 + byteBuf.writeByte(header.getVersion());
  66 +
  67 + // 终端手机号
  68 + byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 20)));
  69 + } else {
  70 + // 消息体属性
  71 + byteBuf.writeShort(encode.readableBytes());
  72 +
  73 + byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 12)));
  74 + }
  75 +
  76 + // 消息体流水号
  77 + byteBuf.writeShort(packageNo);
  78 +
  79 + // 写入消息体
  80 + byteBuf.writeBytes(encode);
  81 +
  82 + // 计算校验码,并反转义
  83 + byteBuf = escapeAndCheck0(byteBuf);
  84 + return byteBuf;
  85 + }
  86 +
  87 +
  88 + private static final ByteProcessor searcher = value -> !(value == 0x7d || value == 0x7e);
  89 +
  90 + //转义与校验
  91 + public static ByteBuf escapeAndCheck0(ByteBuf source) {
  92 +
  93 + sign(source);
  94 +
  95 + int low = source.readerIndex();
  96 + int high = source.writerIndex();
  97 +
  98 + LinkedList<ByteBuf> bufList = new LinkedList<>();
  99 + int mark, len;
  100 + while ((mark = source.forEachByte(low, high - low, searcher)) > 0) {
  101 +
  102 + len = mark + 1 - low;
  103 + ByteBuf[] slice = slice(source, low, len);
  104 + bufList.add(slice[0]);
  105 + bufList.add(slice[1]);
  106 + low += len;
  107 + }
  108 +
  109 + if (bufList.size() > 0) {
  110 + bufList.add(source.slice(low, high - low));
  111 + } else {
  112 + bufList.add(source);
  113 + }
  114 +
  115 + ByteBuf delimiter = Unpooled.buffer(1, 1).writeByte(0x7e).retain();
  116 + bufList.addFirst(delimiter);
  117 + bufList.addLast(delimiter);
  118 +
  119 + CompositeByteBuf byteBufLs = Unpooled.compositeBuffer(bufList.size());
  120 + byteBufLs.addComponents(true, bufList);
  121 + return byteBufLs;
  122 + }
  123 +
  124 + public static void sign(ByteBuf buf) {
  125 + byte checkCode = bcc(buf);
  126 + buf.writeByte(checkCode);
  127 + }
  128 +
  129 + public static byte bcc(ByteBuf byteBuf) {
  130 + byte cs = 0;
  131 + while (byteBuf.isReadable())
  132 + cs ^= byteBuf.readByte();
  133 + byteBuf.resetReaderIndex();
  134 + return cs;
  135 + }
  136 +
  137 + protected static ByteBuf[] slice(ByteBuf byteBuf, int index, int length) {
  138 + byte first = byteBuf.getByte(index + length - 1);
  139 +
  140 + ByteBuf[] byteBufList = new ByteBuf[2];
  141 + byteBufList[0] = byteBuf.retainedSlice(index, length);
  142 +
  143 + if (first == 0x7d) {
  144 + byteBufList[1] = Unpooled.buffer(1, 1).writeByte(0x01);
  145 + } else {
  146 + byteBuf.setByte(index + length - 1, 0x7d);
  147 + byteBufList[1] = Unpooled.buffer(1, 1).writeByte(0x02);
  148 + }
  149 + return byteBufList;
  150 + }
  151 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/codec/netty/Jt808Handler.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.codec.netty;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
  4 +import com.genersoft.iot.vmp.jt1078.session.Session;
  5 +import com.genersoft.iot.vmp.jt1078.session.SessionManager;
  6 +import io.netty.channel.Channel;
  7 +import io.netty.channel.ChannelHandlerContext;
  8 +import io.netty.channel.ChannelInboundHandlerAdapter;
  9 +import io.netty.handler.timeout.IdleState;
  10 +import io.netty.handler.timeout.IdleStateEvent;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +
  14 +/**
  15 + * @author QingtaiJiang
  16 + * @date 2023/4/27 18:14
  17 + * @email qingtaij@163.com
  18 + */
  19 +public class Jt808Handler extends ChannelInboundHandlerAdapter {
  20 +
  21 + private final static Logger log = LoggerFactory.getLogger(Jt808Handler.class);
  22 +
  23 + @Override
  24 + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  25 + if (msg instanceof Rs) {
  26 + ctx.writeAndFlush(msg);
  27 + } else {
  28 + ctx.fireChannelRead(msg);
  29 + }
  30 + }
  31 +
  32 + @Override
  33 + public void channelActive(ChannelHandlerContext ctx) {
  34 + Channel channel = ctx.channel();
  35 + Session session = SessionManager.INSTANCE.newSession(channel);
  36 + channel.attr(Session.KEY).set(session);
  37 + log.info("> Tcp connect {}", session);
  38 + }
  39 +
  40 + @Override
  41 + public void channelInactive(ChannelHandlerContext ctx) {
  42 + Session session = ctx.channel().attr(Session.KEY).get();
  43 + log.info("< Tcp disconnect {}", session);
  44 + ctx.close();
  45 + }
  46 +
  47 + @Override
  48 + public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
  49 + Session session = ctx.channel().attr(Session.KEY).get();
  50 + String message = e.getMessage();
  51 + if (message.toLowerCase().contains("Connection reset by peer".toLowerCase())) {
  52 + log.info("< exception{} {}", session, e.getMessage());
  53 + } else {
  54 + log.info("< exception{} {}", session, e.getMessage(), e);
  55 + }
  56 +
  57 + }
  58 +
  59 + @Override
  60 + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
  61 + if (evt instanceof IdleStateEvent) {
  62 + IdleStateEvent event = (IdleStateEvent) evt;
  63 + IdleState state = event.state();
  64 + if (state == IdleState.READER_IDLE || state == IdleState.WRITER_IDLE) {
  65 + Session session = ctx.channel().attr(Session.KEY).get();
  66 + log.warn("< Proactively disconnect{}", session);
  67 + ctx.close();
  68 + }
  69 + }
  70 + }
  71 +
  72 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/codec/netty/TcpServer.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.codec.netty;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.codec.decode.Jt808Decoder;
  4 +import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808Encoder;
  5 +import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808EncoderCmd;
  6 +import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory;
  7 +import io.netty.bootstrap.ServerBootstrap;
  8 +import io.netty.buffer.ByteBuf;
  9 +import io.netty.buffer.Unpooled;
  10 +import io.netty.channel.ChannelFuture;
  11 +import io.netty.channel.ChannelInitializer;
  12 +import io.netty.channel.EventLoopGroup;
  13 +import io.netty.channel.nio.NioEventLoopGroup;
  14 +import io.netty.channel.socket.nio.NioChannelOption;
  15 +import io.netty.channel.socket.nio.NioServerSocketChannel;
  16 +import io.netty.channel.socket.nio.NioSocketChannel;
  17 +import io.netty.handler.codec.DelimiterBasedFrameDecoder;
  18 +import io.netty.handler.timeout.IdleStateHandler;
  19 +import io.netty.util.concurrent.Future;
  20 +import org.slf4j.Logger;
  21 +import org.slf4j.LoggerFactory;
  22 +
  23 +import java.util.concurrent.TimeUnit;
  24 +
  25 +/**
  26 + * @author QingtaiJiang
  27 + * @date 2023/4/27 18:01
  28 + * @email qingtaij@163.com
  29 + */
  30 +
  31 +public class TcpServer {
  32 + private final static Logger log = LoggerFactory.getLogger(TcpServer.class);
  33 +
  34 + private final Integer port;
  35 + private boolean isRunning = false;
  36 + private EventLoopGroup bossGroup = null;
  37 + private EventLoopGroup workerGroup = null;
  38 +
  39 + private final ByteBuf DECODER_JT808 = Unpooled.wrappedBuffer(new byte[]{0x7e});
  40 +
  41 + public TcpServer(Integer port) {
  42 + this.port = port;
  43 + }
  44 +
  45 + private void startTcpServer() {
  46 + try {
  47 + CodecFactory.init();
  48 + this.bossGroup = new NioEventLoopGroup();
  49 + this.workerGroup = new NioEventLoopGroup();
  50 + ServerBootstrap bootstrap = new ServerBootstrap();
  51 + bootstrap.channel(NioServerSocketChannel.class);
  52 + bootstrap.group(bossGroup, workerGroup);
  53 +
  54 + bootstrap.option(NioChannelOption.SO_BACKLOG, 1024)
  55 + .option(NioChannelOption.SO_REUSEADDR, true)
  56 + .childOption(NioChannelOption.TCP_NODELAY, true)
  57 + .childHandler(new ChannelInitializer<NioSocketChannel>() {
  58 + @Override
  59 + public void initChannel(NioSocketChannel channel) {
  60 + channel.pipeline()
  61 + .addLast(new IdleStateHandler(10, 0, 0, TimeUnit.MINUTES))
  62 + .addLast(new DelimiterBasedFrameDecoder(1024 * 2, DECODER_JT808))
  63 + .addLast(new Jt808Decoder())
  64 + .addLast(new Jt808Encoder())
  65 + .addLast(new Jt808EncoderCmd())
  66 + .addLast(new Jt808Handler());
  67 + }
  68 + });
  69 + ChannelFuture channelFuture = bootstrap.bind(port).sync();
  70 + // 监听设备TCP端口是否启动成功
  71 + channelFuture.addListener(future -> {
  72 + if (!future.isSuccess()) {
  73 + log.error("Binding port:{} fail! cause: {}", port, future.cause().getCause(), future.cause());
  74 + }
  75 + });
  76 + log.info("服务:JT808 Server 启动成功, port:{}", port);
  77 + channelFuture.channel().closeFuture().sync();
  78 + } catch (Exception e) {
  79 + log.warn("服务:JT808 Server 启动异常, port:{},{}", port, e.getMessage(), e);
  80 + } finally {
  81 + stop();
  82 + }
  83 + }
  84 +
  85 + /**
  86 + * 开启一个新的线程,拉起来Netty
  87 + */
  88 + public synchronized void start() {
  89 + if (this.isRunning) {
  90 + log.warn("服务:JT808 Server 已经启动, port:{}", port);
  91 + return;
  92 + }
  93 + this.isRunning = true;
  94 + new Thread(this::startTcpServer).start();
  95 + }
  96 +
  97 + public synchronized void stop() {
  98 + if (!this.isRunning) {
  99 + log.warn("服务:JT808 Server 已经停止, port:{}", port);
  100 + }
  101 + this.isRunning = false;
  102 + Future<?> future = this.bossGroup.shutdownGracefully();
  103 + if (!future.isSuccess()) {
  104 + log.warn("bossGroup 无法正常停止", future.cause());
  105 + }
  106 + future = this.workerGroup.shutdownGracefully();
  107 + if (!future.isSuccess()) {
  108 + log.warn("workerGroup 无法正常停止", future.cause());
  109 + }
  110 + log.warn("服务:JT808 Server 已经停止, port:{}", port);
  111 + }
  112 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/config/JT1078AutoConfiguration.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.config;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template;
  4 +import com.genersoft.iot.vmp.jt1078.codec.netty.TcpServer;
  5 +import org.springframework.beans.factory.annotation.Value;
  6 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  7 +import org.springframework.context.annotation.Bean;
  8 +import org.springframework.context.annotation.Configuration;
  9 +import org.springframework.core.annotation.Order;
  10 +
  11 +/**
  12 + * @author QingtaiJiang
  13 + * @date 2023/4/27 19:35
  14 + * @email qingtaij@163.com
  15 + */
  16 +@Order(Integer.MIN_VALUE)
  17 +@Configuration
  18 +@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true")
  19 +public class JT1078AutoConfiguration {
  20 +
  21 + @Bean(initMethod = "start", destroyMethod = "stop")
  22 + public TcpServer jt1078Server(@Value("${jt1078.port}") Integer port) {
  23 + return new TcpServer(port);
  24 + }
  25 +
  26 + @Bean
  27 + public JT1078Template jt1078Template() {
  28 + return new JT1078Template();
  29 + }
  30 +}
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/config/JT1078Controller.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.config;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template;
  4 +import com.genersoft.iot.vmp.jt1078.proc.response.*;
  5 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  6 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  7 +import org.springframework.web.bind.annotation.GetMapping;
  8 +import org.springframework.web.bind.annotation.PathVariable;
  9 +import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.RestController;
  11 +
  12 +import javax.annotation.Resource;
  13 +
  14 +/**
  15 + * curl http://localhost:18080/api/jt1078/start/live/18864197066/1
  16 + *
  17 + * @author QingtaiJiang
  18 + * @date 2023/4/27 18:12
  19 + * @email qingtaij@163.com
  20 + */
  21 +@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true")
  22 +@RestController
  23 +@RequestMapping("/api/jt1078")
  24 +public class JT1078Controller {
  25 +
  26 + @Resource
  27 + JT1078Template jt1078Template;
  28 +
  29 + /**
  30 + * jt1078Template 调用示例
  31 + */
  32 + @GetMapping("/start/live/{deviceId}/{channelId}")
  33 + public WVPResult<?> startLive(@PathVariable String deviceId, @PathVariable String channelId) {
  34 + J9101 j9101 = new J9101();
  35 + j9101.setChannel(Integer.valueOf(channelId));
  36 + j9101.setIp("192.168.1.1");
  37 + j9101.setRate(1);
  38 + j9101.setTcpPort(7618);
  39 + j9101.setUdpPort(7618);
  40 + j9101.setType(0);
  41 + // TODO 分配ZLM,获取IP、端口
  42 + String s = jt1078Template.startLive(deviceId, j9101, 6);
  43 + // TODO 设备响应成功后,封装拉流结果集
  44 + WVPResult<String> wvpResult = new WVPResult<>();
  45 + wvpResult.setCode(200);
  46 + wvpResult.setData(String.format("http://192.168.1.1/rtp/%s_%s.live.mp4", deviceId, channelId));
  47 + return wvpResult;
  48 + }
  49 +
  50 +}
  51 +
... ...
src/main/java/com/genersoft/iot/vmp/jt1078/proc/Header.java 0 → 100644
  1 +package com.genersoft.iot.vmp.jt1078.proc;
  2 +
  3 +import com.genersoft.iot.vmp.jt1078.util.Bin;
  4 +
  5 +/**
  6 + * @author QingtaiJiang
  7 + * @date 2023/4/27 18:22
  8 + * @email qingtaij@163.com
  9 + */
  10 +public class Header {
  11 + // 消息ID
  12 + String msgId;
  13 +
  14 + // 消息体属性
  15 + Integer msgPro;
  16 +
  17 + // 标识
  18 + String devId;
  19 +
  20 + // 消息体流水号
  21 + Integer sn;
  22 +
  23 + // 协议版本号
  24 + Short version = -1;
  25 +
  26 +
  27 + public String getMsgId() {
  28 + return msgId;
  29 + }
  30 +
  31 + public void setMsgId(String msgId) {
  32 + this.msgId = msgId;
  33 + }
  34 +
  35 + public Integer getMsgPro() {
  36 + return msgPro;
  37 + }
  38 +
  39 + public void setMsgPro(Integer msgPro) {
  40 + this.msgPro = msgPro;
  41 + }
  42 +
  43 + public String getDevId() {
  44 + return devId;
  45 + }
  46 +
  47 + public void setDevId(String devId) {
  48 + this.devId = devId;
  49 + }
  50 +
  51 + public Integer getSn() {
  52 + return sn;
  53 + }
  54 +
  55 + public void setSn(Integer sn) {
  56 + this.sn = sn;
  57 + }
  58 +
  59 + public Short getVersion() {
  60 + return version;
  61 + }
  62 +
  63 + public void setVersion(Short version) {
  64 + this.version = version;
  65 + }
  66 +
  67 + /**
  68 + * 判断是否是2019的版本
  69 + *
  70 + * @return true 2019后的版本。false 2013
  71 + */
  72 + public boolean is2019Version() {
  73 + return Bin.get(msgPro, 14);
  74 + }
  75 +
  76 +}
... ...