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:
648540858
2023-02-10 15:54:42 +08:00
85 changed files with 2638 additions and 1856 deletions

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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) {
// 注销成功

View File

@@ -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());

View File

@@ -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

View File

@@ -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());
}

View File

@@ -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);

View File

@@ -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);
}
}