Commit c1145a816399528e81589eef11046d877315ad5e

Authored by 648540858
1 parent 15169913

优化级联注册,以及sip日志

src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java
1 package com.genersoft.iot.vmp.gb28181.conf; 1 package com.genersoft.iot.vmp.gb28181.conf;
2 2
  3 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.AlarmNotifyMessageHandler;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +
3 import java.util.Properties; 7 import java.util.Properties;
4 8
5 /** 9 /**
@@ -12,6 +16,7 @@ public class DefaultProperties { @@ -12,6 +16,7 @@ public class DefaultProperties {
12 Properties properties = new Properties(); 16 Properties properties = new Properties();
13 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); 17 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
14 properties.setProperty("javax.sip.IP_ADDRESS", ip); 18 properties.setProperty("javax.sip.IP_ADDRESS", ip);
  19 + // 关闭自动会话
15 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); 20 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
16 /** 21 /**
17 * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码 22 * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
@@ -26,7 +31,7 @@ public class DefaultProperties { @@ -26,7 +31,7 @@ public class DefaultProperties {
26 // 接收所有notify请求,即使没有订阅 31 // 接收所有notify请求,即使没有订阅
27 properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); 32 properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
28 properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); 33 properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
29 - properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false"); 34 + properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "true");
30 // 为_NULL _对话框传递_终止的_事件 35 // 为_NULL _对话框传递_终止的_事件
31 properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); 36 properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
32 // 会话清理策略 37 // 会话清理策略
@@ -35,11 +40,33 @@ public class DefaultProperties { @@ -35,11 +40,33 @@ public class DefaultProperties {
35 properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60"); 40 properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
36 // 获取实际内容长度,不使用header中的长度信息 41 // 获取实际内容长度,不使用header中的长度信息
37 properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true"); 42 properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
  43 + // 线程可重入
  44 + properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "true");
  45 + // 定义应用程序打算多久审计一次 SIP 堆栈,了解其内部线程的健康状况(该属性指定连续审计之间的时间(以毫秒为单位))
  46 + properties.setProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS", "30000");
38 47
39 /** 48 /**
40 * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE 49 * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
41 */ 50 */
42 - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); 51 + Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class);
  52 + if (logger.isDebugEnabled()) {
  53 + System.out.println("DEBUG");
  54 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
  55 + }else if (logger.isInfoEnabled()) {
  56 + System.out.println("INFO1");
  57 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
  58 + }else if (logger.isWarnEnabled()) {
  59 + System.out.println("WARNING");
  60 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "WARNING");
  61 + }else if (logger.isErrorEnabled()) {
  62 + System.out.println("ERROR");
  63 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
  64 + }else {
  65 + System.out.println("INFO2");
  66 + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
  67 + }
  68 + logger.info("[SIP日志]级别为: {}", properties.getProperty("gov.nist.javax.sip.TRACE_LEVEL"));
  69 +
