Commit 710600db6f3bd6f72a83ef75cca30953fd0f375f

Authored by 648540858
1 parent 1ee56d50

优化sip消息,去除自动dialog创建

Showing 59 changed files with 888 additions and 861 deletions
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
... ... @@ -64,8 +64,8 @@ public class MediaConfig{
64 64 @Value("${media.secret}")
65 65 private String secret;
66 66  
67   - @Value("${media.stream-none-reader-delay-ms:10000}")
68   - private int streamNoneReaderDelayMS = 10000;
  67 + @Value("${media.stream-none-reader-delay-ms:15000}")
  68 + private int streamNoneReaderDelayMS = 15000;
69 69  
70 70 @Value("${media.rtp.enable}")
71 71 private boolean rtpEnable;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
1 1 package com.genersoft.iot.vmp.gb28181;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
  4 +import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
4 5 import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
5 6 import gov.nist.javax.sip.SipProviderImpl;
6 7 import gov.nist.javax.sip.SipStackImpl;
... ... @@ -41,43 +42,7 @@ public class SipLayer{
41 42 @Bean("sipStack")
42 43 @DependsOn({"sipFactory"})
43 44 SipStack createSipStack() throws PeerUnavailableException {
44   - Properties properties = new Properties();
45   - properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
46   - properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp());
47   - /**
48   - * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
49   - * gov/nist/javax/sip/SipStackImpl.class
50   - * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
51   - */
52   -
53   -// * gov/nist/javax/sip/SipStackImpl.class
54   - if (logger.isDebugEnabled()) {
55   - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
56   - }
57   - // 接收所有notify请求,即使没有订阅
58   - properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
59   - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
60   - properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
61   - // 为_NULL _对话框传递_终止的_事件
62   - properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
63   - // 会话清理策略
64   - properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
65   - // 处理由该服务器处理的基于底层TCP的保持生存超时
66   - properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
67   - // 获取实际内容长度,不使用header中的长度信息
68   - properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
69   -
70   - /**
71   - * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
72   - */
73   - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
74   -// properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", "com.genersoft.iot.vmp.gb28181.session.SipMessagePreprocessing");
75   -// if (logger.isDebugEnabled()) {
76   -// properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
77   -// }
78   -
79   - sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
80   -
  45 + sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
81 46 return sipStack;
82 47 }
83 48  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -380,4 +380,5 @@ public class Device {
380 380 public void setTreeType(String treeType) {
381 381 this.treeType = treeType;
382 382 }
  383 +
383 384 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
  3 +import gov.nist.javax.sip.message.SIPRequest;
  4 +
3 5 public class SendRtpItem {
4 6  
5 7 /**
... ... @@ -77,11 +79,21 @@ public class SendRtpItem {
77 79 private String serverId;
78 80  
79 81 /**
80   - * invitecallId
  82 + * invitecallId
81 83 */
82 84 private String CallId;
83 85  
84 86 /**
  87 + * invite 的 fromTag
  88 + */
  89 + private String fromTag;
  90 +
  91 + /**
  92 + * invite 的 toTag
  93 + */
  94 + private String toTag;
  95 +
  96 + /**
85 97 * 发送时,rtp的pt(uint8_t),不传时默认为96
86 98 */
87 99 private int pt = 96;
... ... @@ -96,15 +108,12 @@ public class SendRtpItem {
96 108 */
97 109 private boolean onlyAudio = false;
98 110  
  111 +
99 112 /**
100 113 * 播放类型
101 114 */
102 115 private InviteStreamType playType;
103 116  
104   - private byte[] transaction;
105   -
106   - private byte[] dialog;
107   -
108 117 public String getIp() {
109 118 return ip;
110 119 }
... ... @@ -225,22 +234,6 @@ public class SendRtpItem {
225 234 this.playType = playType;
226 235 }
227 236  
228   - public byte[] getTransaction() {
229   - return transaction;
230   - }
231   -
232   - public void setTransaction(byte[] transaction) {
233   - this.transaction = transaction;
234   - }
235   -
236   - public byte[] getDialog() {
237   - return dialog;
238   - }
239   -
240   - public void setDialog(byte[] dialog) {
241   - this.dialog = dialog;
242   - }
243   -
244 237 public int getPt() {
245 238 return pt;
246 239 }
... ... @@ -272,4 +265,20 @@ public class SendRtpItem {
272 265 public void setServerId(String serverId) {
273 266 this.serverId = serverId;
274 267 }
  268 +
  269 + public String getFromTag() {
  270 + return fromTag;
  271 + }
  272 +
  273 + public void setFromTag(String fromTag) {
  274 + this.fromTag = fromTag;
  275 + }
  276 +
  277 + public String getToTag() {
  278 + return toTag;
  279 + }
  280 +
  281 + public void setToTag(String toTag) {
  282 + this.toTag = toTag;
  283 + }
275 284 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
... ... @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
7 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  8 +import com.genersoft.iot.vmp.service.IPlatformService;
8 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 11 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -23,15 +24,6 @@ public class SubscribeHolder {
23 24 @Autowired
24 25 private DynamicTask dynamicTask;
25 26  
26   - @Autowired
27   - private IRedisCatchStorage redisCatchStorage;
28   -
29   - @Autowired
30   - private ISIPCommanderForPlatform sipCommanderForPlatform;
31   -
32   - @Autowired
33   - private IVideoManagerStorage storager;
34   -
35 27 private final String taskOverduePrefix = "subscribe_overdue_";
36 28  
37 29 private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
... ... @@ -62,15 +54,13 @@ public class SubscribeHolder {
62 54 }
63 55 // 添加任务处理订阅过期
64 56 dynamicTask.stop(taskOverdueKey);
65   -
66 57 }
67 58  
68 59 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
69 60 mobilePositionMap.put(platformId, subscribeInfo);
70 61 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
71 62 // 添加任务处理GPS定时推送
72   - dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform,
73   - storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask),
  63 + dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId),
74 64 subscribeInfo.getGpsInterval() * 1000);
75 65 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
76 66 // 添加任务处理订阅过期
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3 3 import com.genersoft.iot.vmp.utils.SerializeUtils;
  4 +import gov.nist.javax.sip.message.SIPRequest;
  5 +import gov.nist.javax.sip.message.SIPResponse;
4 6  
  7 +import javax.sip.ClientTransaction;
5 8 import javax.sip.Dialog;
6 9 import javax.sip.RequestEvent;
7 10 import javax.sip.ServerTransaction;
... ... @@ -11,30 +14,24 @@ import javax.sip.message.Request;
11 14 public class SubscribeInfo {
12 15  
13 16  
14   - public SubscribeInfo(RequestEvent evt, String id) {
  17 + public SubscribeInfo(ServerTransaction serverTransaction, String id) {
15 18 this.id = id;
16   - Request request = evt.getRequest();
17   - ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME);
18   - this.expires = expiresHeader.getExpires();
  19 + SIPRequest request = (SIPRequest)serverTransaction.getRequest();
  20 + this.request = request;
  21 + this.expires = request.getExpires().getExpires();
19 22 EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
20 23 this.eventId = eventHeader.getEventId();
21 24 this.eventType = eventHeader.getEventType();
22   - this.transaction = evt.getServerTransaction();
23   - this.dialog = evt.getDialog();
24   - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
25   - this.callId = callIdHeader.getCallId();
26   - }
27 25  
28   - public SubscribeInfo() {
29 26 }
30 27  
31 28 private String id;
  29 +
  30 + private SIPRequest request;
32 31 private int expires;
33   - private String callId;
34 32 private String eventId;
35 33 private String eventType;
36   - private ServerTransaction transaction;
37   - private Dialog dialog;
  34 + private SIPResponse response;
38 35  
39 36 /**
40 37 * 以下为可选字段
... ... @@ -43,29 +40,28 @@ public class SubscribeInfo {
43 40 private String sn;
44 41 private int gpsInterval;
45 42  
46   -
47 43 public String getId() {
48 44 return id;
49 45 }
50 46  
51   - public int getExpires() {
52   - return expires;
  47 + public void setId(String id) {
  48 + this.id = id;
53 49 }
54 50  
55   - public String getCallId() {
56   - return callId;
  51 + public SIPRequest getRequest() {
  52 + return request;
57 53 }
58 54  
59   - public void setId(String id) {
60   - this.id = id;
  55 + public void setRequest(SIPRequest request) {
  56 + this.request = request;
61 57 }
62 58  
63   - public void setExpires(int expires) {
64   - this.expires = expires;
  59 + public int getExpires() {
  60 + return expires;
65 61 }
66 62  
67   - public void setCallId(String callId) {
68   - this.callId = callId;
  63 + public void setExpires(int expires) {
  64 + this.expires = expires;
69 65 }
70 66  
71 67 public String getEventId() {
... ... @@ -84,20 +80,12 @@ public class SubscribeInfo {
84 80 this.eventType = eventType;
85 81 }
86 82  
87   - public ServerTransaction getTransaction() {
88   - return transaction;
89   - }
90   -
91   - public void setTransaction(ServerTransaction transaction) {
92   - this.transaction = transaction;
93   - }
94   -
95   - public Dialog getDialog() {
96   - return dialog;
  83 + public SIPResponse getResponse() {
  84 + return response;
97 85 }
98 86  
99   - public void setDialog(Dialog dialog) {
100   - this.dialog = dialog;
  87 + public void setResponse(SIPResponse response) {
  88 + this.response = response;
101 89 }
102 90  
103 91 public String getSn() {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.conf;
  2 +
  3 +import java.util.Properties;
  4 +
  5 +/**
  6 + * 获取sip默认配置
  7 + * @author lin
  8 + */
  9 +public class DefaultProperties {
  10 +
  11 + public static Properties getProperties(String ip, boolean isDebug) {
  12 + Properties properties = new Properties();
  13 + properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
  14 + properties.setProperty("javax.sip.IP_ADDRESS", ip);
  15 + properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
  16 + /**
  17 + * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
  18 + * gov/nist/javax/sip/SipStackImpl.class
  19 + * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
  20 + */
  21 +
  22 +// * gov/nist/javax/sip/SipStackImpl.class
  23 + if (isDebug) {
  24 + properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
  25 + }
  26 + // 接收所有notify请求,即使没有订阅
  27 + properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
  28 + properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
  29 + properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
  30 + // 为_NULL _对话框传递_终止的_事件
  31 + properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
  32 + // 会话清理策略
  33 + properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
  34 + // 处理由该服务器处理的基于底层TCP的保持生存超时
  35 + properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
  36 + // 获取实际内容长度,不使用header中的长度信息
  37 + properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
  38 +
  39 + /**
  40 + * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
  41 + */
  42 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
  43 +
  44 + return properties;
  45 + }
  46 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
1 1 package com.genersoft.iot.vmp.gb28181.event;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
  4 +import gov.nist.javax.sip.message.SIPRequest;
4 5 import org.slf4j.Logger;
5 6 import org.slf4j.LoggerFactory;
6 7 import org.springframework.scheduling.annotation.Scheduled;
... ... @@ -104,22 +105,27 @@ public class SipSubscribe {
104 105 this.type = EventResultType.timeout;
105 106 this.msg = "消息超时未回复";
106 107 this.statusCode = -1024;
107   - this.dialog = timeoutEvent.getClientTransaction().getDialog();
108   - this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null;
  108 + if (timeoutEvent.isServerTransaction()) {
  109 + this.callId = ((SIPRequest)timeoutEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
  110 + }else {
  111 + this.callId = ((SIPRequest)timeoutEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
  112 + }
109 113 }else if (event instanceof TransactionTerminatedEvent) {
110 114 TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event;
111 115 this.type = EventResultType.transactionTerminated;
112 116 this.msg = "事务已结束";
113 117 this.statusCode = -1024;
114   - this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId();
115   - this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog();
  118 + if (transactionTerminatedEvent.isServerTransaction()) {
  119 + this.callId = ((SIPRequest)transactionTerminatedEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
  120 + }else {
  121 + this.callId = ((SIPRequest)transactionTerminatedEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
  122 + }
116 123 }else if (event instanceof DialogTerminatedEvent) {
117 124 DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event;
118 125 this.type = EventResultType.dialogTerminated;
119 126 this.msg = "会话已结束";
120 127 this.statusCode = -1024;
121 128 this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
122   - this.dialog = dialogTerminatedEvent.getDialog();
123 129 }else if (event instanceof DeviceNotFoundEvent) {
124 130 DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
125 131 this.type = EventResultType.deviceNotFoundEvent;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
... ... @@ -7,6 +7,4 @@ import javax.sip.DialogState;
7 7 */
8 8 public interface ISubscribeTask extends Runnable{
9 9 void stop();
10   -
11   - DialogState getDialogState();
12 10 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
... ... @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  7 +import gov.nist.javax.sip.message.SIPRequest;
7 8 import org.slf4j.Logger;
8 9 import org.slf4j.LoggerFactory;
9 10 import org.springframework.scheduling.annotation.Async;
... ... @@ -12,6 +13,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
12 13 import javax.sip.Dialog;
13 14 import javax.sip.DialogState;
14 15 import javax.sip.ResponseEvent;
  16 +import javax.sip.header.ToHeader;
  17 +import java.text.ParseException;
15 18 import java.util.Timer;
16 19 import java.util.TimerTask;
17 20  
... ... @@ -23,7 +26,7 @@ public class CatalogSubscribeTask implements ISubscribeTask {
23 26 private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
24 27 private Device device;
25 28 private final ISIPCommander sipCommander;
26   - private Dialog dialog;
  29 + private SIPRequest request;
27 30  
28 31 private DynamicTask dynamicTask;
29 32  
... ... @@ -41,24 +44,26 @@ public class CatalogSubscribeTask implements ISubscribeTask {
41 44 if (dynamicTask.get(taskKey) != null) {
42 45 dynamicTask.stop(taskKey);
43 46 }
44   - sipCommander.catalogSubscribe(device, dialog, eventResult -> {
45   - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
46   - dialog = eventResult.dialog;
47   - }
  47 + SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
48 48 ResponseEvent event = (ResponseEvent) eventResult.event;
49   - if (event.getResponse().getRawContent() != null) {
50   - // 成功
51   - logger.info("[目录订阅]成功: {}", device.getDeviceId());
52   - }else {
53   - // 成功
54   - logger.info("[目录订阅]成功: {}", device.getDeviceId());
  49 + // 成功
  50 + logger.info("[目录订阅]成功: {}", device.getDeviceId());
  51 + ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
  52 + try {
  53 + this.request.getToHeader().setTag(toHeader.getTag());
  54 + } catch (ParseException e) {
  55 + logger.info("[目录订阅]成功: 但为request设置ToTag失败");
  56 + this.request = null;
55 57 }
56 58 },eventResult -> {
57   - dialog = null;
  59 + this.request = null;
58 60 // 失败
59 61 logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
60 62 dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
61 63 });
  64 + if (sipRequest != null) {
  65 + this.request = sipRequest;
  66 + }
62 67 }
63 68  
64 69 @Override
... ... @@ -74,29 +79,19 @@ public class CatalogSubscribeTask implements ISubscribeTask {
74 79 if (dynamicTask.get(taskKey) != null) {
75 80 dynamicTask.stop(taskKey);
76 81 }
77   - if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
78   - device.setSubscribeCycleForCatalog(0);
79   - sipCommander.catalogSubscribe(device, dialog, eventResult -> {
80   - ResponseEvent event = (ResponseEvent) eventResult.event;
81   - if (event.getResponse().getRawContent() != null) {
82   - // 成功
83   - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
84   - }else {
85   - // 成功
86   - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
87   - }
88   - },eventResult -> {
89   - // 失败
90   - logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
91   - });
92   - }
93   - }
94   -
95   - @Override
96   - public DialogState getDialogState() {
97   - if (dialog == null) {
98   - return null;
99   - }
100   - return dialog.getState();
  82 + device.setSubscribeCycleForCatalog(0);
  83 + sipCommander.catalogSubscribe(device, request, eventResult -> {
  84 + ResponseEvent event = (ResponseEvent) eventResult.event;
  85 + if (event.getResponse().getRawContent() != null) {
  86 + // 成功
  87 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  88 + }else {
  89 + // 成功
  90 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  91 + }
  92 + },eventResult -> {
  93 + // 失败
  94 + logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  95 + });
101 96 }
102 97 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
... ... @@ -4,9 +4,11 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
4 4 import com.genersoft.iot.vmp.gb28181.bean.*;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  7 +import com.genersoft.iot.vmp.service.IPlatformService;
7 8 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
8 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  11 +import com.genersoft.iot.vmp.utils.SpringBeanFactory;
10 12 import org.slf4j.Logger;
11 13 import org.slf4j.LoggerFactory;
12 14 import org.springframework.scheduling.annotation.Async;
... ... @@ -20,71 +22,23 @@ import java.util.List;
20 22 */
21 23 public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
22 24  
23   - private Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeHandlerTask.class);
24 25  
25   - private IRedisCatchStorage redisCatchStorage;
26   - private IVideoManagerStorage storager;
27   - private ISIPCommanderForPlatform sipCommanderForPlatform;
28   - private SubscribeHolder subscribeHolder;
29   - private ParentPlatform platform;
  26 + private IPlatformService platformService;
  27 + private String platformId;
30 28  
31   - private String sn;
32   - private String key;
33 29  
34   - public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage,
35   - ISIPCommanderForPlatform sipCommanderForPlatform,
36   - IVideoManagerStorage storager,
37   - String platformId,
38   - String sn,
39   - String key,
40   - SubscribeHolder subscribeInfo,
41   - DynamicTask dynamicTask) {
42   - this.redisCatchStorage = redisCatchStorage;
43   - this.storager = storager;
44   - this.platform = storager.queryParentPlatByServerGBId(platformId);
45   - this.sn = sn;
46   - this.key = key;
47   - this.sipCommanderForPlatform = sipCommanderForPlatform;
48   - this.subscribeHolder = subscribeInfo;
  30 + public MobilePositionSubscribeHandlerTask(String platformId) {
  31 + this.platformService = SpringBeanFactory.getBean("platformServiceImpl");
  32 + this.platformId = platformId;
49 33 }
50 34  
51 35 @Override
52 36 public void run() {
53   -
54   - if (platform == null) {
55   - return;
56   - }
57   - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
58   - if (subscribe != null) {
59   -
60   - // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
61   - List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
62   - if (gbStreams.size() == 0) {
63   - return;
64   - }
65   - for (DeviceChannel deviceChannel : gbStreams) {
66   - String gbId = deviceChannel.getChannelId();
67   - GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
68   - // 无最新位置不发送
69   - if (gpsMsgInfo != null) {
70   - // 经纬度都为0不发送
71   - if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
72   - continue;
73   - }
74   - // 发送GPS消息
75   - sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
76   - }
77   - }
78   - }
  37 + platformService.sendNotifyMobilePosition(this.platformId);
79 38 }
80 39  
81 40 @Override
82 41 public void stop() {
83 42  
84 43 }
85   -
86   - @Override
87   - public DialogState getDialogState() {
88   - return null;
89   - }
90 44 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
... ... @@ -4,6 +4,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  7 +import gov.nist.javax.sip.message.SIPRequest;
  8 +import gov.nist.javax.sip.message.SIPResponse;
7 9 import org.dom4j.Element;
8 10 import org.slf4j.Logger;
9 11 import org.slf4j.LoggerFactory;
... ... @@ -12,6 +14,8 @@ import org.springframework.scheduling.annotation.Async;
12 14 import javax.sip.Dialog;
13 15 import javax.sip.DialogState;
14 16 import javax.sip.ResponseEvent;
  17 +import javax.sip.header.ToHeader;
  18 +import java.text.ParseException;
15 19 import java.util.Timer;
16 20 import java.util.TimerTask;
17 21  
... ... @@ -21,9 +25,10 @@ import java.util.TimerTask;
21 25 */
22 26 public class MobilePositionSubscribeTask implements ISubscribeTask {
23 27 private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
24   - private Device device;
25   - private ISIPCommander sipCommander;
26   - private Dialog dialog;
  28 + private Device device;
  29 + private ISIPCommander sipCommander;
  30 +
  31 + private SIPRequest request;
27 32 private DynamicTask dynamicTask;
28 33 private String taskKey = "mobile-position-subscribe-timeout";
29 34  
... ... @@ -38,24 +43,26 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
38 43 if (dynamicTask.get(taskKey) != null) {
39 44 dynamicTask.stop(taskKey);
40 45 }
41   - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
42   - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
43   - dialog = eventResult.dialog;
44   - }
  46 + SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
  47 + // 成功
  48 + logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
45 49 ResponseEvent event = (ResponseEvent) eventResult.event;
46   - if (event.getResponse().getRawContent() != null) {
47   - // 成功
48   - logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
49   - }else {
50   - // 成功
51   - logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
  50 + ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
  51 + try {
  52 + this.request.getToHeader().setTag(toHeader.getTag());
  53 + } catch (ParseException e) {
  54 + logger.info("[移动位置订阅]成功: 为request设置ToTag失败");
  55 + this.request = null;
52 56 }
53 57 },eventResult -> {
54   - dialog = null;
  58 + this.request = null;
55 59 // 失败
56 60 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
57 61 dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
58 62 });
  63 + if (sipRequest != null) {
  64 + this.request = sipRequest;
  65 + }
59 66  
60 67 }
61 68  
... ... @@ -71,29 +78,19 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
71 78 if (dynamicTask.get(taskKey) != null) {
72 79 dynamicTask.stop(taskKey);
73 80 }
74   - if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
75   - logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
76   - device.setSubscribeCycleForMobilePosition(0);
77   - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
78   - ResponseEvent event = (ResponseEvent) eventResult.event;
79   - if (event.getResponse().getRawContent() != null) {
80   - // 成功
81   - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
82   - }else {
83   - // 成功
84   - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
85   - }
86   - },eventResult -> {
87   - // 失败
88   - logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
89   - });
90   - }
91   - }
92   - @Override
93   - public DialogState getDialogState() {
94   - if (dialog == null) {
95   - return null;
96   - }
97   - return dialog.getState();
  81 + device.setSubscribeCycleForMobilePosition(0);
  82 + sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
  83 + ResponseEvent event = (ResponseEvent) eventResult.event;
  84 + if (event.getResponse().getRawContent() != null) {
  85 + // 成功
  86 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  87 + }else {
  88 + // 成功
  89 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  90 + }
  91 + },eventResult -> {
  92 + // 失败
  93 + logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  94 + });
98 95 }
99 96 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
... ... @@ -72,9 +72,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
72 72 @Async("taskExecutor")
73 73 public void processRequest(RequestEvent requestEvent) {
74 74 String method = requestEvent.getRequest().getMethod();
75   - if ("NOTIFY".equalsIgnoreCase(requestEvent.getRequest().getMethod())) {
76   - System.out.println();
77   - }
78 75 ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
79 76 if (sipRequestProcessor == null) {
80 77 logger.warn("不支持方法{}的request", method);
... ... @@ -173,6 +170,12 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
173 170  
174 171 @Override
175 172 public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
  173 +// if (transactionTerminatedEvent.isServerTransaction()) {
  174 +// ServerTransaction serverTransaction = transactionTerminatedEvent.getServerTransaction();
  175 +// serverTransaction.get
  176 +// }
  177 +
  178 +
176 179 // Transaction transaction = null;
177 180 // System.out.println("processTransactionTerminated");
178 181 // if (transactionTerminatedEvent.isServerTransaction()) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 6 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
7 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 8 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
  9 +import gov.nist.javax.sip.message.SIPRequest;
9 10  
10 11 import javax.sip.Dialog;
11 12  
... ... @@ -313,7 +314,7 @@ public interface ISIPCommander {
313 314 * @param device 视频设备
314 315 * @return true = 命令发送成功
315 316 */
316   - boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
  317 + SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
317 318  
318 319 /**
319 320 * 订阅、取消订阅报警信息
... ... @@ -333,7 +334,7 @@ public interface ISIPCommander {
333 334 * @param device 视频设备
334 335 * @return true = 命令发送成功
335 336 */
336   - boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
  337 + SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
337 338  
338 339 /**
339 340 * 拉框控制命令
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
... ... @@ -117,4 +117,5 @@ public interface ISIPCommanderForPlatform {
117 117 * @param callId callId
118 118 */
119 119 void streamByeCmd(ParentPlatform platform, String callId);
  120 + void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem);
120 121 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -2,10 +2,13 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
4 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  6 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
5 7 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
6 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
7 9 import com.genersoft.iot.vmp.utils.GitUtil;
8 10 import gov.nist.javax.sip.message.MessageFactoryImpl;
  11 +import gov.nist.javax.sip.message.SIPRequest;
9 12 import org.springframework.beans.factory.annotation.Autowired;
10 13 import org.springframework.stereotype.Component;
11 14 import org.springframework.util.DigestUtils;
... ... @@ -154,8 +157,17 @@ public class SIPRequestHeaderPlarformProvider {
154 157 return registerRequest;
155 158 }
156 159  
  160 + public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  161 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
  162 + return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader);
  163 + }
