Merge branch 'main' into main2
# Conflicts: # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java # src/main/resources/all-application.yml # web_src/src/components/dialog/devicePlayer.vue
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
@@ -29,6 +30,9 @@ public class SipLayer implements CommandLineRunner {
|
||||
@Autowired
|
||||
private ISIPProcessorObserver sipProcessorObserver;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -61,7 +65,7 @@ public class SipLayer implements CommandLineRunner {
|
||||
private void addListeningPoint(String monitorIp, int port){
|
||||
SipStackImpl sipStack;
|
||||
try {
|
||||
sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false));
|
||||
sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false, userSetting.getSipLog()));
|
||||
} catch (PeerUnavailableException e) {
|
||||
logger.error("[Sip Server] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);
|
||||
return;
|
||||
|
||||
@@ -94,6 +94,13 @@ public class Device {
|
||||
@Schema(description = "心跳时间")
|
||||
private String keepaliveTime;
|
||||
|
||||
|
||||
/**
|
||||
* 心跳间隔
|
||||
*/
|
||||
@Schema(description = "心跳间隔")
|
||||
private int keepaliveIntervalTime;
|
||||
|
||||
/**
|
||||
* 通道个数
|
||||
*/
|
||||
@@ -414,4 +421,12 @@ public class Device {
|
||||
public void setLocalIp(String localIp) {
|
||||
this.localIp = localIp;
|
||||
}
|
||||
|
||||
public int getKeepaliveIntervalTime() {
|
||||
return keepaliveIntervalTime;
|
||||
}
|
||||
|
||||
public void setKeepaliveIntervalTime(int keepaliveIntervalTime) {
|
||||
this.keepaliveIntervalTime = keepaliveIntervalTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
public class RemoteAddressInfo {
|
||||
private String ip;
|
||||
private int port;
|
||||
|
||||
public RemoteAddressInfo(String ip, int port) {
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,15 @@ public class SipTransactionInfo {
|
||||
private String toTag;
|
||||
private String viaBranch;
|
||||
|
||||
private boolean fromServer;
|
||||
// 自己是否媒体流发送者
|
||||
private boolean asSender;
|
||||
|
||||
public SipTransactionInfo(SIPResponse response, boolean fromServer) {
|
||||
public SipTransactionInfo(SIPResponse response, boolean asSender) {
|
||||
this.callId = response.getCallIdHeader().getCallId();
|
||||
this.fromTag = response.getFromTag();
|
||||
this.toTag = response.getToTag();
|
||||
this.viaBranch = response.getTopmostViaHeader().getBranch();
|
||||
this.fromServer = fromServer;
|
||||
this.asSender = asSender;
|
||||
}
|
||||
|
||||
public SipTransactionInfo(SIPResponse response) {
|
||||
@@ -24,7 +25,7 @@ public class SipTransactionInfo {
|
||||
this.fromTag = response.getFromTag();
|
||||
this.toTag = response.getToTag();
|
||||
this.viaBranch = response.getTopmostViaHeader().getBranch();
|
||||
this.fromServer = true;
|
||||
this.asSender = false;
|
||||
}
|
||||
|
||||
public SipTransactionInfo() {
|
||||
@@ -62,11 +63,11 @@ public class SipTransactionInfo {
|
||||
this.viaBranch = viaBranch;
|
||||
}
|
||||
|
||||
public boolean isFromServer() {
|
||||
return fromServer;
|
||||
public boolean isAsSender() {
|
||||
return asSender;
|
||||
}
|
||||
|
||||
public void setFromServer(boolean fromServer) {
|
||||
this.fromServer = fromServer;
|
||||
public void setAsSender(boolean asSender) {
|
||||
this.asSender = asSender;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.genersoft.iot.vmp.gb28181.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.AlarmNotifyMessageHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -8,10 +12,11 @@ import java.util.Properties;
|
||||
*/
|
||||
public class DefaultProperties {
|
||||
|
||||
public static Properties getProperties(String ip, boolean isDebug) {
|
||||
public static Properties getProperties(String ip, boolean isDebug, boolean sipLog) {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
|
||||
properties.setProperty("javax.sip.IP_ADDRESS", ip);
|
||||
// 关闭自动会话
|
||||
properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
|
||||
/**
|
||||
* 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
|
||||
@@ -26,7 +31,7 @@ public class DefaultProperties {
|
||||
// 接收所有notify请求,即使没有订阅
|
||||
properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
|
||||
properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
|
||||
properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
|
||||
properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "true");
|
||||
// 为_NULL _对话框传递_终止的_事件
|
||||
properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
|
||||
// 会话清理策略
|
||||
@@ -35,11 +40,38 @@ public class DefaultProperties {
|
||||
properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
|
||||
// 获取实际内容长度,不使用header中的长度信息
|
||||
properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
|
||||
// 线程可重入
|
||||
properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "true");
|
||||
// 定义应用程序打算多久审计一次 SIP 堆栈,了解其内部线程的健康状况(该属性指定连续审计之间的时间(以毫秒为单位))
|
||||
properties.setProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS", "30000");
|
||||
|
||||
/**
|
||||
* sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
|
||||
*/
|
||||
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
|
||||
Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class);
|
||||
if (sipLog) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
System.out.println("DEBUG");
|
||||
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
|
||||
}else if (logger.isInfoEnabled()) {
|
||||
System.out.println("INFO1");
|
||||
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
|
||||
}else if (logger.isWarnEnabled()) {
|
||||
System.out.println("WARNING");
|
||||
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "WARNING");
|
||||
}else if (logger.isErrorEnabled()) {
|
||||
System.out.println("ERROR");
|
||||
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
|
||||
}else {
|
||||
System.out.println("INFO2");
|
||||
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
|
||||
}
|
||||
logger.info("[SIP日志]级别为: {}", properties.getProperty("gov.nist.javax.sip.TRACE_LEVEL"));
|
||||
}else {
|
||||
logger.info("[SIP日志]已关闭");
|
||||
}
|
||||
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.genersoft.iot.vmp.gb28181.conf;
|
||||
|
||||
import gov.nist.core.StackLogger;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* sip日志格式化
|
||||
* 暂不使用
|
||||
*/
|
||||
public class SipLoggerPass implements StackLogger {
|
||||
|
||||
@Override
|
||||
public void logStackTrace() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logStackTrace(int traceLevel) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logException(Throwable ex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message, Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logTrace(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFatalError(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled(int logLevel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message, Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String string) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableLogging() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableLogging() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBuildTimeStamp(String buildTimeStamp) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStackProperties(Properties stackProperties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoggerName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import org.springframework.util.ObjectUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月13日 下午4:03:02
|
||||
@@ -51,6 +51,7 @@ public class VideoStreamSessionManager {
|
||||
ssrcTransaction.setSsrc(ssrc);
|
||||
ssrcTransaction.setMediaServerId(mediaServerId);
|
||||
ssrcTransaction.setType(type);
|
||||
|
||||
RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
|
||||
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
|
||||
}
|
||||
|
||||
@@ -170,11 +170,11 @@ public class SIPRequestHeaderProvider {
|
||||
//from
|
||||
SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isFromServer()?transactionInfo.getFromTag():transactionInfo.getToTag());
|
||||
FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,transactionInfo.isFromServer()?transactionInfo.getToTag():transactionInfo.getFromTag());
|
||||
ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
@@ -186,11 +186,6 @@ public class SIPRequestHeaderProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
|
||||
|
||||
Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
@@ -574,10 +574,11 @@ public class SIPCommander implements ISIPCommander {
|
||||
if (inviteStreamCallback != null) {
|
||||
inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()));
|
||||
}
|
||||
|
||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent -> {
|
||||
ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
|
||||
SIPResponse response = (SIPResponse) responseEvent.getResponse();
|
||||
streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
|
||||
streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -655,7 +656,12 @@ public class SIPCommander implements ISIPCommander {
|
||||
*/
|
||||
@Override
|
||||
public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException {
|
||||
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callId, stream);
|
||||
SsrcTransaction ssrcTransaction;
|
||||
if (callId != null) {
|
||||
ssrcTransaction = streamSession.getSsrcTransaction(null, null, callId, null);
|
||||
}else {
|
||||
ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, stream);
|
||||
}
|
||||
if (ssrcTransaction == null) {
|
||||
throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream);
|
||||
}
|
||||
@@ -769,7 +775,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
|
||||
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
|
||||
|
||||
@@ -307,19 +307,20 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
|
||||
public void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,int status) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (parentPlatform == null) {
|
||||
return ;
|
||||
}
|
||||
String statusStr = (status==1)?"ONLINE":"OFFLINE";
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer deviceStatusXml = new StringBuffer(600);
|
||||
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
deviceStatusXml.append("<Response>\r\n");
|
||||
deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
|
||||
deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
|
||||
deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
|
||||
deviceStatusXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
deviceStatusXml.append("<Result>OK</Result>\r\n");
|
||||
deviceStatusXml.append("<Online>ONLINE</Online>\r\n");
|
||||
deviceStatusXml.append("<Online>"+statusStr+"</Online>\r\n");
|
||||
deviceStatusXml.append("<Status>OK</Status>\r\n");
|
||||
deviceStatusXml.append("</Response>\r\n");
|
||||
|
||||
@@ -327,7 +328,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import gov.nist.javax.sip.RequestEventExt;
|
||||
@@ -59,6 +62,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
@Autowired
|
||||
private SIPSender sipSender;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// 添加消息处理的订阅
|
||||
@@ -128,15 +134,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
// 添加Expires头
|
||||
response.addHeader(request.getExpires());
|
||||
|
||||
// 获取到通信地址等信息
|
||||
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||
String received = viaHeader.getReceived();
|
||||
int rPort = viaHeader.getRPort();
|
||||
// 解析本地地址替代
|
||||
if (ObjectUtils.isEmpty(received) || rPort == -1) {
|
||||
received = viaHeader.getHost();
|
||||
rPort = viaHeader.getPort();
|
||||
}
|
||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
|
||||
userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||
|
||||
if (device == null) {
|
||||
device = new Device();
|
||||
device.setStreamMode("UDP");
|
||||
@@ -146,9 +146,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
device.setDeviceId(deviceId);
|
||||
device.setOnline(0);
|
||||
}
|
||||
device.setIp(received);
|
||||
device.setPort(rPort);
|
||||
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
|
||||
device.setIp(remoteAddressInfo.getIp());
|
||||
device.setPort(remoteAddressInfo.getPort());
|
||||
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
|
||||
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
||||
if (request.getExpires().getExpires() == 0) {
|
||||
// 注销成功
|
||||
|
||||
@@ -67,6 +67,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
|
||||
@Override
|
||||
public void process(RequestEvent evt) {
|
||||
SIPRequest sipRequest = (SIPRequest)evt.getRequest();
|
||||
logger.info("接收到消息:" + evt.getRequest());
|
||||
logger.debug("接收到消息:" + evt.getRequest());
|
||||
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||
CallIdHeader callIdHeader = sipRequest.getCallIdHeader();
|
||||
@@ -94,7 +95,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
|
||||
if (device == null && parentPlatform == null) {
|
||||
// 不存在则回复404
|
||||
responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found");
|
||||
logger.warn("[设备未找到 ]: {}", deviceId);
|
||||
logger.warn("[设备未找到 ]deviceId: {}, callId: {}", deviceId, callIdHeader.getCallId());
|
||||
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
|
||||
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
|
||||
deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import org.dom4j.Element;
|
||||
@@ -17,13 +19,10 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.header.ViaHeader;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
|
||||
@@ -33,6 +32,7 @@ import java.text.ParseException;
|
||||
@Component
|
||||
public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
|
||||
private final static String cmdType = "Keepalive";
|
||||
|
||||
@@ -42,6 +42,12 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
notifyMessageHandler.addHandler(cmdType, this);
|
||||
@@ -53,26 +59,27 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
||||
// 未注册的设备不做处理
|
||||
return;
|
||||
}
|
||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||
// 回复200 OK
|
||||
try {
|
||||
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
||||
responseAck(request, Response.OK);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 心跳回复: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 心跳回复: {}", e.getMessage());
|
||||
}
|
||||
// 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息
|
||||
// 获取到通信地址等信息
|
||||
ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME);
|
||||
String received = viaHeader.getReceived();
|
||||
int rPort = viaHeader.getRPort();
|
||||
// 解析本地地址替代
|
||||
if (ObjectUtils.isEmpty(received) || rPort == -1) {
|
||||
received = viaHeader.getHost();
|
||||
rPort = viaHeader.getPort();
|
||||
|
||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
|
||||
device.setPort(remoteAddressInfo.getPort());
|
||||
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
|
||||
device.setIp(remoteAddressInfo.getIp());
|
||||
}
|
||||
if (device.getPort() != rPort) {
|
||||
device.setPort(rPort);
|
||||
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
|
||||
if (device.getKeepaliveTime() == null) {
|
||||
device.setKeepaliveIntervalTime(60);
|
||||
}else {
|
||||
long lastTime = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(device.getKeepaliveTime());
|
||||
device.setKeepaliveIntervalTime(new Long(System.currentTimeMillis()/1000-lastTime).intValue());
|
||||
}
|
||||
|
||||
device.setKeepaliveTime(DateUtil.getNow());
|
||||
|
||||
if (device.getOnline() == 1) {
|
||||
@@ -80,9 +87,15 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
||||
}else {
|
||||
// 对于已经离线的设备判断他的注册是否已经过期
|
||||
if (!deviceService.expire(device)){
|
||||
device.setOnline(0);
|
||||
deviceService.online(device);
|
||||
}
|
||||
}
|
||||
// 刷新过期任务
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||
// 如果三次心跳失败,则设置设备离线
|
||||
dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId()), device.getKeepaliveIntervalTime()*1000*3);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
@@ -24,6 +25,8 @@ import javax.sip.header.FromHeader;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
|
||||
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||
|
||||
@Component
|
||||
public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||
|
||||
@@ -62,13 +65,19 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
|
||||
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||
// 回复200 OK
|
||||
try {
|
||||
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
||||
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage());
|
||||
}
|
||||
String sn = rootElement.element("SN").getText();
|
||||
String channelId = getText(rootElement, "DeviceID");
|
||||
DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId);
|
||||
if (deviceChannel ==null){
|
||||
logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
|
||||
cmderFroPlatform.deviceStatusResponse(parentPlatform,channelId, sn, fromHeader.getTag(),deviceChannel.getStatus());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
|
||||
}
|
||||
|
||||
@@ -63,7 +63,12 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
|
||||
return;
|
||||
}
|
||||
String result = getText(rootElement, "Result");
|
||||
logger.info("[语音广播]回复:{}, {}/{}", result, device.getDeviceId(), channelId );
|
||||
Element infoElement = rootElement.element("Info");
|
||||
String reason = null;
|
||||
if (infoElement != null) {
|
||||
reason = getText(infoElement, "Reason");
|
||||
}
|
||||
logger.info("[语音广播]回复:{}, {}/{}", reason == null? result : result + ": " + reason, device.getDeviceId(), channelId );
|
||||
|
||||
// 回复200 OK
|
||||
responseAck(request, Response.OK);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.genersoft.iot.vmp.gb28181.utils;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import gov.nist.javax.sip.address.AddressImpl;
|
||||
import gov.nist.javax.sip.address.SipUri;
|
||||
import gov.nist.javax.sip.header.Subject;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.PeerUnavailableException;
|
||||
@@ -139,4 +141,31 @@ public class SipUtils {
|
||||
int typeCodeFromGbCode = getTypeCodeFromGbCode(deviceId);
|
||||
return typeCodeFromGbCode > 130 && typeCodeFromGbCode < 199;
|
||||
}
|
||||
/**
|
||||
* 从请求中获取设备ip地址和端口号
|
||||
* @param request 请求
|
||||
* @param sipUseSourceIpAsRemoteAddress false 从via中获取地址, true 直接获取远程地址
|
||||
* @return 地址信息
|
||||
*/
|
||||
public static RemoteAddressInfo getRemoteAddressFromRequest(SIPRequest request, boolean sipUseSourceIpAsRemoteAddress) {
|
||||
|
||||
String remoteAddress;
|
||||
int remotePort;
|
||||
if (sipUseSourceIpAsRemoteAddress) {
|
||||
remoteAddress = request.getRemoteAddress().getHostAddress();
|
||||
remotePort = request.getRemotePort();
|
||||
}else {
|
||||
// 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息
|
||||
// 获取到通信地址等信息
|
||||
remoteAddress = request.getTopmostViaHeader().getReceived();
|
||||
remotePort = request.getTopmostViaHeader().getRPort();
|
||||
// 解析本地地址替代
|
||||
if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) {
|
||||
remoteAddress = request.getTopmostViaHeader().getHost();
|
||||
remotePort = request.getTopmostViaHeader().getPort();
|
||||
}
|
||||
}
|
||||
|
||||
return new RemoteAddressInfo(remoteAddress, remotePort);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user