43 70
44 return properties; 71 return properties;
45 } 72 }
src/main/java/com/genersoft/iot/vmp/gb28181/conf/SipLoggerPass.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.conf;  
2 -  
3 -import gov.nist.core.StackLogger;  
4 -  
5 -import java.util.Properties;  
6 -  
7 -/**  
8 - * sip日志格式化  
9 - * 暂不使用  
10 - */  
11 -public class SipLoggerPass implements StackLogger {  
12 -  
13 - @Override  
14 - public void logStackTrace() {  
15 -  
16 - }  
17 -  
18 - @Override  
19 - public void logStackTrace(int traceLevel) {  
20 -  
21 - }  
22 -  
23 - @Override  
24 - public int getLineCount() {  
25 - return 0;  
26 - }  
27 -  
28 - @Override  
29 - public void logException(Throwable ex) {  
30 -  
31 - }  
32 -  
33 - @Override  
34 - public void logDebug(String message) {  
35 -  
36 - }  
37 -  
38 - @Override  
39 - public void logDebug(String message, Exception ex) {  
40 -  
41 - }  
42 -  
43 - @Override  
44 - public void logTrace(String message) {  
45 -  
46 - }  
47 -  
48 - @Override  
49 - public void logFatalError(String message) {  
50 -  
51 - }  
52 -  
53 - @Override  
54 - public void logError(String message) {  
55 -  
56 - }  
57 -  
58 - @Override  
59 - public boolean isLoggingEnabled() {  
60 - return false;  
61 - }  
62 -  
63 - @Override  
64 - public boolean isLoggingEnabled(int logLevel) {  
65 - return false;  
66 - }  
67 -  
68 - @Override  
69 - public void logError(String message, Exception ex) {  
70 -  
71 - }  
72 -  
73 - @Override  
74 - public void logWarning(String string) {  
75 -  
76 - }  
77 -  
78 - @Override  
79 - public void logInfo(String string) {  
80 -  
81 - }  
82 -  
83 - @Override  
84 - public void disableLogging() {  
85 -  
86 - }  
87 -  
88 - @Override  
89 - public void enableLogging() {  
90 -  
91 - }  
92 -  
93 - @Override  
94 - public void setBuildTimeStamp(String buildTimeStamp) {  
95 -  
96 - }  
97 -  
98 - @Override  
99 - public void setStackProperties(Properties stackProperties) {  
100 -  
101 - }  
102 -  
103 - @Override  
104 - public String getLoggerName() {  
105 - return null;  
106 - }  
107 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
@@ -13,7 +13,6 @@ import javax.sip.SipFactory; @@ -13,7 +13,6 @@ import javax.sip.SipFactory;
13 import javax.sip.header.FromHeader; 13 import javax.sip.header.FromHeader;
14 import javax.sip.header.Header; 14 import javax.sip.header.Header;
15 import javax.sip.header.UserAgentHeader; 15 import javax.sip.header.UserAgentHeader;
16 -import javax.sip.header.ViaHeader;  
17 import javax.sip.message.Request; 16 import javax.sip.message.Request;
18 import java.text.ParseException; 17 import java.text.ParseException;
19 import java.util.ArrayList; 18 import java.util.ArrayList;
@@ -138,13 +137,12 @@ public class SipUtils { @@ -138,13 +137,12 @@ public class SipUtils {
138 }else { 137 }else {
139 // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 138 // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息
140 // 获取到通信地址等信息 139 // 获取到通信地址等信息
141 - ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);  
142 - remoteAddress = viaHeader.getReceived();  
143 - remotePort = viaHeader.getRPort(); 140 + remoteAddress = request.getTopmostViaHeader().getReceived();
  141 + remotePort = request.getTopmostViaHeader().getRPort();
144 // 解析本地地址替代 142 // 解析本地地址替代
145 if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) { 143 if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) {
146 - remoteAddress = viaHeader.getHost();  
147 - remotePort = viaHeader.getPort(); 144 + remoteAddress = request.getTopmostViaHeader().getHost();
  145 + remotePort = request.getTopmostViaHeader().getPort();
148 } 146 }
149 } 147 }
150 148
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -424,7 +424,7 @@ public class ZLMHttpHookListener { @@ -424,7 +424,7 @@ public class ZLMHttpHookListener {
424 logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); 424 logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
425 JSONObject ret = new JSONObject(); 425 JSONObject ret = new JSONObject();
426 ret.put("code", 0); 426 ret.put("code", 0);
427 - // 录像下载 427 + // 国标类型的流
428 if ("rtp".equals(param.getApp())){ 428 if ("rtp".equals(param.getApp())){
429 ret.put("close", userSetting.getStreamOnDemand()); 429 ret.put("close", userSetting.getStreamOnDemand());
430 // 国标流, 点播/录像回放/录像下载 430 // 国标流, 点播/录像回放/录像下载
@@ -596,7 +596,7 @@ public class ZLMHttpHookListener { @@ -596,7 +596,7 @@ public class ZLMHttpHookListener {
596 @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8") 596 @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8")
597 public JSONObject onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param){ 597 public JSONObject onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param){
598 598
599 - logger.info("[ZLM HOOK] 发送rtp被动关闭:{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream()); 599 + logger.info("[ZLM HOOK] rtp发送关闭:{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream());
600 600
601 JSONObject ret = new JSONObject(); 601 JSONObject ret = new JSONObject();
602 ret.put("code", 0); 602 ret.put("code", 0);
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -154,7 +154,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -154,7 +154,8 @@ public class DeviceServiceImpl implements IDeviceService {
154 } 154 }
155 // 刷新过期任务 155 // 刷新过期任务
156 String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); 156 String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId();
157 - dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); 157 + // 增加一个10秒给设备重发消息的机会
  158 + dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), (device.getExpires() + 10) * 1000);