157 164  
158 165 public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  166 + return createMessageRequest(parentPlatform, content, fromTag, viaTag, null, callIdHeader);
  167 + }
  168 +
  169 +
  170 + public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
159 171 Request request = null;
160 172 String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort();
161 173 // sipuri
... ... @@ -174,7 +186,7 @@ public class SIPRequestHeaderPlarformProvider {
174 186 // to
175 187 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
176 188 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
177   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null);
  189 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
178 190  
179 191 // Forwards
180 192 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
... ... @@ -192,4 +204,107 @@ public class SIPRequestHeaderPlarformProvider {
192 204 request.setContent(content, contentTypeHeader);
193 205 return request;
194 206 }
  207 +
  208 + public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  209 + SIPRequest request = null;
  210 + // sipuri
  211 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
  212 + // via
  213 + ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
  214 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
  215 + parentPlatform.getTransport(), SipUtils.getNewViaTag());
  216 + viaHeader.setRPort();
  217 + viaHeaders.add(viaHeader);
  218 + // from
  219 + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
  220 + parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
  221 + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  222 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
  223 + // to
  224 + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
  225 + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  226 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
  227 +
  228 + // Forwards
  229 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  230 + // ceq
  231 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY);
  232 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  233 + // 设置编码, 防止中文乱码
  234 + messageFactory.setDefaultContentEncodingCharset("gb2312");
  235 +
  236 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
  237 +
  238 + request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
  239 + toHeader, viaHeaders, maxForwards);
  240 +
  241 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  242 +
  243 + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  244 + if (subscribeInfo.getEventId() != null) {
  245 + event.setEventId(subscribeInfo.getEventId());
  246 + }
  247 +
  248 + request.addHeader(event);
  249 +
  250 + SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");
  251 + request.setHeader(active);
  252 +
  253 + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
  254 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
  255 + .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
  256 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  257 +
  258 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  259 + request.setContent(content, contentTypeHeader);
  260 + return request;
  261 + }
  262 +
  263 + public SIPRequest createByeRequest(ParentPlatform platform, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  264 +
  265 + if (sendRtpItem == null ) {
  266 + return null;
  267 + }
  268 +
  269 + SIPRequest request = null;
  270 + // sipuri
  271 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort());
  272 + // via
  273 + ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
  274 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(platform.getDeviceIp(), Integer.parseInt(platform.getDevicePort()),
  275 + platform.getTransport(), SipUtils.getNewViaTag());
  276 + viaHeader.setRPort();
  277 + viaHeaders.add(viaHeader);
  278 + // from
  279 + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(),
  280 + platform.getDeviceIp() + ":" + platform.getDevicePort());
  281 + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  282 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag());
  283 + // to
  284 + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain());
  285 + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  286 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag());
  287 +
  288 + // Forwards
  289 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  290 + // ceq
  291 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
  292 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  293 + // 设置编码, 防止中文乱码
  294 + messageFactory.setDefaultContentEncodingCharset("gb2312");
  295 +
  296 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
  297 +
  298 + request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader,
  299 + toHeader, viaHeaders, maxForwards);
  300 +
  301 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  302 +
  303 + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
  304 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
  305 + .createSipURI(platform.getDeviceGBId(), sipAddress));
  306 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  307 +
  308 + return request;
  309 + }
195 310 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 16 import com.genersoft.iot.vmp.utils.GitUtil;
17 17 import gov.nist.javax.sip.SipProviderImpl;
18 18 import gov.nist.javax.sip.SipStackImpl;
  19 +import gov.nist.javax.sip.message.SIPRequest;
19 20 import gov.nist.javax.sip.stack.SIPDialog;
20 21 import org.springframework.beans.factory.annotation.Autowired;
21 22 import org.springframework.beans.factory.annotation.Qualifier;
... ... @@ -199,24 +200,24 @@ public class SIPRequestHeaderProvider {
199 200 return request;
200 201 }
201 202  
202   - public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
  203 + public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
203 204 Request request = null;
204 205 // sipuri
205 206 SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
206 207 // via
207 208 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
208 209 ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(),
209   - device.getTransport(), viaTag);
  210 + device.getTransport(), SipUtils.getNewViaTag());
210 211 viaHeader.setRPort();
211 212 viaHeaders.add(viaHeader);
212 213 // from
213 214 SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
214 215 Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
215   - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
  216 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
216 217 // to
217 218 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
218 219 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
219   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
  220 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
220 221  
221 222 // Forwards
222 223 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
... ... @@ -238,7 +239,7 @@ public class SIPRequestHeaderProvider {
238 239 // Event
239 240 EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
240 241  
241   - int random = (int)Math.random() * 1000000000;
  242 + int random = (int) Math.floor(Math.random() * 10000);
242 243 eventHeader.setEventId(random + "");
243 244 request.addHeader(eventHeader);
244 245  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -1424,7 +1424,7 @@ public class SIPCommander implements ISIPCommander {
1424 1424 * @return true = 命令发送成功
1425 1425 */
1426 1426 @Override
1427   - public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
  1427 + public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
1428 1428 try {
1429 1429 StringBuffer subscribePostitionXml = new StringBuffer(200);
1430 1430 String charset = device.getCharset();
... ... @@ -1434,38 +1434,27 @@ public class SIPCommander implements ISIPCommander {
1434 1434 subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1435 1435 subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1436 1436 if (device.getSubscribeCycleForMobilePosition() > 0) {
1437   - subscribePostitionXml.append("<Interval>" + String.valueOf(device.getMobilePositionSubmissionInterval()) + "</Interval>\r\n");
  1437 + subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");
1438 1438 }
1439 1439 subscribePostitionXml.append("</Query>\r\n");
1440 1440  
1441   - Request request;
1442   - if (dialog != null) {
1443   - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
1444   - request = dialog.createRequest(Request.SUBSCRIBE);
1445   - ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
1446   - request.setExpires(expiresHeader);
  1441 + CallIdHeader callIdHeader;
1447 1442  
1448   - request.setRequestURI(requestURI);
1449   -
1450   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1451   - request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
1452   -
1453   - CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
1454   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
1455   - request.removeHeader(CSeqHeader.NAME);
1456   - request.addHeader(cSeqHeader);
  1443 + if (requestOld != null) {
  1444 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1457 1445 }else {
1458   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1446 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1459 1447 : udpSipProvider.getNewCallId();
1460   - request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
1461 1448 }
  1449 + SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
  1450 +
1462 1451 transmitRequest(device, request, errorEvent, okEvent);
1463 1452  
1464   - return true;
  1453 + return request;
1465 1454  
1466 1455 } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1467 1456 e.printStackTrace();
1468   - return false;
  1457 + return null;
1469 1458 }
1470 1459 }
1471 1460  
... ... @@ -1515,7 +1504,7 @@ public class SIPCommander implements ISIPCommander {
1515 1504 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1516 1505 : udpSipProvider.getNewCallId();
1517 1506  
1518   - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, expires, "presence" , callIdHeader);
  1507 + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence" , callIdHeader);
1519 1508 transmitRequest(device, request);
1520 1509  
1521 1510 return true;
... ... @@ -1527,7 +1516,7 @@ public class SIPCommander implements ISIPCommander {
1527 1516 }
1528 1517  
1529 1518 @Override
1530   - public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
  1519 + public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
1531 1520 try {
1532 1521 StringBuffer cmdXml = new StringBuffer(200);
1533 1522 String charset = device.getCharset();
... ... @@ -1538,40 +1527,24 @@ public class SIPCommander implements ISIPCommander {
1538 1527 cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1539 1528 cmdXml.append("</Query>\r\n");
1540 1529  
  1530 + CallIdHeader callIdHeader ;
1541 1531  
1542   - Request request;
1543   - if (dialog != null) {
1544   - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
1545   - request = dialog.createRequest(Request.SUBSCRIBE);
1546   - ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
1547   - request.setExpires(expiresHeader);
1548   -
1549   - request.setRequestURI(requestURI);
1550   -
1551   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1552   - request.setContent(cmdXml.toString(), contentTypeHeader);
1553   -
1554   - CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
1555   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
1556   - request.removeHeader(CSeqHeader.NAME);
1557   - request.addHeader(cSeqHeader);
1558   -
  1532 + if (requestOld != null) {
  1533 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1559 1534 }else {
1560   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1535 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1561 1536 : udpSipProvider.getNewCallId();
1562   -
1563   - // 有效时间默认为60秒以上
1564   - request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(),
1565   - SipUtils.getNewFromTag(), null, device.getSubscribeCycleForCatalog(), "Catalog" ,
1566   - callIdHeader);
1567   -
1568 1537 }
  1538 +
  1539 + // 有效时间默认为60秒以上
  1540 + SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog" ,
  1541 + callIdHeader);
1569 1542 transmitRequest(device, request, errorEvent, okEvent);
1570   - return true;
  1543 + return request;
1571 1544  
1572 1545 } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1573 1546 e.printStackTrace();
1574   - return false;
  1547 + return null;
1575 1548 }
1576 1549 }
1577 1550  
... ... @@ -1847,61 +1820,4 @@ public class SIPCommander implements ISIPCommander {
1847 1820 }
1848 1821 return true;
1849 1822 }
1850   -
1851   - private void sendNotify(Device device, String catalogXmlContent,
1852   - SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
1853   - throws SipException, ParseException {
1854   - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
1855   - String characterSet = device.getCharset();
1856   - // 设置编码, 防止中文乱码
1857   - messageFactory.setDefaultContentEncodingCharset(characterSet);
1858   - Dialog dialog = subscribeInfo.getDialog();
1859   - if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
1860   - return;
1861   - }
1862   - SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
1863   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
1864   - notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
1865   -
1866   - SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
1867   - .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
1868   - notifyRequest.addHeader(subscriptionState);
1869   -
1870   - EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
1871   - if (subscribeInfo.getEventId() != null) {
1872   - event.setEventId(subscribeInfo.getEventId());
1873   - }
1874   - notifyRequest.addHeader(event);
1875   -
1876   - SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
1877   - if (subscribeInfo.getTransaction() != null) {
1878   - SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
1879   - sipURI.setHost(request.getRemoteAddress().getHostAddress());
1880   - sipURI.setPort(request.getRemotePort());
1881   - }else {
1882   - sipURI.setHost(device.getIp());
1883   - sipURI.setPort(device.getPort());
1884   - }
1885   -
1886   - ClientTransaction transaction = null;
1887   - if ("TCP".equals(device.getTransport())) {
1888   - transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
1889   - } else if ("UDP".equals(device.getTransport())) {
1890   - transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
1891   - }
1892   - // 添加错误订阅
1893   - if (errorEvent != null) {
1894   - sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
1895   - }
1896   - // 添加订阅
1897   - if (okEvent != null) {
1898   - sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
1899   - }
1900   - if (transaction == null) {
1901   - logger.error("平台{}的Transport错误:{}",device.getDeviceId(), device.getTransport());
1902   - return;
1903   - }
1904   - dialog.sendRequest(transaction);
1905   -
1906   - }
1907 1823 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2  
  3 +import com.alibaba.fastjson.JSONObject;
3 4 import com.genersoft.iot.vmp.gb28181.bean.*;
4 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
... ... @@ -45,7 +46,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
45 46 private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class);
46 47  
47 48 @Autowired
48   - private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider;
  49 + private SIPRequestHeaderPlarformProvider headerProviderPlatformProvider;
49 50  
50 51 @Autowired
51 52 private IRedisCatchStorage redisCatchStorage;
... ... @@ -72,6 +73,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
72 73 @Autowired
73 74 private SipFactory sipFactory;
74 75  
  76 + @Autowired
  77 + private SubscribeHolder subscribeHolder;
  78 +
75 79 @Override
76 80 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
77 81 return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
... ... @@ -96,7 +100,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
96 100 callIdHeader = udpSipProvider.getNewCallId();
97 101 }
98 102  
99   - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform,
  103 + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform,
100 104 redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(),
101 105 SipUtils.getNewViaTag(), callIdHeader, isRegister);
102 106 // 将 callid 写入缓存, 等注册成功可以更新状态
... ... @@ -118,7 +122,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
118 122 }else {
119 123 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
120 124 : udpSipProvider.getNewCallId();
121   - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister);
  125 + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister);
122 126 }
123 127  
124 128 transmitRequest(parentPlatform, request, null, okEvent);
... ... @@ -152,7 +156,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
152 156 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
153 157 : udpSipProvider.getNewCallId();
154 158  
155   - Request request = headerProviderPlarformProvider.createMessageRequest(
  159 + Request request = headerProviderPlatformProvider.createMessageRequest(
156 160 parentPlatform,
157 161 keepaliveXml.toString(),
158 162 SipUtils.getNewFromTag(),
... ... @@ -218,7 +222,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
218 222 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
219 223 : udpSipProvider.getNewCallId();
220 224  
221   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  225 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
222 226 transmitRequest(parentPlatform, request);
223 227  
224 228 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -312,7 +316,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
312 316 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
313 317 : udpSipProvider.getNewCallId();
314 318  
315   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
  319 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
316 320 transmitRequest(parentPlatform, request, null, eventResult -> {
317 321 int indexNext = index + parentPlatform.getCatalogGroup();
318 322 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
... ... @@ -352,7 +356,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
352 356 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
353 357 : udpSipProvider.getNewCallId();
354 358  
355   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  359 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
356 360 transmitRequest(parentPlatform, request);
357 361  
358 362 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -390,7 +394,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
390 394 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
391 395 : udpSipProvider.getNewCallId();
392 396  
393   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  397 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
394 398 transmitRequest(parentPlatform, request);
395 399  
396 400 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -425,11 +429,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
425 429 deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
426 430 deviceStatusXml.append("</Notify>\r\n");
427 431  
428   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
429   - : udpSipProvider.getNewCallId();
430   - callIdHeader.setCallId(subscribeInfo.getCallId());
431   -
432   - sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
  432 + sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
433 433 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
434 434 }, null);
435 435  
... ... @@ -451,8 +451,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
451 451 if (parentPlatform == null) {
452 452 return false;
453 453 }
454   - logger.info("[发送 报警订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
455   - deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  454 + logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
  455 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
456 456 try {
457 457 String characterSet = parentPlatform.getCharacterSet();
458 458 StringBuffer deviceStatusXml = new StringBuffer(600);
... ... @@ -475,7 +475,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
475 475 CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
476 476 : udpSipProvider.getNewCallId();
477 477  
478   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
  478 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
479 479 transmitRequest(parentPlatform, request);
480 480  
481 481 } catch (SipException | ParseException e) {
... ... @@ -527,18 +527,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
527 527 return true;
528 528 }
529 529  
530   - private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
  530 + private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
531 531 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
532 532 throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException {
533 533 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
534 534 String characterSet = parentPlatform.getCharacterSet();
535 535 // 设置编码, 防止中文乱码
536 536 messageFactory.setDefaultContentEncodingCharset(characterSet);
537   - Dialog dialog = subscribeInfo.getDialog();
538   - if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
539   - return;
540   - }
541   - SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
  537 +
  538 + SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
542 539  
543 540 notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());
544 541  
... ... @@ -558,26 +555,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
558 555 sipURI.setHost(parentPlatform.getServerIP());
559 556 sipURI.setPort(parentPlatform.getServerPort());
560 557  
  558 +// ClientTransaction transaction = subscribeInfo.getClientTransaction();
  559 +// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {
  560 +// if ("TCP".equals(parentPlatform.getTransport())) {
  561 +// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
  562 +// } else if ("UDP".equals(parentPlatform.getTransport())) {
  563 +// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
  564 +// }
  565 +// }
  566 +
561 567 ClientTransaction transaction = null;
562 568 if ("TCP".equals(parentPlatform.getTransport())) {
563 569 transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
564 570 } else if ("UDP".equals(parentPlatform.getTransport())) {
565 571 transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
566 572 }
  573 +
567 574 // 添加错误订阅
568 575 if (errorEvent != null) {
569   - sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
  576 + sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);
570 577 }
571 578 // 添加订阅
572 579 if (okEvent != null) {
573   - sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
  580 + sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);
574 581 }
575   - if (transaction == null) {
576   - logger.error("平台{}的Transport错误:{}",parentPlatform.getServerGBId(), parentPlatform.getTransport());
577   - return;
578   - }
579   - dialog.sendRequest(transaction);
580   -
  582 + transaction.sendRequest();
  583 + return transaction;
581 584 }
582 585  
583 586 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
... ... @@ -753,7 +756,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
753 756 // callid
754 757 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
755 758 : udpSipProvider.getNewCallId();
756   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  759 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
757 760 transmitRequest(parentPlatform, request);
758 761  
759 762 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -772,36 +775,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
772 775 return false;
773 776 }
774 777  
775   - byte[] dialogByteArray = sendRtpItem.getDialog();
776   - if (dialogByteArray == null) {
777   - return false;
778   - }
779 778 try{
780   - SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray);
781   - SipStack sipStack;
782   - if ("TCP".equals(platform.getTransport())) {
783   - sipStack = tcpSipProvider.getSipStack();
784   - } else {
785   - sipStack = udpSipProvider.getSipStack();
786   - }
787   - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
788   - if (dialog != sipDialog) {
789   - dialog = sipDialog;
790   - }
791   - if ("TCP".equals(platform.getTransport())) {
792   - dialog.setSipProvider(tcpSipProvider);
793   - } else {
794   - dialog.setSipProvider(udpSipProvider);
795   - }
796   -
797   - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
798   - sipStackField.setAccessible(true);
799   - sipStackField.set(dialog, sipStack);
800   - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
801   - eventListenersField.setAccessible(true);
802   - eventListenersField.set(dialog, new HashSet<>());
803 779  
804   - SIPRequest messageRequest = (SIPRequest)dialog.createRequest(Request.MESSAGE);
805 780 String characterSet = platform.getCharacterSet();
806 781 StringBuffer mediaStatusXml = new StringBuffer(200);
807 782 mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
... ... @@ -811,6 +786,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
811 786 mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
812 787 mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
813 788 mediaStatusXml.append("</Notify>\r\n");
  789 +
  790 + SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
  791 + sendRtpItem);
  792 +
814 793 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
815 794 messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);
816 795 SipURI sipURI = (SipURI) messageRequest.getRequestURI();
... ... @@ -822,17 +801,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
822 801 }else {
823 802 clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
824 803 }
825   - dialog.sendRequest(clientTransaction);
  804 + clientTransaction.sendRequest();
826 805 } catch (SipException e) {
827 806 e.printStackTrace();
828 807 return false;
829 808 } catch (ParseException e) {
830 809 e.printStackTrace();
831 810 return false;
832   - } catch (NoSuchFieldException e) {
833   - e.printStackTrace();
834   - } catch (IllegalAccessException e) {
835   - e.printStackTrace();
  811 + } catch (InvalidArgumentException e) {
  812 + throw new RuntimeException(e);
836 813 }
837 814 return true;
838 815  
... ... @@ -846,61 +823,46 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
846 823 }
847 824 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platform.getServerGBId(), null, null, callId);
848 825 if (sendRtpItem != null) {
849   - String mediaServerId = sendRtpItem.getMediaServerId();
850   - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
851   - if (mediaServerItem != null) {
852   - mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
853   - zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
854   - }
855   - byte[] dialogByteArray = sendRtpItem.getDialog();
856   - if (dialogByteArray != null) {
857   - SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray);
858   - SipStack sipStack;
859   - if ("TCP".equals(platform.getTransport())) {
860   - sipStack = tcpSipProvider.getSipStack();
861   - } else {
862   - sipStack = udpSipProvider.getSipStack();
863   - }
864   - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
865   - if (dialog != sipDialog) {
866   - dialog = sipDialog;
867   - }
868   - try {
869   - if ("TCP".equals(platform.getTransport())) {
870   - dialog.setSipProvider(tcpSipProvider);
871   - } else {
872   - dialog.setSipProvider(udpSipProvider);
873   - }
874   - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
875   - sipStackField.setAccessible(true);
876   - sipStackField.set(dialog, sipStack);
877   - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
878   - eventListenersField.setAccessible(true);
879   - eventListenersField.set(dialog, new HashSet<>());
880   -
881   - Request byeRequest = dialog.createRequest(Request.BYE);
882   -
883   - SipURI byeURI = (SipURI) byeRequest.getRequestURI();
884   - byeURI.setHost(platform.getServerIP());
885   - byeURI.setPort(platform.getServerPort());
886   - ClientTransaction clientTransaction;
887   - if ("TCP".equals(platform.getTransport())) {
888   - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
889   - } else {
890   - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
891   - }
892   - dialog.sendRequest(clientTransaction);
893   - } catch (SipException e) {
894   - e.printStackTrace();
895   - } catch (ParseException e) {
896   - e.printStackTrace();
897   - } catch (NoSuchFieldException e) {
898   - e.printStackTrace();
899   - } catch (IllegalAccessException e) {
900   - e.printStackTrace();
901   - }
  826 + streamByeCmd(platform, sendRtpItem);
  827 + }
  828 + }
  829 +
  830 + @Override
  831 + public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) {
  832 + if (sendRtpItem == null ) {
  833 + logger.info("[向上级发送BYE], sendRtpItem 为NULL");
  834 + return;
  835 + }
  836 + if (platform == null) {
  837 + logger.info("[向上级发送BYE], platform 为NULL");
  838 + return;
  839 + }
  840 + logger.info("[向上级发送BYE], {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId());
  841 + String mediaServerId = sendRtpItem.getMediaServerId();
  842 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  843 + if (mediaServerItem != null) {
  844 + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
  845 + zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
  846 + }
  847 + try {
902 848  
  849 + SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
  850 + if (byeRequest == null) {
  851 + logger.warn("[向上级发送bye]:无法创建 byeRequest");
  852 + }
  853 + ClientTransaction clientTransaction;
  854 + if ("TCP".equals(platform.getTransport())) {
  855 + clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
  856 + } else {
  857 + clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
903 858 }
  859 + clientTransaction.sendRequest();
  860 + } catch (SipException e) {
  861 + e.printStackTrace();
  862 + } catch (ParseException e) {
  863 + e.printStackTrace();
  864 + } catch (InvalidArgumentException e) {
  865 + throw new RuntimeException(e);
904 866 }
905 867 }
906 868 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  4 +import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
4 5 import gov.nist.javax.sip.SipProviderImpl;
5 6 import gov.nist.javax.sip.SipStackImpl;
6 7 import gov.nist.javax.sip.message.SIPRequest;
  8 +import gov.nist.javax.sip.message.SIPResponse;
7 9 import gov.nist.javax.sip.stack.SIPServerTransaction;
8 10 import org.apache.commons.lang3.ArrayUtils;
9 11 import org.dom4j.Document;
... ... @@ -19,10 +21,7 @@ import javax.sip.*;
19 21 import javax.sip.address.Address;
20 22 import javax.sip.address.AddressFactory;
21 23 import javax.sip.address.SipURI;
22   -import javax.sip.header.ContentTypeHeader;
23   -import javax.sip.header.ExpiresHeader;
24   -import javax.sip.header.HeaderFactory;
25   -import javax.sip.header.ViaHeader;
  24 +import javax.sip.header.*;
26 25 import javax.sip.message.MessageFactory;
27 26 import javax.sip.message.Request;
28 27 import javax.sip.message.Response;
... ... @@ -59,9 +58,6 @@ public abstract class SIPRequestProcessorParent {
59 58 public ServerTransaction getServerTransaction(RequestEvent evt) {
60 59 Request request = evt.getRequest();
61 60 ServerTransaction serverTransaction = evt.getServerTransaction();
62   - if (serverTransaction != null) {
63   - System.out.println(serverTransaction.getState().toString());
64   - }
65 61 // 判断TCP还是UDP
66 62 boolean isTcp = false;
67 63 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
... ... @@ -123,105 +119,107 @@ public abstract class SIPRequestProcessorParent {
123 119 return null;
124 120 }
125 121  
  122 + class ResponseAckExtraParam{
  123 + String content;
  124 + ContentTypeHeader contentTypeHeader;
  125 + SipURI sipURI;
  126 + int expires = -1;
  127 + }
  128 +
126 129 /***
127 130 * 回复状态码
128 131 * 100 trying
129 132 * 200 OK
130 133 * 400
131 134 * 404
132   - * @param evt
133   - * @throws SipException
134   - * @throws InvalidArgumentException
135   - * @throws ParseException
136 135 */
137   - public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException {
138   - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
139   - ServerTransaction serverTransaction = getServerTransaction(evt);
140   - if (serverTransaction == null) {
141   - logger.warn("回复失败:{}", response);
142   - return;
  136 + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode) throws SipException, InvalidArgumentException, ParseException {
  137 + return responseAck(serverTransaction, statusCode, null);
  138 + }
  139 +
  140 + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
  141 + return responseAck(serverTransaction, statusCode, msg, null);
  142 + }
  143 +
  144 + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException {
  145 + ToHeader toHeader = (ToHeader) serverTransaction.getRequest().getHeader(ToHeader.NAME);
  146 + if (toHeader.getTag() == null) {
  147 + toHeader.setTag(SipUtils.getNewTag());
143 148 }
144   - serverTransaction.sendResponse(response);
145   - if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
  149 + SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, serverTransaction.getRequest());
  150 + if (msg != null) {
  151 + response.setReasonPhrase(msg);
  152 + }
  153 + if (responseAckExtraParam != null) {
  154 + if (responseAckExtraParam.sipURI != null && serverTransaction.getRequest().getMethod().equals(Request.INVITE)) {
  155 + logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
  156 + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(
  157 + SipFactory.getInstance().createAddressFactory().createSipURI(responseAckExtraParam.sipURI.getUser(), responseAckExtraParam.sipURI.getHost()+":"+responseAckExtraParam.sipURI.getPort()
  158 + ));
  159 + response.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
  160 + }
  161 + if (responseAckExtraParam.contentTypeHeader != null) {
  162 + response.setContent(responseAckExtraParam.content, responseAckExtraParam.contentTypeHeader);
  163 + }
146 164  
147   - if (serverTransaction.getDialog() != null) {
148   - serverTransaction.getDialog().delete();
  165 + if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
  166 + if (responseAckExtraParam.expires == -1) {
  167 + logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
  168 + }else {
  169 + ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(responseAckExtraParam.expires);
  170 + response.addHeader(expiresHeader);
  171 + }
  172 + }
  173 + }else {
  174 + if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
  175 + logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
149 176 }
150 177 }
151   - }
152   -
153   - public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
154   - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
155   - response.setReasonPhrase(msg);
156   - ServerTransaction serverTransaction = getServerTransaction(evt);
157 178 serverTransaction.sendResponse(response);
158   - if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
  179 + if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(serverTransaction.getRequest().getMethod())) {
159 180 if (serverTransaction.getDialog() != null) {
160 181 serverTransaction.getDialog().delete();
161 182 }
162 183 }
  184 + return response;
163 185 }
164 186  
165 187 /**
166 188 * 回复带sdp的200
167   - * @param evt
168   - * @param sdp
169   - * @throws SipException
170   - * @throws InvalidArgumentException
171   - * @throws ParseException
172 189 */
173   - public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
174   - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
175   - SipFactory sipFactory = SipFactory.getInstance();
176   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
177   - response.setContent(sdp, contentTypeHeader);
  190 + public SIPResponse responseSdpAck(ServerTransaction serverTransaction, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
  191 +
  192 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
178 193  
179 194 // 兼容国标中的使用编码@域名作为RequestURI的情况
180   - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
  195 + SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
181 196 if (sipURI.getPort() == -1) {
182   - sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
  197 + sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
183 198 }
184   - logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
  199 + ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam();
  200 + responseAckExtraParam.contentTypeHeader = contentTypeHeader;
  201 + responseAckExtraParam.content = sdp;
  202 + responseAckExtraParam.sipURI = sipURI;
185 203  
186   - Address concatAddress = sipFactory.createAddressFactory().createAddress(
187   - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
188   - ));
189   - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
190   - ServerTransaction serverTransaction = getServerTransaction(evt);
191   - if (serverTransaction == null) {
192   -
193   - }
194   - getServerTransaction(evt).sendResponse(response);
  204 + return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
195 205 }
196 206  
197 207 /**
198 208 * 回复带xml的200
199   - * @param evt
200   - * @param xml
201   - * @throws SipException
202   - * @throws InvalidArgumentException
203   - * @throws ParseException
204 209 */
205   - public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
206   - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
207   - SipFactory sipFactory = SipFactory.getInstance();
208   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
209   - response.setContent(xml, contentTypeHeader);
  210 + public SIPResponse responseXmlAck(ServerTransaction serverTransaction, String xml, ParentPlatform platform, Integer expires) throws SipException, InvalidArgumentException, ParseException {
  211 + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
210 212  
211   - // 兼容国标中的使用编码@域名作为RequestURI的情况
212   - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
  213 + SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
213 214 if (sipURI.getPort() == -1) {
214   - sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
  215 + sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
215 216 }
216   - logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
217   -
218   - Address concatAddress = sipFactory.createAddressFactory().createAddress(
219   - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
220   - ));
221   - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
222   - response.addHeader(evt.getRequest().getHeader(ExpiresHeader.NAME));
223   - getServerTransaction(evt).sendResponse(response);
224   - return response;
  217 + ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam();
  218 + responseAckExtraParam.contentTypeHeader = contentTypeHeader;
  219 + responseAckExtraParam.content = xml;
  220 + responseAckExtraParam.sipURI = sipURI;
  221 + responseAckExtraParam.expires = expires;
  222 + return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
225 223 }
226 224  
227 225 public Element getRootElement(RequestEvent evt) throws DocumentException {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
... ... @@ -87,53 +87,46 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
87 87 */
88 88 @Override
89 89 public void process(RequestEvent evt) {
90   - Dialog dialog = evt.getDialog();
91 90 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
92   - if (dialog == null) {
93   - return;
  91 +
  92 + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
  93 + logger.info("[收到ACK]: platformGbId->{}", platformGbId);
  94 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
  95 + // 取消设置的超时任务
  96 + dynamicTask.stop(callIdHeader.getCallId());
  97 + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
  98 + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
  99 + String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
  100 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  101 + logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
  102 + Map<String, Object> param = new HashMap<>();
  103 + param.put("vhost","__defaultVhost__");
  104 + param.put("app",sendRtpItem.getApp());
  105 + param.put("stream",sendRtpItem.getStreamId());
  106 + param.put("ssrc", sendRtpItem.getSsrc());
  107 + param.put("dst_url",sendRtpItem.getIp());
  108 + param.put("dst_port", sendRtpItem.getPort());
  109 + param.put("is_udp", is_Udp);
  110 + param.put("src_port", sendRtpItem.getLocalPort());
  111 + param.put("pt", sendRtpItem.getPt());
  112 + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
  113 + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
  114 + if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
  115 + // 开启rtcp保活
  116 + param.put("udp_rtcp_timeout", "1");
94 117 }
95   - if (dialog.getState()== DialogState.CONFIRMED) {
96   - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
97   - logger.info("ACK请求: platformGbId->{}", platformGbId);
98   - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
99   - // 取消设置的超时任务
100   - dynamicTask.stop(callIdHeader.getCallId());
101   - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
102   - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
103   - String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
104   - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
105   - logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
106   - Map<String, Object> param = new HashMap<>();
107   - param.put("vhost","__defaultVhost__");
108   - param.put("app",sendRtpItem.getApp());
109   - param.put("stream",sendRtpItem.getStreamId());
110   - param.put("ssrc", sendRtpItem.getSsrc());
111   - param.put("dst_url",sendRtpItem.getIp());
112   - param.put("dst_port", sendRtpItem.getPort());
113   - param.put("is_udp", is_Udp);
114   - param.put("src_port", sendRtpItem.getLocalPort());
115   - param.put("pt", sendRtpItem.getPt());
116   - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
117   - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
118   - if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
119   - // 开启rtcp保活
120   - param.put("udp_rtcp_timeout", "1");
121   - }
122 118  
123   - if (mediaInfo == null) {
124   - RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
125   - sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(),
126   - sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(),
127   - sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio());
128   - redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{
129   - startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
130   - });
131   - }else {
132   - JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
  119 + if (mediaInfo == null) {
  120 + RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
  121 + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(),
  122 + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(),
  123 + sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio());
  124 + redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{
133 125 startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
134   - }
135   -
136   -
  126 + });
  127 + }else {
  128 + JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
  129 + startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
137 130 }
138 131 }
139 132 private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform,
... ... @@ -141,12 +134,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
141 134 if (jsonObject == null) {
142 135 logger.error("RTP推流失败: 请检查ZLM服务");
143 136 } else if (jsonObject.getInteger("code") == 0) {
  137 + logger.info("调用ZLM推流接口, 结果: {}", jsonObject);
144 138 logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
145   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
146   - sendRtpItem.setDialog(dialogByteArray);
147   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
148   - sendRtpItem.setTransaction(transactionByteArray);
149   - redisCatchStorage.updateSendRTPSever(sendRtpItem);
150 139 } else {
151 140 logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
152 141 if (sendRtpItem.isOnlyAudio()) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
... ... @@ -78,72 +78,66 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
78 78 @Override
79 79 public void process(RequestEvent evt) {
80 80 try {
81   - responseAck(evt, Response.OK);
82   - Dialog dialog = evt.getDialog();
  81 + responseAck(getServerTransaction(evt), Response.OK);
83 82 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
84   - if (dialog == null) {
85   - return;
86   - }
87   - if (dialog.getState().equals(DialogState.TERMINATED)) {
88   - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
89   - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
90   - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
91   - logger.info("收到bye, [{}/{}]", platformGbId, channelId);
92   - if (sendRtpItem != null){
93   - String streamId = sendRtpItem.getStreamId();
94   - Map<String, Object> param = new HashMap<>();
95   - param.put("vhost","__defaultVhost__");
96   - param.put("app",sendRtpItem.getApp());
97   - param.put("stream",streamId);
98   - param.put("ssrc",sendRtpItem.getSsrc());
99   - logger.info("收到bye:停止向上级推流:" + streamId);
100   - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
101   - redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
102   - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
103   - int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
104   - if (totalReaderCount <= 0) {
105   - logger.info("收到bye: {} 无其它观看者,通知设备停止推流", streamId);
106   - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
107   - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null);
108   - }
109   - if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
110   - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
111   - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
112   - sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
113   - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
114   - }
  83 + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
  84 + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
  85 + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
  86 + logger.info("[收到bye] {}/{}", platformGbId, channelId);
  87 + if (sendRtpItem != null){
  88 + String streamId = sendRtpItem.getStreamId();
  89 + Map<String, Object> param = new HashMap<>();
  90 + param.put("vhost","__defaultVhost__");
  91 + param.put("app",sendRtpItem.getApp());
  92 + param.put("stream",streamId);
  93 + param.put("ssrc",sendRtpItem.getSsrc());
  94 + logger.info("[收到bye] 停止向上级推流:{}", streamId);
  95 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  96 + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
  97 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
  98 + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
  99 + if (totalReaderCount <= 0) {
  100 + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
  101 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
  102 + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null);
115 103 }
116   - }
117   - // 可能是设备主动停止
118   - Device device = storager.queryVideoDeviceByChannelId(platformGbId);
119   - if (device != null) {
120   - storager.stopPlay(device.getDeviceId(), channelId);
121   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
122   - if (streamInfo != null) {
123   - redisCatchStorage.stopPlay(streamInfo);
124   - mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
125   - }
126   - SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
127   - if (ssrcTransactionForPlay != null){
128   - SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
129   - if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
130   - // 释放ssrc
131   - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
132   - if (mediaServerItem != null) {
133   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
134   - }
135   - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
136   - }
  104 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
  105 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  106 + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
  107 + sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
  108 + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
137 109 }
138   - SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
139   - if (ssrcTransactionForPlayBack != null) {
  110 + }
  111 + }
  112 + // 可能是设备主动停止
  113 + Device device = storager.queryVideoDeviceByChannelId(platformGbId);
  114 + if (device != null) {
  115 + storager.stopPlay(device.getDeviceId(), channelId);
  116 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
  117 + if (streamInfo != null) {
  118 + redisCatchStorage.stopPlay(streamInfo);
  119 + mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
  120 + }
  121 + SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
  122 + if (ssrcTransactionForPlay != null){
  123 + SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
  124 + if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
140 125 // 释放ssrc
141   - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
  126 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
142 127 if (mediaServerItem != null) {
143   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
  128 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
144 129 }
145   - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
  130 + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
  131 + }
  132 + }
  133 + SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
  134 + if (ssrcTransactionForPlayBack != null) {
  135 + // 释放ssrc
  136 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
  137 + if (mediaServerItem != null) {
  138 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
146 139 }
  140 + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
147 141 }
148 142 }
149 143 } catch (SipException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -8,7 +8,6 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
8 8 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
9 9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
10 10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
11   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
12 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
13 12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
14 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
... ... @@ -28,9 +27,10 @@ import com.genersoft.iot.vmp.service.impl.RedisPushStreamResponseListener;
28 27 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
29 28 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
30 29 import com.genersoft.iot.vmp.utils.DateUtil;
31   -import com.genersoft.iot.vmp.utils.SerializeUtils;
32 30 import gov.nist.javax.sdp.TimeDescriptionImpl;
33 31 import gov.nist.javax.sdp.fields.TimeField;
  32 +import gov.nist.javax.sip.message.SIPRequest;
  33 +import gov.nist.javax.sip.message.SIPResponse;
34 34 import org.slf4j.Logger;
35 35 import org.slf4j.LoggerFactory;
36 36 import org.springframework.beans.factory.InitializingBean;
... ... @@ -128,17 +128,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
128 128 String channelId = SipUtils.getChannelIdFromRequest(request);
129 129 String requesterId = SipUtils.getUserIdFromFromHeader(request);
130 130 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
  131 + ServerTransaction serverTransaction = getServerTransaction(evt);
131 132 if (requesterId == null || channelId == null) {
132 133 logger.info("无法从FromHeader的Address中获取到平台id,返回400");
133 134 // 参数不全, 发400,请求错误
134   - responseAck(evt, Response.BAD_REQUEST);
  135 + responseAck(serverTransaction, Response.BAD_REQUEST);
135 136 return;
136 137 }
137 138  
  139 +
138 140 // 查询请求是否来自上级平台\设备
139 141 ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
140 142 if (platform == null) {
141   - inviteFromDeviceHandle(evt, requesterId);
  143 + inviteFromDeviceHandle(serverTransaction, requesterId);
142 144 } else {
143 145 // 查询平台下是否有该通道
144 146 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
... ... @@ -150,12 +152,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
150 152 StreamProxyItem proxyByAppAndStream =null;
151 153 // 不是通道可能是直播流
152 154 if (channel != null && gbStream == null) {
153   - if (channel.getStatus() == 0) {
154   - logger.info("通道离线,返回400");
155   - responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
156   - return;
157   - }
158   - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
  155 +// if (channel.getStatus() == 0) {
  156 +// logger.info("通道离线,返回400");
  157 +// responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
  158 +// return;
  159 +// }
  160 + // 通道存在,发100,TRYING
  161 + responseAck(serverTransaction, Response.TRYING);
159 162 } else if (channel == null && gbStream != null) {
160 163  
161 164 String mediaServerId = gbStream.getMediaServerId();
... ... @@ -163,13 +166,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
163 166 if (mediaServerItem == null) {
164 167 if ("proxy".equals(gbStream.getStreamType())) {
165 168 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
166   - responseAck(evt, Response.GONE);
  169 + responseAck(serverTransaction, Response.GONE);
167 170 return;
168 171 } else {
169 172 streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
170 173 if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) {
171 174 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
172   - responseAck(evt, Response.GONE);
  175 + responseAck(serverTransaction, Response.GONE);
173 176 return;
174 177 }
175 178 }
... ... @@ -178,25 +181,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
178 181 streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
179 182 if (streamPushItem == null) {
180 183 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
181   - responseAck(evt, Response.GONE);
  184 + responseAck(serverTransaction, Response.GONE);
182 185 return;
183 186 }
184 187 }else if("proxy".equals(gbStream.getStreamType())){
185 188 proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
186 189 if (proxyByAppAndStream == null) {
187 190 logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
188   - responseAck(evt, Response.GONE);
  191 + responseAck(serverTransaction, Response.GONE);
189 192 return;
190 193 }
191 194 }
192 195 }
193   - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
  196 + responseAck(serverTransaction, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
194 197 } else if (catalog != null) {
195   - responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播
  198 + responseAck(serverTransaction, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播
196 199 return;
197 200 } else {
198 201 logger.info("通道不存在,返回404");
199   - responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
  202 + responseAck(serverTransaction, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
200 203 return;
201 204 }
202 205 // 解析sdp消息, 使用jainsip 自带的sdp解析方式
... ... @@ -209,7 +212,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
209 212 String ssrc;
210 213 SessionDescription sdp;
211 214 if (ssrcIndex >= 0) {
212   - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
  215 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
213 216 ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
214 217 String substring = contentString.substring(0, contentString.indexOf("y="));
215 218 sdp = SdpFactory.getInstance().createSessionDescription(substring);
... ... @@ -256,9 +259,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
256 259 mediaTransmissionTCP = true;
257 260 if ("active".equalsIgnoreCase(setup)) {
258 261 tcpActive = true;
259   - // 不支持tcp主动
260   - responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 目录不支持点播
261   - return;
262 262 } else if ("passive".equalsIgnoreCase(setup)) {
263 263 tcpActive = false;
264 264 }
... ... @@ -270,7 +270,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
270 270 if (port == -1) {
271 271 logger.info("不支持的媒体格式,返回415");
272 272 // 回复不支持的格式
273   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
  273 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
274 274 return;
275 275 }
276 276 String username = sdp.getOrigin().getUsername();
... ... @@ -283,24 +283,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
283 283 device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
284 284 if (device == null) {
285 285 logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel);
286   - responseAck(evt, Response.SERVER_INTERNAL_ERROR);
  286 + responseAck(serverTransaction, Response.SERVER_INTERNAL_ERROR);
287 287 return;
288 288 }
289 289 mediaServerItem = playService.getNewMediaServerItem(device);
290 290 if (mediaServerItem == null) {
291 291 logger.warn("未找到可用的zlm");
292   - responseAck(evt, Response.BUSY_HERE);
  292 + responseAck(serverTransaction, Response.BUSY_HERE);
293 293 return;
294 294 }
295 295 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
296 296 device.getDeviceId(), channelId,
297 297 mediaTransmissionTCP);
  298 +
298 299 if (tcpActive != null) {
299 300 sendRtpItem.setTcpActive(tcpActive);
300 301 }
301 302 if (sendRtpItem == null) {
302 303 logger.warn("服务器端口资源不足");
303   - responseAck(evt, Response.BUSY_HERE);
  304 + responseAck(serverTransaction, Response.BUSY_HERE);
304 305 return;
305 306 }
306 307 sendRtpItem.setCallId(callIdHeader.getCallId());
... ... @@ -342,7 +343,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
342 343 // 回复bye
343 344 cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
344 345 }, 60 * 1000);
345   - responseSdpAck(evt, content.toString(), platform);
  346 + responseSdpAck(serverTransaction, content.toString(), platform);
346 347  
347 348 } catch (SipException e) {
348 349 e.printStackTrace();
... ... @@ -357,8 +358,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
357 358 Response response = null;
358 359 try {
359 360 response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
360   - ServerTransaction serverTransaction = getServerTransaction(evt);
361 361 serverTransaction.sendResponse(response);
  362 + System.out.println("未知错误。直接转发设备点播的错误");
362 363 if (serverTransaction.getDialog() != null) {
363 364 serverTransaction.getDialog().delete();
364 365 }
... ... @@ -382,7 +383,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
382 383 }
383 384 redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
384 385 try {
385   - responseAck(evt, Response.REQUEST_TIMEOUT);
  386 + responseAck(serverTransaction, Response.REQUEST_TIMEOUT);
386 387 } catch (SipException e) {
387 388 e.printStackTrace();
388 389 } catch (InvalidArgumentException e) {
... ... @@ -420,6 +421,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
420 421 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
421 422 logger.info(JSONObject.toJSONString(ssrcInfo));
422 423 sendRtpItem.setStreamId(ssrcInfo.getStream());
  424 +
423 425 // 写入redis, 超时时回复
424 426 redisCatchStorage.updateSendRTPSever(sendRtpItem);
425 427 playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> {
... ... @@ -440,26 +442,26 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
440 442 if("push".equals(gbStream.getStreamType())) {
441 443 if (streamPushItem != null && streamPushItem.isPushIng()) {
442 444 // 推流状态
443   - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  445 + pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
444 446 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
445 447 } else {
446 448 // 未推流 拉起
447   - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  449 + notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
448 450 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
449 451 }
450 452 }else if ("proxy".equals(gbStream.getStreamType())){
451 453 if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){
452   - pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  454 + pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
453 455 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
454 456 }else{
455 457 //开启代理拉流
456 458 boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
457 459 if(start1) {
458   - pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  460 + pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
459 461 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
460 462 }else{
461 463 //失败后通知
462   - notifyStreamOnline(evt, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
  464 + notifyStreamOnline(evt, serverTransaction,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
463 465 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
464 466 }
465 467 }
... ... @@ -482,7 +484,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
482 484 /**
483 485 * 安排推流
484 486 */
485   - private void pushProxyStream(RequestEvent evt, GbStream gbStream, ParentPlatform platform,
  487 + private void pushProxyStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, ParentPlatform platform,
486 488 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
487 489 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
488 490 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
... ... @@ -495,7 +497,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
495 497  
496 498 if (sendRtpItem == null) {
497 499 logger.warn("服务器端口资源不足");
498   - responseAck(evt, Response.BUSY_HERE);
  500 + responseAck(serverTransaction, Response.BUSY_HERE);
499 501 return;
500 502 }
501 503 if (tcpActive != null) {
... ... @@ -505,17 +507,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
505 507 // 写入redis, 超时时回复
506 508 sendRtpItem.setStatus(1);
507 509 sendRtpItem.setCallId(callIdHeader.getCallId());
508   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
509   - sendRtpItem.setDialog(dialogByteArray);
510   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
511   - sendRtpItem.setTransaction(transactionByteArray);
  510 + SIPRequest request = (SIPRequest) evt.getRequest();
  511 + sendRtpItem.setFromTag(request.getFromTag());
  512 +
  513 + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
  514 + if (response != null) {
  515 + sendRtpItem.setToTag(response.getToTag());
  516 + }
512 517 redisCatchStorage.updateSendRTPSever(sendRtpItem);
513   - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
514 518  
515 519 }
516 520  
517 521 }
518   - private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
  522 + private void pushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
519 523 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
520 524 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
521 525 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
... ... @@ -530,7 +534,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
530 534  
531 535 if (sendRtpItem == null) {
532 536 logger.warn("服务器端口资源不足");
533   - responseAck(evt, Response.BUSY_HERE);
  537 + responseAck(serverTransaction, Response.BUSY_HERE);
534 538 return;
535 539 }
536 540 if (tcpActive != null) {
... ... @@ -540,39 +544,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
540 544 // 写入redis, 超时时回复
541 545 sendRtpItem.setStatus(1);
542 546 sendRtpItem.setCallId(callIdHeader.getCallId());
543   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
544   - sendRtpItem.setDialog(dialogByteArray);
545   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
546   - sendRtpItem.setTransaction(transactionByteArray);
  547 +
  548 + SIPRequest request = (SIPRequest) evt.getRequest();
  549 + sendRtpItem.setFromTag(request.getFromTag());
  550 + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
  551 + if (response != null) {
  552 + sendRtpItem.setToTag(response.getToTag());
  553 + }
  554 +
547 555 redisCatchStorage.updateSendRTPSever(sendRtpItem);
548   - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
  556 +
549 557 } else {
550 558 // 不在线 拉起
551   - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  559 + notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
552 560 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
553 561 }
554 562  
555 563 } else {
556 564 // 其他平台内容
557   - otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  565 + otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
558 566 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
559 567 }
560 568 }
561 569 /**
562 570 * 通知流上线
563 571 */
564   - private void notifyStreamOnline(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
  572 + private void notifyStreamOnline(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
565 573 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
566 574 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
567 575 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
568 576 if ("proxy".equals(gbStream.getStreamType())) {
569 577 // TODO 控制启用以使设备上线
570 578 logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream());
571   - responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
  579 + responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
572 580 } else if ("push".equals(gbStream.getStreamType())) {
573 581 if (!platform.isStartOfflinePush()) {
574 582 // 平台设置中关闭了拉起离线的推流则直接回复
575   - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
  583 + responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
576 584 return;
577 585 }
578 586 // 发送redis消息以使设备上线
... ... @@ -587,7 +595,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
587 595 logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
588 596 try {
589 597 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
590   - responseAck(evt, Response.REQUEST_TIMEOUT); // 超时
  598 + responseAck(serverTransaction, Response.REQUEST_TIMEOUT); // 超时
591 599 } catch (SipException e) {
592 600 e.printStackTrace();
593 601 } catch (InvalidArgumentException e) {
... ... @@ -610,7 +618,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
610 618 if (sendRtpItem == null) {
611 619 logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
612 620 try {
613   - responseAck(evt, Response.BUSY_HERE);
  621 + responseAck(serverTransaction, Response.BUSY_HERE);
614 622 } catch (SipException e) {
615 623 e.printStackTrace();
616 624 } catch (InvalidArgumentException e) {
... ... @@ -627,15 +635,17 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
627 635 // 写入redis, 超时时回复
628 636 sendRtpItem.setStatus(1);
629 637 sendRtpItem.setCallId(callIdHeader.getCallId());
630   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
631   - sendRtpItem.setDialog(dialogByteArray);
632   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
633   - sendRtpItem.setTransaction(transactionByteArray);
  638 +
  639 + SIPRequest request = (SIPRequest) evt.getRequest();
  640 + sendRtpItem.setFromTag(request.getFromTag());
  641 + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
  642 + if (response != null) {
  643 + sendRtpItem.setToTag(response.getToTag());
  644 + }
634 645 redisCatchStorage.updateSendRTPSever(sendRtpItem);
635   - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
636 646 } else {
637 647 // 其他平台内容
638   - otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  648 + otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
639 649 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
640 650 }
641 651 });
... ... @@ -646,7 +656,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
646 656 dynamicTask.stop(callIdHeader.getCallId());
647 657 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
648 658 try {
649   - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
  659 + responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
650 660 } catch (SipException e) {
651 661 throw new RuntimeException(e);
652 662 } catch (InvalidArgumentException e) {
... ... @@ -662,7 +672,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
662 672 /**
663 673 * 来自其他wvp的推流
664 674 */
665   - private void otherWvpPushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
  675 + private void otherWvpPushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
666 676 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
667 677 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
668 678 String channelId, String addressStr, String ssrc, String requesterId) {
... ... @@ -675,7 +685,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
675 685 if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
676 686 logger.warn("服务器端口资源不足");
677 687 try {
678   - responseAck(evt, Response.BUSY_HERE);
  688 + responseAck(serverTransaction, Response.BUSY_HERE);
679 689 } catch (SipException e) {
680 690 e.printStackTrace();
681 691 } catch (InvalidArgumentException e) {
... ... @@ -693,12 +703,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
693 703 // 写入redis, 超时时回复
694 704 sendRtpItem.setStatus(1);
695 705 sendRtpItem.setCallId(callIdHeader.getCallId());
696   - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
697   - sendRtpItem.setDialog(dialogByteArray);
698   - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
699   - sendRtpItem.setTransaction(transactionByteArray);
  706 +
  707 + SIPRequest request = (SIPRequest) evt.getRequest();
  708 + sendRtpItem.setFromTag(request.getFromTag());
  709 + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), serverTransaction,sendRtpItem, platform, evt);
  710 + if (response != null) {
  711 + sendRtpItem.setToTag(response.getToTag());
  712 + }
700 713 redisCatchStorage.updateSendRTPSever(sendRtpItem);
701   - sendStreamAck(responseSendItemMsg.getMediaServerItem(), sendRtpItem, platform, evt);
702 714 }, (wvpResult) -> {
703 715 try {
704 716 // 错误
... ... @@ -708,12 +720,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
708 720 StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
709 721 if (currentStreamPushItem.isPushIng()) {
710 722 // 在线状态
711   - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  723 + pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
712 724 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
713 725  
714 726 } else {
715 727 // 不在线 拉起
716   - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  728 + notifyStreamOnline(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
717 729 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
718 730 }
719 731 }
... ... @@ -727,7 +739,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
727 739  
728 740  
729 741 try {
730   - responseAck(evt, Response.BUSY_HERE);
  742 + responseAck(serverTransaction, Response.BUSY_HERE);
731 743 } catch (SipException e) {
732 744 e.printStackTrace();
733 745 } catch (InvalidArgumentException e) {
... ... @@ -739,7 +751,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
739 751 });
740 752 }
741 753  
742   - public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
  754 + public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, ServerTransaction serverTransaction, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
743 755  
744 756 StringBuffer content = new StringBuffer(200);
745 757 content.append("v=0\r\n");
... ... @@ -762,7 +774,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
762 774 content.append("f=\r\n");
763 775  
764 776 try {
765   - responseSdpAck(evt, content.toString(), platform);
  777 + return responseSdpAck(serverTransaction, content.toString(), platform);
766 778 } catch (SipException e) {
767 779 e.printStackTrace();
768 780 } catch (InvalidArgumentException e) {
... ... @@ -770,18 +782,18 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
770 782 } catch (ParseException e) {
771 783 e.printStackTrace();
772 784 }
  785 + return null;
773 786 }
774 787  
775   - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException {
  788 + public void inviteFromDeviceHandle(ServerTransaction serverTransaction, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException {
776 789  
777 790 // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
778 791 Device device = redisCatchStorage.getDevice(requesterId);
779   - Request request = evt.getRequest();
780 792 if (device != null) {
781 793 logger.info("收到设备" + requesterId + "的语音广播Invite请求");
782   - responseAck(evt, Response.TRYING);
  794 + responseAck(serverTransaction, Response.TRYING);
783 795  
784   - String contentString = new String(request.getRawContent());
  796 + String contentString = new String(serverTransaction.getRequest().getRawContent());
785 797 // jainSip不支持y=字段, 移除移除以解析。
786 798 String substring = contentString;
787 799 String ssrc = "0000000404";
... ... @@ -829,7 +841,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
829 841 if (port == -1) {
830 842 logger.info("不支持的媒体格式,返回415");
831 843 // 回复不支持的格式
832   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
  844 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
833 845 return;
834 846 }
835 847 String username = sdp.getOrigin().getUsername();
... ... @@ -838,7 +850,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
838 850  
839 851 } else {
840 852 logger.warn("来自无效设备/平台的请求");
841   - responseAck(evt, Response.BAD_REQUEST);
  853 + responseAck(serverTransaction, Response.BAD_REQUEST);
842 854 }
843 855 }
844 856 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
... ... @@ -34,6 +34,7 @@ import org.springframework.util.StringUtils;
34 34  
35 35 import javax.sip.InvalidArgumentException;
36 36 import javax.sip.RequestEvent;
  37 +import javax.sip.ServerTransaction;
37 38 import javax.sip.SipException;
38 39 import javax.sip.header.FromHeader;
39 40 import javax.sip.message.Response;
... ... @@ -94,7 +95,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
94 95 public void process(RequestEvent evt) {
95 96 try {
96 97 taskQueue.offer(new HandlerCatchData(evt, null, null));
97   - responseAck(evt, Response.OK);
  98 + ServerTransaction serverTransaction = getServerTransaction(evt);
  99 + responseAck(serverTransaction, Response.OK);
98 100 if (!taskQueueHandlerRun) {
99 101 taskQueueHandlerRun = true;
100 102 taskExecutor.execute(()-> {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
... ... @@ -17,6 +17,12 @@ import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
17 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
18 18 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
19 19 import gov.nist.javax.sip.SipProviderImpl;
  20 +import gov.nist.javax.sip.message.SIPRequest;
  21 +import gov.nist.javax.sip.message.SIPResponse;
  22 +import gov.nist.javax.sip.stack.SIPClientTransaction;
  23 +import gov.nist.javax.sip.stack.SIPDialog;
  24 +import gov.nist.javax.sip.stack.SIPServerTransaction;
  25 +import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
20 26 import org.dom4j.DocumentException;
21 27 import org.dom4j.Element;
22 28 import org.slf4j.Logger;
... ... @@ -49,22 +55,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
49 55 @Autowired
50 56 private IVideoManagerStorage storager;
51 57  
52   - @Lazy
53   - @Autowired
54   - @Qualifier(value="tcpSipProvider")
55   - private SipProviderImpl tcpSipProvider;
56   -
57   - @Lazy
58   - @Autowired
59   - @Qualifier(value="udpSipProvider")
60   - private SipProviderImpl udpSipProvider;
61   -
62   - @Autowired
63   - private DynamicTask dynamicTask;
64   -
65   - @Autowired
66   - private UserSetting userSetting;
67   -
68 58 @Autowired
69 59 private SubscribeHolder subscribeHolder;
70 60  
... ... @@ -81,6 +71,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
81 71 */
82 72 @Override
83 73 public void process(RequestEvent evt) {
  74 + ServerTransaction serverTransaction = getServerTransaction(evt);
84 75 Request request = evt.getRequest();
85 76 try {
86 77 Element rootElement = getRootElement(evt);
... ... @@ -90,12 +81,12 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
90 81 }
91 82 String cmd = XmlUtil.getText(rootElement, "CmdType");
92 83 if (CmdType.MOBILE_POSITION.equals(cmd)) {
93   - processNotifyMobilePosition(evt, rootElement);
  84 + processNotifyMobilePosition(serverTransaction, rootElement);
94 85 // } else if (CmdType.ALARM.equals(cmd)) {
95 86 // logger.info("接收到Alarm订阅");
96   -// processNotifyAlarm(evt, rootElement);
  87 +// processNotifyAlarm(serverTransaction, rootElement);
97 88 } else if (CmdType.CATALOG.equals(cmd)) {
98   - processNotifyCatalogList(evt, rootElement);
  89 + processNotifyCatalogList(serverTransaction, rootElement);
99 90 } else {
100 91 logger.info("接收到消息:" + cmd);
101 92  
... ... @@ -108,7 +99,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
108 99 ServerTransaction transaction = getServerTransaction(evt);
109 100 if (transaction != null) {
110 101 transaction.sendResponse(response);
111   - transaction.getDialog().delete();
112 102 transaction.terminate();
113 103 } else {
114 104 logger.info("processRequest serverTransactionId is null.");
... ... @@ -123,24 +113,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
123 113 /**
124 114 * 处理移动位置订阅消息
125 115 */
126   - private void processNotifyMobilePosition(RequestEvent evt, Element rootElement) throws SipException {
127   - String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
  116 + private void processNotifyMobilePosition(ServerTransaction serverTransaction, Element rootElement) throws SipException {
  117 + if (serverTransaction == null) {
  118 + return;
  119 + }
  120 + String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
128 121 String deviceId = XmlUtil.getText(rootElement, "DeviceID");
129 122 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
130   - SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
  123 + SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
131 124 if (platform == null) {
132 125 return;
133 126 }
134   - if (evt.getServerTransaction() == null) {
135   - ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
136   - : udpSipProvider.getNewServerTransaction(evt.getRequest());
137   - subscribeInfo.setTransaction(serverTransaction);
138   - Dialog dialog = serverTransaction.getDialog();
139   - dialog.terminateOnBye(false);
140   - subscribeInfo.setDialog(dialog);
141   - }
  127 +
142 128 String sn = XmlUtil.getText(rootElement, "SN");
143   - logger.info("[回复 移动位置订阅]: {}", platformId);
  129 + logger.info("[回复上级的移动位置订阅请求]: {}", platformId);
144 130 StringBuilder resultXml = new StringBuilder(200);
145 131 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
146 132 .append("<Response>\r\n")
... ... @@ -158,17 +144,19 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
158 144 }else {
159 145 subscribeInfo.setGpsInterval(Integer.parseInt(interval));
160 146 }
161   -
162 147 subscribeInfo.setSn(sn);
163   - subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
164   -
165   - }else if (subscribeInfo.getExpires() == 0) {
166   - subscribeHolder.removeMobilePositionSubscribe(platformId);
167 148 }
168 149  
169 150 try {
170 151 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
171   - responseXmlAck(evt, resultXml.toString(), parentPlatform);
  152 + SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
  153 + if (subscribeInfo.getExpires() == 0) {
  154 + subscribeHolder.removeMobilePositionSubscribe(platformId);
  155 + }else {
  156 + subscribeInfo.setResponse(response);
  157 + subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
  158 + }
  159 +
172 160 } catch (SipException | InvalidArgumentException | ParseException e) {
173 161 e.printStackTrace();
174 162 }
... ... @@ -178,25 +166,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
178 166  
179 167 }
180 168  
181   - private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException {
182   -
183   - String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
  169 + private void processNotifyCatalogList(ServerTransaction serverTransaction, Element rootElement) throws SipException {
  170 + if (serverTransaction == null) {
  171 + return;
  172 + }
  173 + String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
184 174 String deviceId = XmlUtil.getText(rootElement, "DeviceID");
185 175 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
186 176 if (platform == null){
187 177 return;
188 178 }
189   - SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
190   - if (evt.getServerTransaction() == null) {
191   - ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
192   - : udpSipProvider.getNewServerTransaction(evt.getRequest());
193   - subscribeInfo.setTransaction(serverTransaction);
194   - Dialog dialog = serverTransaction.getDialog();
195   - dialog.terminateOnBye(false);
196   - subscribeInfo.setDialog(dialog);
197   - }
  179 + SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
  180 +
198 181 String sn = XmlUtil.getText(rootElement, "SN");
199   - logger.info("[回复 目录订阅]: {}/{}", platformId, deviceId);
  182 + logger.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId);
200 183 StringBuilder resultXml = new StringBuilder(200);
201 184 resultXml.append("<?xml version=\"1.0\" ?>\r\n")
202 185 .append("<Response>\r\n")
... ... @@ -213,7 +196,13 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
213 196 }
214 197 try {
215 198 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
216   - responseXmlAck(evt, resultXml.toString(), parentPlatform);
  199 + SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
  200 + if (subscribeInfo.getExpires() == 0) {
  201 + subscribeHolder.removeCatalogSubscribe(platformId);
  202 + }else {
  203 + subscribeInfo.setResponse(response);
  204 + subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
  205 + }
217 206 } catch (SipException | InvalidArgumentException | ParseException e) {
218 207 e.printStackTrace();
219 208 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
... ... @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
19 19 import org.springframework.stereotype.Component;
20 20 import javax.sip.InvalidArgumentException;
21 21 import javax.sip.RequestEvent;
  22 +import javax.sip.ServerTransaction;
22 23 import javax.sip.SipException;
23 24 import javax.sip.header.*;
24 25 import javax.sip.message.Response;
... ... @@ -65,9 +66,12 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
65 66 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
66 67 // 先从会话内查找
67 68 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
68   - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
  69 +
  70 + // 兼容海康 媒体通知 消息from字段不是设备ID的问题
  71 + if (ssrcTransaction != null) {
69 72 deviceId = ssrcTransaction.getDeviceId();
70 73 }
  74 + ServerTransaction serverTransaction = getServerTransaction(evt);
71 75 // 查询设备是否存在
72 76 Device device = redisCatchStorage.getDevice(deviceId);
73 77 // 查询上级平台是否存在
... ... @@ -86,7 +90,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
86 90 }
87 91 if (device == null && parentPlatform == null) {
88 92 // 不存在则回复404
89   - responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found");
  93 + responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
90 94 logger.warn("[设备未找到 ]: {}", deviceId);
91 95 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
92 96 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
... ... @@ -101,14 +105,14 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
101 105 String streamId = sendRtpItem.getStreamId();
102 106 StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
103 107 if (null == streamInfo) {
104   - responseAck(evt, Response.NOT_FOUND, "stream " + streamId + " not found");
  108 + responseAck(serverTransaction, Response.NOT_FOUND, "stream " + streamId + " not found");
105 109 return;
106 110 }
107 111 Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID());
108 112 cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> {
109 113 // 失败的回复
110 114 try {
111   - responseAck(evt, eventResult.statusCode, eventResult.msg);
  115 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
112 116 } catch (SipException e) {
113 117 e.printStackTrace();
114 118 } catch (InvalidArgumentException e) {
... ... @@ -119,7 +123,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
119 123 }, eventResult -> {
120 124 // 成功的回复
121 125 try {
122   - responseAck(evt, eventResult.statusCode);
  126 + responseAck(serverTransaction, eventResult.statusCode);
123 127 } catch (SipException e) {
124 128 e.printStackTrace();
125 129 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
... ... @@ -23,6 +23,7 @@ import org.springframework.stereotype.Component;
23 23  
24 24 import javax.sip.InvalidArgumentException;
25 25 import javax.sip.RequestEvent;
  26 +import javax.sip.ServerTransaction;
26 27 import javax.sip.SipException;
27 28 import javax.sip.address.SipURI;
28 29 import javax.sip.header.CSeqHeader;
... ... @@ -79,6 +80,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
79 80 if (ssrcTransaction != null) {
80 81 deviceId = ssrcTransaction.getDeviceId();
81 82 }
  83 +
  84 + ServerTransaction serverTransaction = getServerTransaction(evt);
  85 +
82 86 // 查询设备是否存在
83 87 Device device = redisCatchStorage.getDevice(deviceId);
84 88 // 查询上级平台是否存在
... ... @@ -98,7 +102,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
98 102 }
99 103 if (device == null && parentPlatform == null) {
100 104 // 不存在则回复404
101   - responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found");
  105 + responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
102 106 logger.warn("[设备未找到 ]: {}", deviceId);
103 107 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
104 108 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
... ... @@ -110,13 +114,13 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
110 114 rootElement = getRootElement(evt);
111 115 if (rootElement == null) {
112 116 logger.error("处理MESSAGE请求 未获取到消息体{}", evt.getRequest());
113   - responseAck(evt, Response.BAD_REQUEST, "content is null");
  117 + responseAck(serverTransaction, Response.BAD_REQUEST, "content is null");
114 118 return;
115 119 }
116 120 } catch (DocumentException e) {
117 121 logger.warn("解析XML消息内容异常", e);
118 122 // 不存在则回复404
119   - responseAck(evt, Response.BAD_REQUEST, e.getMessage());
  123 + responseAck(serverTransaction, Response.BAD_REQUEST, e.getMessage());
120 124 }
121 125 String name = rootElement.getName();
122 126 IMessageHandler messageHandler = messageHandlerMap.get(name);
... ... @@ -129,7 +133,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
129 133 }else {
130 134 // 不支持的message
131 135 // 不存在则回复415
132   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
  136 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
133 137 }
134 138 }
135 139 } catch (SipException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
... ... @@ -61,6 +61,8 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
61 61 @Override
62 62 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
63 63  
  64 + ServerTransaction serverTransaction = getServerTransaction(evt);
  65 +
64 66 // 此处是上级发出的DeviceControl指令
65 67 String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
66 68 String channelId = getText(rootElement, "DeviceID");
... ... @@ -107,7 +109,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
107 109 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
108 110 if (deviceForPlatform == null) {
109 111 try {
110   - responseAck(evt, Response.NOT_FOUND);
  112 + responseAck(serverTransaction, Response.NOT_FOUND);
111 113 return;
112 114 } catch (SipException e) {
113 115 e.printStackTrace();
... ... @@ -120,7 +122,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
120 122 cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
121 123 // 失败的回复
122 124 try {
123   - responseAck(evt, eventResult.statusCode, eventResult.msg);
  125 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
124 126 } catch (SipException e) {
125 127 e.printStackTrace();
126 128 } catch (InvalidArgumentException e) {
... ... @@ -131,7 +133,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
131 133 }, eventResult -> {
132 134 // 成功的回复
133 135 try {
134   - responseAck(evt, eventResult.statusCode);
  136 + responseAck(serverTransaction, eventResult.statusCode);
135 137 } catch (SipException e) {
136 138 e.printStackTrace();
137 139 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
... ... @@ -77,7 +77,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
77 77 logger.info("[收到报警通知]设备:{}", device.getDeviceId());
78 78 // 回复200 OK
79 79 try {
80   - responseAck(evt, Response.OK);
  80 + responseAck(getServerTransaction(evt), Response.OK);
81 81 } catch (SipException | InvalidArgumentException | ParseException e) {
82 82 logger.error("[收到报警通知], 回复200OK失败", e);
83 83 }
... ... @@ -179,7 +179,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
179 179 if (sipConfig.isAlarm()) {
180 180 deviceAlarmService.add(deviceAlarm);
181 181 }
182   -
  182 + logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm));
183 183 if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) {
184 184 publisher.deviceAlarmEventPublish(deviceAlarm);
185 185 }
... ... @@ -190,7 +190,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
190 190 logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId());
191 191 // 回复200 OK
192 192 try {
193   - responseAck(evt, Response.OK);
  193 + responseAck(getServerTransaction(evt), Response.OK);
194 194 } catch (SipException e) {
195 195 throw new RuntimeException(e);
196 196 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -69,7 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
69 69 }
70 70 device.setKeepaliveTime(DateUtil.getNow());
71 71 // 回复200 OK
72   - responseAck(evt, Response.OK);
  72 + responseAck(getServerTransaction(evt), Response.OK);
73 73 if (device.getOnline() == 1) {
74 74 deviceService.updateDevice(device);
75 75 }else {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
... ... @@ -66,7 +66,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
66 66  
67 67 // 回复200 OK
68 68 try {
69   - responseAck(evt, Response.OK);
  69 + responseAck(getServerTransaction(evt), Response.OK);
70 70 } catch (SipException e) {
71 71 e.printStackTrace();
72 72 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
... ... @@ -65,7 +65,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
65 65 rootElement = getRootElement(evt, device.getCharset());
66 66 if (rootElement == null) {
67 67 logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest());
68   - responseAck(evt, Response.BAD_REQUEST);
  68 + responseAck(getServerTransaction(evt), Response.BAD_REQUEST);
69 69 return;
70 70 }
71 71 MobilePosition mobilePosition = new MobilePosition();
... ... @@ -116,7 +116,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
116 116 }
117 117 storager.updateChannelPosition(deviceChannel);
118 118 //回复 200 OK
119   - responseAck(evt, Response.OK);
  119 + responseAck(getServerTransaction(evt), Response.OK);
120 120  
121 121 // 发送redis消息。 通知位置信息的变化
122 122 JSONObject jsonObject = new JSONObject();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java
... ... @@ -58,7 +58,7 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen
58 58  
59 59 logger.info("不支持alarm查询");
60 60 try {
61   - responseAck(evt, Response.NOT_FOUND, "not support alarm query");
  61 + responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query");
62 62 } catch (SipException e) {
63 63 e.printStackTrace();
64 64 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
... ... @@ -66,7 +66,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
66 66 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
67 67 try {
68 68 // 回复200 OK
69   - responseAck(evt, Response.OK);
  69 + responseAck(getServerTransaction(evt), Response.OK);
70 70 Element snElement = rootElement.element("SN");
71 71 String sn = snElement.getText();
72 72 // 准备回复通道信息
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
... ... @@ -48,7 +48,7 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
48 48 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
49 49 try {
50 50 // 回复200 OK
51   - responseAck(evt, Response.OK);
  51 + responseAck(getServerTransaction(evt), Response.OK);
52 52 } catch (SipException e) {
53 53 e.printStackTrace();
54 54 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java
... ... @@ -61,7 +61,7 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
61 61 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
62 62 // 回复200 OK
63 63 try {
64   - responseAck(evt, Response.OK);
  64 + responseAck(getServerTransaction(evt), Response.OK);
65 65 } catch (SipException e) {
66 66 e.printStackTrace();
67 67 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java
... ... @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
21 21  
22 22 import javax.sip.InvalidArgumentException;
23 23 import javax.sip.RequestEvent;
  24 +import javax.sip.ServerTransaction;
24 25 import javax.sip.SipException;
25 26 import javax.sip.header.FromHeader;
26 27 import javax.sip.message.Response;
... ... @@ -68,7 +69,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
68 69 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
69 70  
70 71 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
71   -
  72 + ServerTransaction serverTransaction = getServerTransaction(evt);
72 73 Element snElement = rootElement.element("SN");
73 74 int sn = Integer.parseInt(snElement.getText());
74 75 Element deviceIDElement = rootElement.element("DeviceID");
... ... @@ -108,7 +109,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
108 109 DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
109 110 // 回复200 OK
110 111 try {
111   - responseAck(evt, Response.OK);
  112 + responseAck(serverTransaction, Response.OK);
112 113 } catch (SipException e) {
113 114 e.printStackTrace();
114 115 } catch (InvalidArgumentException e) {
... ... @@ -119,7 +120,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
119 120 }),(eventResult -> {
120 121 // 查询失败
121 122 try {
122   - responseAck(evt, eventResult.statusCode, eventResult.msg);
  123 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
123 124 } catch (SipException e) {
124 125 e.printStackTrace();
125 126 } catch (InvalidArgumentException e) {
... ... @@ -132,7 +133,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
132 133 }else if (channelSources.get(1).getCount() > 0) { // 直播流
133 134 // TODO
134 135 try {
135   - responseAck(evt, Response.NOT_IMPLEMENTED); // 回复未实现
  136 + responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
136 137 } catch (SipException e) {
137 138 e.printStackTrace();
138 139 } catch (InvalidArgumentException e) {
... ... @@ -142,7 +143,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
142 143 }
143 144 }else { // 错误的请求
144 145 try {
145   - responseAck(evt, Response.BAD_REQUEST);
  146 + responseAck(serverTransaction, Response.BAD_REQUEST);
146 147 } catch (SipException e) {
147 148 e.printStackTrace();
148 149 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
... ... @@ -18,6 +18,7 @@ import org.springframework.stereotype.Component;
18 18  
19 19 import javax.sip.InvalidArgumentException;
20 20 import javax.sip.RequestEvent;
  21 +import javax.sip.ServerTransaction;
21 22 import javax.sip.SipException;
22 23 import javax.sip.message.Response;
23 24 import java.text.ParseException;
... ... @@ -46,8 +47,9 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
46 47 try {
47 48 String channelId = getText(rootElement, "DeviceID");
48 49 String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId;
  50 + ServerTransaction serverTransaction = getServerTransaction(evt);
49 51 // 回复200 OK
50   - responseAck(evt, Response.OK);
  52 + responseAck(serverTransaction, Response.OK);
51 53 // 此处是对本平台发出Broadcast指令的应答
52 54 JSONObject json = new JSONObject();
53 55 XmlUtil.node2Json(rootElement, json);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
... ... @@ -27,6 +27,7 @@ import org.springframework.util.StringUtils;
27 27  
28 28 import javax.sip.InvalidArgumentException;
29 29 import javax.sip.RequestEvent;
  30 +import javax.sip.ServerTransaction;
30 31 import javax.sip.SipException;
31 32 import javax.sip.message.Response;
32 33 import java.text.ParseException;
... ... @@ -87,7 +88,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
87 88 taskQueue.offer(new HandlerCatchData(evt, device, element));
88 89 // 回复200 OK
89 90 try {
90   - responseAck(evt, Response.OK);
  91 + ServerTransaction serverTransaction = getServerTransaction(evt);
  92 + responseAck(serverTransaction, Response.OK);
91 93 if (!taskQueueHandlerRun) {
92 94 taskQueueHandlerRun = true;
93 95 taskExecutor.execute(()-> {
... ... @@ -103,7 +105,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
103 105 Element sumNumElement = rootElement.element("SumNum");
104 106 Element snElement = rootElement.element("SN");
105 107 if (snElement == null || sumNumElement == null || deviceListElement == null) {
106   - responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error");
  108 + responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
107 109 continue;
108 110 }
109 111 int sumNum = Integer.parseInt(sumNumElement.getText());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java
... ... @@ -52,7 +52,7 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
52 52 String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
53 53 try {
54 54 // 回复200 OK
55   - responseAck(evt, Response.OK);
  55 + responseAck(getServerTransaction(evt), Response.OK);
56 56 // 此处是对本平台发出DeviceControl指令的应答
57 57 JSONObject json = new JSONObject();
58 58 XmlUtil.node2Json(element, json);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java
... ... @@ -46,7 +46,7 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare
46 46 public void handForDevice(RequestEvent evt, Device device, Element element) {
47 47 // 此处是对本平台发出DeviceControl指令的应答
48 48 try {
49   - responseAck(evt, Response.OK);
  49 + responseAck(getServerTransaction(evt), Response.OK);
50 50 JSONObject json = new JSONObject();
51 51 String channelId = getText(element, "DeviceID");
52 52 XmlUtil.node2Json(element, json);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
... ... @@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
25 25  
26 26 import javax.sip.InvalidArgumentException;
27 27 import javax.sip.RequestEvent;
  28 +import javax.sip.ServerTransaction;
28 29 import javax.sip.SipException;
29 30 import javax.sip.message.Response;
30 31 import java.text.ParseException;
... ... @@ -74,11 +75,12 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
74 75 logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]:" + (device != null ? device.getDeviceId():"" ));
75 76 return;
76 77 }
  78 + ServerTransaction serverTransaction = getServerTransaction(evt);
77 79 try {
78 80 rootElement = getRootElement(evt, device.getCharset());
79 81 if (rootElement == null) {
80 82 logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest());
81   - responseAck(evt, Response.BAD_REQUEST);
  83 + responseAck(serverTransaction, Response.BAD_REQUEST);
82 84 return;
83 85 }
84 86 Element deviceIdElement = rootElement.element("DeviceID");
... ... @@ -99,7 +101,7 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
99 101 msg.setData(device);
100 102 deferredResultHolder.invokeAllResult(msg);
101 103 // 回复200 OK
102   - responseAck(evt, Response.OK);
  104 + responseAck(serverTransaction, Response.OK);
103 105 } catch (DocumentException e) {
104 106 e.printStackTrace();
105 107 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
... ... @@ -59,7 +59,7 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
59 59 }
60 60 // 回复200 OK
61 61 try {
62   - responseAck(evt, Response.OK);
  62 + responseAck(getServerTransaction(evt), Response.OK);
63 63 } catch (SipException e) {
64 64 e.printStackTrace();
65 65 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
... ... @@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
25 25  
26 26 import javax.sip.InvalidArgumentException;
27 27 import javax.sip.RequestEvent;
  28 +import javax.sip.ServerTransaction;
28 29 import javax.sip.SipException;
29 30 import javax.sip.message.Response;
30 31 import java.text.ParseException;
... ... @@ -64,11 +65,13 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
64 65 @Override
65 66 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
66 67  
  68 + ServerTransaction serverTransaction = getServerTransaction(evt);
  69 +
67 70 try {
68 71 rootElement = getRootElement(evt, device.getCharset());
69 72 if (rootElement == null) {
70 73 logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest());
71   - responseAck(evt, Response.BAD_REQUEST);
  74 + responseAck(serverTransaction, Response.BAD_REQUEST);
72 75 return;
73 76 }
74 77 MobilePosition mobilePosition = new MobilePosition();
... ... @@ -130,7 +133,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
130 133 jsonObject.put("speed", mobilePosition.getSpeed());
131 134 redisCatchStorage.sendMobilePositionMsg(jsonObject);
132 135 //回复 200 OK
133   - responseAck(evt, Response.OK);
  136 + responseAck(serverTransaction, Response.OK);
134 137 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
135 138 e.printStackTrace();
136 139 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
... ... @@ -17,6 +17,7 @@ import org.springframework.stereotype.Component;
17 17  
18 18 import javax.sip.InvalidArgumentException;
19 19 import javax.sip.RequestEvent;
  20 +import javax.sip.ServerTransaction;
20 21 import javax.sip.SipException;
21 22 import javax.sip.message.Response;
22 23 import java.text.ParseException;
... ... @@ -51,10 +52,13 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
51 52 public void handForDevice(RequestEvent evt, Device device, Element element) {
52 53 Element rootElement = null;
53 54 try {
  55 +
  56 + ServerTransaction serverTransaction = getServerTransaction(evt);
  57 +
54 58 rootElement = getRootElement(evt, device.getCharset());
55 59 if (rootElement == null) {
56 60 logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
57   - responseAck(evt, Response.BAD_REQUEST);
  61 + responseAck(serverTransaction, Response.BAD_REQUEST);
58 62 return;
59 63 }
60 64 Element presetListNumElement = rootElement.element("PresetList");
... ... @@ -63,7 +67,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
63 67 String deviceId = getText(rootElement, "DeviceID");
64 68 String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
65 69 if (snElement == null || presetListNumElement == null) {
66   - responseAck(evt, Response.BAD_REQUEST, "xml error");
  70 + responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
67 71 return;
68 72 }
69 73 int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
... ... @@ -93,7 +97,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
93 97 requestMessage.setKey(key);
94 98 requestMessage.setData(presetQuerySipReqList);
95 99 deferredResultHolder.invokeAllResult(requestMessage);
96   - responseAck(evt, Response.OK);
  100 + responseAck(serverTransaction, Response.OK);
97 101 } catch (DocumentException e) {
98 102 e.printStackTrace();
99 103 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
... ... @@ -72,7 +72,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
72 72  
73 73 // 回复200 OK
74 74 try {
75   - responseAck(evt, Response.OK);
  75 + responseAck(getServerTransaction(evt), Response.OK);
76 76 taskQueue.offer(new HandlerCatchData(evt, device, rootElement));
77 77 if (!taskQueueHandlerRun) {
78 78 taskQueueHandlerRun = true;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
... ... @@ -7,6 +7,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcesso
7 7 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
8 8 import com.genersoft.iot.vmp.utils.GitUtil;
9 9 import gov.nist.javax.sip.ResponseEventExt;
  10 +import gov.nist.javax.sip.message.SIPResponse;
  11 +import gov.nist.javax.sip.stack.SIPClientTransaction;
10 12 import gov.nist.javax.sip.stack.SIPDialog;
11 13 import org.slf4j.Logger;
12 14 import org.slf4j.LoggerFactory;
... ... @@ -78,7 +80,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
78 80 // 下发ack
79 81 if (statusCode == Response.OK) {
80 82 ResponseEventExt event = (ResponseEventExt)evt;
81   - SIPDialog dialog = (SIPDialog)evt.getDialog();
  83 + SIPDialog dialog = new SIPDialog((SIPClientTransaction) event.getClientTransaction(), (SIPResponse) event.getResponse());
82 84 CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
83 85 Request reqAck = dialog.createAck(cseq.getSeqNumber());
84 86 SipURI requestURI = (SipURI) reqAck.getRequestURI();
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -103,7 +103,7 @@ public class ZLMHttpHookListener {
103 103 @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
104 104 public JSONObject onServerKeepalive(@RequestBody JSONObject json){
105 105  
106   - logger.info("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString());
  106 + logger.info("[ ZLM HOOK ]on_server_keepalive API调用,参数:" + json.toString());
107 107 String mediaServerId = json.getString("mediaServerId");
108 108 List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
109 109 if (subscribes != null && subscribes.size() > 0) {
... ... @@ -453,6 +453,7 @@ public class ZLMHttpHookListener {
453 453 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
454 454 // 如果正在给上级推送,则发送bye
455 455  
  456 +
456 457 }else{
457 458 streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null);
458 459 if (streamInfo != null) {
... ... @@ -509,6 +510,19 @@ public class ZLMHttpHookListener {
509 510 }
510 511 }
511 512 }
  513 + if (!regist) {
  514 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(stream);
  515 + if (sendRtpItems.size() > 0) {
  516 + for (SendRtpItem sendRtpItem : sendRtpItems) {
  517 + if (sendRtpItem.getApp().equals(app)) {
  518 + String platformId = sendRtpItem.getPlatformId();
  519 + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
  520 +
  521 + commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
  522 + }
  523 + }
  524 + }
  525 + }
512 526 }
513 527  
514 528 JSONObject ret = new JSONObject();
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
... ... @@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory;
17 17 import org.springframework.beans.factory.annotation.Autowired;
18 18 import org.springframework.stereotype.Component;
19 19  
  20 +import java.text.ParseException;
20 21 import java.util.*;
21 22 import java.util.concurrent.ConcurrentHashMap;
22 23  
... ... @@ -83,7 +84,11 @@ public class ZLMMediaListManager {
83 84 }
84 85 if (transform != null) {
85 86 if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) {
86   - getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
  87 + try {
  88 + getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
  89 + } catch (ParseException e) {
  90 + throw new RuntimeException(e);
  91 + }
87 92 removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
88 93 }
89 94 }
... ... @@ -95,7 +100,11 @@ public class ZLMMediaListManager {
95 100 // 查看推流状态
96 101 if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
97 102 if (getChannelOnlineEventLister(app, stream) != null) {
98   - getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
  103 + try {
  104 + getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
  105 + } catch (ParseException e) {
  106 + throw new RuntimeException(e);
  107 + }
99 108 removedChannelOnlineEventLister(app, stream);
100 109 }
101 110 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -330,12 +330,12 @@ public class ZLMRTPServerFactory {
330 330 Boolean result = false;
331 331 JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
332 332 if (jsonObject == null) {
333   - logger.error("停止RTP推流失败: 请检查ZLM服务");
  333 + logger.error("[停止RTP推流] 失败: 请检查ZLM服务");
334 334 } else if (jsonObject.getInteger("code") == 0) {
335 335 result= true;
336   - logger.info("停止RTP推流成功");
  336 + logger.info("[停止RTP推流] 成功");
337 337 } else {
338   - logger.error("停止RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
  338 + logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"),JSONObject.toJSON(param), jsonObject);
339 339 }
340 340 return result;
341 341 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java
... ... @@ -137,8 +137,6 @@ public class ZlmHttpHookSubscribe {
137 137 @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
138 138 public void execute(){
139 139  
140   - logger.info("[hook订阅] 清理");
141   -
142 140 Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
143 141 int total = 0;
144 142 for (HookType hookType : allSubscribes.keySet()) {
... ... @@ -153,6 +151,5 @@ public class ZlmHttpHookSubscribe {
153 151 }
154 152 }
155 153 }
156   - logger.info("[hook订阅] 清理结束,共清理{}条过期数据", total);
157 154 }
158 155 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java
1 1 package com.genersoft.iot.vmp.media.zlm.dto;
2 2  
  3 +import java.text.ParseException;
  4 +
3 5 /**
4 6 * @author lin
5 7 */
6 8 public interface ChannelOnlineEvent {
7 9  
8   - void run(String app, String stream, String serverId);
  10 + void run(String app, String stream, String serverId) throws ParseException;
9 11 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
1 1 package com.genersoft.iot.vmp.service;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
3 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
  6 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
4 7 import com.github.pagehelper.PageInfo;
5 8  
  9 +import java.util.List;
  10 +
6 11 /**
7 12 * 国标平台的业务类
8 13 * @author lin
... ... @@ -42,4 +47,10 @@ public interface IPlatformService {
42 47 * @param parentPlatform
43 48 */
44 49 void login(ParentPlatform parentPlatform);
  50 +
  51 + /**
  52 + * 向上级平台发送位置订阅
  53 + * @param platformId 平台
  54 + */
  55 + void sendNotifyMobilePosition(String platformId);
45 56 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
... ... @@ -73,7 +73,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
73 73 result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
74 74 // TODO 后续给平台增加控制开关以控制是否响应目录订阅
75 75 List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
76   - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  76 + if (deviceChannelList != null) {
  77 + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  78 + }
77 79 }
78 80  
79 81 return result;
... ... @@ -83,7 +85,7 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
83 85 List<DeviceChannel> deviceChannelList = new ArrayList<>();
84 86 if (channelReduces.size() > 0){
85 87 PlatformCatalog catalog = catalogManager.select(catalogId);
86   - if (catalog == null && !catalogId.equals(platform.getServerGBId())) {
  88 + if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) {
87 89 logger.warn("未查询到目录{}的信息", catalogId);
88 90 return null;
89 91 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
1 1 package com.genersoft.iot.vmp.service.impl;
2 2  
3 3 import com.genersoft.iot.vmp.conf.DynamicTask;
4   -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5   -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
6   -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
7   -import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
  4 +import com.genersoft.iot.vmp.gb28181.bean.*;
8 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
9 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
10 7 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
11 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 9 import com.genersoft.iot.vmp.service.IMediaServerService;
13 10 import com.genersoft.iot.vmp.service.IPlatformService;
  11 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
14 12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  13 +import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
15 14 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
16 15 import com.github.pagehelper.PageHelper;
17 16 import com.github.pagehelper.PageInfo;
... ... @@ -57,6 +56,9 @@ public class PlatformServiceImpl implements IPlatformService {
57 56 @Autowired
58 57 private SubscribeHolder subscribeHolder;
59 58  
  59 + @Autowired
  60 + private GbStreamMapper gbStreamMapper;
  61 +
60 62  
61 63  
62 64 @Override
... ... @@ -228,4 +230,34 @@ public class PlatformServiceImpl implements IPlatformService {
228 230 60*1000);
229 231 }, null);
230 232 }
  233 +
  234 + @Override
  235 + public void sendNotifyMobilePosition(String platformId) {
  236 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
  237 + if (platform == null) {
  238 + return;
  239 + }
  240 + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
  241 + if (subscribe != null) {
  242 +
  243 + // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
  244 + List<DeviceChannel> gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId());
  245 + if (gbStreams.size() == 0) {
  246 + return;
  247 + }
  248 + for (DeviceChannel deviceChannel : gbStreams) {
  249 + String gbId = deviceChannel.getChannelId();
  250 + GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
  251 + // 无最新位置不发送
  252 + if (gpsMsgInfo != null) {
  253 + // 经纬度都为0不发送
  254 + if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
  255 + continue;
  256 + }
  257 + // 发送GPS消息
  258 + commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
  259 + }
  260 + }
  261 + }
  262 + }
231 263 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java
... ... @@ -23,6 +23,7 @@ import org.springframework.data.redis.connection.Message;
23 23 import org.springframework.data.redis.connection.MessageListener;
24 24 import org.springframework.stereotype.Component;
25 25  
  26 +import java.text.ParseException;
26 27 import java.util.HashMap;
27 28 import java.util.Map;
28 29 import java.util.UUID;
... ... @@ -86,7 +87,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
86 87  
87 88  
88 89 public interface PlayMsgCallback{
89   - void handler(ResponseSendItemMsg responseSendItemMsg);
  90 + void handler(ResponseSendItemMsg responseSendItemMsg) throws ParseException;
90 91 }
91 92  
92 93 public interface PlayMsgCallbackForStartSendRtpStream{
... ... @@ -134,7 +135,11 @@ public class RedisGbPlayMsgListener implements MessageListener {
134 135 PlayMsgCallback playMsgCallback = callbacks.get(key);
135 136 if (playMsgCallback != null) {
136 137 callbacksForError.remove(key);
137   - playMsgCallback.handler(responseSendItemMsg);
  138 + try {
  139 + playMsgCallback.handler(responseSendItemMsg);
  140 + } catch (ParseException e) {
  141 + throw new RuntimeException(e);
  142 + }
138 143 }
139 144 break;
140 145 case ERROR_CODE_MEDIA_SERVER_NOT_FOUND:
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -710,14 +710,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
710 710 @Override
711 711 public void sendMobilePositionMsg(JSONObject jsonObject) {
712 712 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
713   - logger.info("[redis发送通知]移动位置 {}: {}", key, jsonObject.toString());
  713 + logger.info("[redis发送通知] 移动位置 {}: {}", key, jsonObject.toString());
714 714 RedisUtil.convertAndSend(key, jsonObject);
715 715 }
716 716  
717 717 @Override
718 718 public void sendStreamPushRequestedMsg(MessageForPushChannel msg) {
719 719 String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
720   - logger.info("[redis发送通知]推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
  720 + logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
721 721 RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
722 722 }
723 723  
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -413,24 +413,20 @@ public class DeviceQuery {
413 413 @GetMapping("/{deviceId}/subscribe_info")
414 414 @Operation(summary = "获取设备的订阅状态")
415 415 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
416   - public WVPResult<Map<String, String>> getSubscribeInfo(@PathVariable String deviceId) {
  416 + public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) {
417 417 Set<String> allKeys = dynamicTask.getAllKeys();
418   - Map<String, String> dialogStateMap = new HashMap<>();
  418 + Map<String, Integer> dialogStateMap = new HashMap<>();
419 419 for (String key : allKeys) {
420 420 if (key.startsWith(deviceId)) {
421 421 ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key);
422   - DialogState dialogState = subscribeTask.getDialogState();
423   - if (dialogState == null) {
424   - continue;
425   - }
426 422 if (subscribeTask instanceof CatalogSubscribeTask) {
427   - dialogStateMap.put("catalog", dialogState.toString());
  423 + dialogStateMap.put("catalog", 1);
428 424 }else if (subscribeTask instanceof MobilePositionSubscribeTask) {
429   - dialogStateMap.put("mobilePosition", dialogState.toString());
  425 + dialogStateMap.put("mobilePosition", 1);
430 426 }
431 427 }
432 428 }
433   - WVPResult<Map<String, String>> wvpResult = new WVPResult<>();
  429 + WVPResult<Map<String, Integer>> wvpResult = new WVPResult<>();
434 430 wvpResult.setCode(0);
435 431 wvpResult.setData(dialogStateMap);
436 432 return wvpResult;
... ...
web_src/src/components/dialog/recordDownload.vue
... ... @@ -84,12 +84,13 @@ export default {
84 84 method: 'get',
85 85 url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
86 86 }).then((res)=> {
  87 + console.log(res)
87 88 if (res.data.code === 0) {
88 89 this.streamInfo = res.data.data;
89 90 if (parseFloat(res.data.progress) == 1) {
90 91 this.percentage = 100;
91 92 }else {
92   - this.percentage = (res.data.data.progress*100).toFixed(1);
  93 + this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1);
93 94 }
94 95 if (callback)callback();
95 96 }
... ...