158 } 159 }
159 160
160 @Override 161 @Override
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
@@ -135,14 +135,7 @@ public class PlatformServiceImpl implements IPlatformService { @@ -135,14 +135,7 @@ public class PlatformServiceImpl implements IPlatformService {
135 dynamicTask.startCron(registerTaskKey, 135 dynamicTask.startCron(registerTaskKey,
136 // 注册失败(注册成功时由程序直接调用了online方法) 136 // 注册失败(注册成功时由程序直接调用了online方法)
137 ()-> { 137 ()-> {
138 - try {  
139 - logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId());  
140 - commanderForPlatform.register(parentPlatform, eventResult -> {  
141 - offline(parentPlatform, false);  
142 - },null);  
143 - } catch (InvalidArgumentException | ParseException | SipException e) {  
144 - logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());  
145 - } 138 + registerTask(parentPlatform);
146 }, 139 },
147 (parentPlatform.getExpires() - 10) *1000); 140 (parentPlatform.getExpires() - 10) *1000);
148 } 141 }
@@ -194,6 +187,28 @@ public class PlatformServiceImpl implements IPlatformService { @@ -194,6 +187,28 @@ public class PlatformServiceImpl implements IPlatformService {
194 } 187 }
195 } 188 }
196 189
  190 + private void registerTask(ParentPlatform parentPlatform){
  191 + try {
  192 + // 设置超时重发, 后续从底层支持消息重发
  193 + String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout";
  194 + if (dynamicTask.isAlive(key)) {
  195 + return;
  196 + }
  197 + dynamicTask.startDelay(key, ()->{
  198 + registerTask(parentPlatform);
  199 + }, 1000);
  200 + logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId());
  201 + commanderForPlatform.register(parentPlatform, eventResult -> {
  202 + dynamicTask.stop(key);
  203 + offline(parentPlatform, false);
  204 + },eventResult -> {
  205 + dynamicTask.stop(key);
  206 + });
  207 + } catch (InvalidArgumentException | ParseException | SipException e) {
  208 + logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
  209 + }
  210 + }
  211 +
197 @Override 212 @Override
198 public void offline(ParentPlatform parentPlatform, boolean stopRegister) { 213 public void offline(ParentPlatform parentPlatform, boolean stopRegister) {
199 logger.info("[平台离线]:{}", parentPlatform.getServerGBId()); 214 logger.info("[平台离线]:{}", parentPlatform.getServerGBId());
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -106,24 +106,21 @@ public class PlayController { @@ -106,24 +106,21 @@ public class PlayController {
106 msg.setData(wvpResult); 106 msg.setData(wvpResult);
107 resultHolder.invokeResult(msg); 107 resultHolder.invokeResult(msg);
108 }); 108 });
109 -  
110 -  
111 - // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误  
112 - deferredResultEx.setFilter(result1 -> {  
113 - WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;  
114 - WVPResult<StreamContent> resultStream = null;  
115 - if (wvpResult1.getCode() == ErrorCode.SUCCESS.getCode()) {  
116 - StreamInfo data = wvpResult1.getData().clone();  
117 - if (userSetting.getUseSourceIpAsStreamIp()) {  
118 - data.channgeStreamIp(request.getLocalName());  
119 - }  
120 - resultStream = new WVPResult<>();  
121 - resultStream.setCode(wvpResult1.getCode());  
122 - resultStream.setMsg(wvpResult1.getMsg());  
123 - resultStream.setData(new StreamContent(wvpResult1.getData())); 109 + // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
  110 + deferredResultEx.setFilter(result1 -> {
  111 + WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;
  112 + WVPResult<StreamContent> resultStream = new WVPResult<>();
  113 + resultStream.setCode(wvpResult1.getCode());
  114 + resultStream.setMsg(wvpResult1.getMsg());
  115 + if (wvpResult1.getCode() == ErrorCode.SUCCESS.getCode()) {
  116 + StreamInfo data = wvpResult1.getData().clone();
  117 + if (userSetting.getUseSourceIpAsStreamIp()) {
  118 + data.channgeStreamIp(request.getLocalName());
124 } 119 }
125 - return resultStream;  
126 - }); 120 + resultStream.setData(new StreamContent(wvpResult1.getData()));
  121 + }
  122 + return resultStream;
  123 + });
127 124
128 125
129 // 录像查询以channelId作为deviceId查询 126 // 录像查询以channelId作为deviceId查询
src/main/resources/all-application.yml
@@ -186,7 +186,7 @@ user-settings: @@ -186,7 +186,7 @@ user-settings:
186 use-pushing-as-status: true 186 use-pushing-as-status: true
187 # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启 187 # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
188 use-source-ip-as-stream-ip: true 188 use-source-ip-as-stream-ip: true
189 - # 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放 189 + # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
190 stream-on-demand: true 190 stream-on-demand: true
191 # 推流鉴权, 默认开启 191 # 推流鉴权, 默认开启
192 push-authority: true 192 push-authority: true
@@ -195,8 +195,8 @@ user-settings: @@ -195,8 +195,8 @@ user-settings:
195 gb-send-stream-strict: false 195 gb-send-stream-strict: false
196 # 设备上线时是否自动同步通道 196 # 设备上线时是否自动同步通道
197 sync-channel-on-device-online: false 197 sync-channel-on-device-online: false
198 - # 设备上线时是否自动同步通道  
199 - sip-use-source-ip-as-remote-address: true 198 + # 是否使用设备来源Ip作为回复IP, 不设置则为 false
  199 + sip-use-source-ip-as-remote-address: false
200 200
201 # 关闭在线文档(生产环境建议关闭) 201 # 关闭在线文档(生产环境建议关闭)
202 springdoc: 202 springdoc: