重构28181信令结构,解决循环依赖导致的无法直接注入
This commit is contained in:
parent
341ea7110a
commit
f1217682a9
@ -1,7 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.common;
|
package com.genersoft.iot.vmp.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 定义常量
|
* @description: 定义常量
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年5月30日 下午3:04:04
|
* @date: 2019年5月30日 下午3:04:04
|
||||||
*
|
*
|
||||||
|
@ -16,7 +16,7 @@ import redis.clients.jedis.JedisPool;
|
|||||||
import redis.clients.jedis.JedisPoolConfig;
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
* @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年5月30日 上午10:58:25
|
* @date: 2019年5月30日 上午10:58:25
|
||||||
*
|
*
|
||||||
|
@ -32,5 +32,7 @@ public class SipDeviceRunner implements CommandLineRunner {
|
|||||||
for (String deviceId : onlineForAll) {
|
for (String deviceId : onlineForAll) {
|
||||||
storager.online(deviceId);
|
storager.online(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 获取数据库配置
|
* @description: 获取数据库配置
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午2:46:00
|
* @date: 2020年5月6日 下午2:46:00
|
||||||
*/
|
*/
|
||||||
|
@ -1,19 +1,10 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181;
|
package com.genersoft.iot.vmp.gb28181;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.TooManyListenersException;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.header.CallIdHeader;
|
|
||||||
import javax.sip.header.Header;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import gov.nist.javax.sip.SipProviderImpl;
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -21,14 +12,15 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import javax.sip.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
|
import java.util.Properties;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
import java.util.TooManyListenersException;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class SipLayer implements SipListener {
|
public class SipLayer{
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
|
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
|
||||||
|
|
||||||
@ -36,7 +28,7 @@ public class SipLayer implements SipListener {
|
|||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPProcessorFactory processorFactory;
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipSubscribe sipSubscribe;
|
private SipSubscribe sipSubscribe;
|
||||||
@ -50,19 +42,16 @@ public class SipLayer implements SipListener {
|
|||||||
*/
|
*/
|
||||||
private ThreadPoolExecutor processThreadPool;
|
private ThreadPoolExecutor processThreadPool;
|
||||||
|
|
||||||
@Bean("initSipServer")
|
public SipLayer() {
|
||||||
private ThreadPoolExecutor initSipServer() {
|
|
||||||
|
|
||||||
int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
|
int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
|
||||||
LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
|
LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
|
||||||
processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
|
processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
|
||||||
0L,TimeUnit.MILLISECONDS,processQueue,
|
0L,TimeUnit.MILLISECONDS,processQueue,
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy());
|
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
return processThreadPool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean("sipFactory")
|
@Bean("sipFactory")
|
||||||
@DependsOn("initSipServer")
|
|
||||||
private SipFactory createSipFactory() {
|
private SipFactory createSipFactory() {
|
||||||
sipFactory = SipFactory.getInstance();
|
sipFactory = SipFactory.getInstance();
|
||||||
sipFactory.setPathName("gov.nist");
|
sipFactory.setPathName("gov.nist");
|
||||||
@ -70,7 +59,7 @@ public class SipLayer implements SipListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean("sipStack")
|
@Bean("sipStack")
|
||||||
@DependsOn({"initSipServer", "sipFactory"})
|
@DependsOn({"sipFactory"})
|
||||||
private SipStack createSipStack() throws PeerUnavailableException {
|
private SipStack createSipStack() throws PeerUnavailableException {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
|
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
|
||||||
@ -96,7 +85,7 @@ public class SipLayer implements SipListener {
|
|||||||
try {
|
try {
|
||||||
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "TCP");
|
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "TCP");
|
||||||
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||||
tcpSipProvider.addSipListener(this);
|
tcpSipProvider.addSipListener(sipProcessorObserver);
|
||||||
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}");
|
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}");
|
||||||
} catch (TransportNotSupportedException e) {
|
} catch (TransportNotSupportedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -119,8 +108,7 @@ public class SipLayer implements SipListener {
|
|||||||
try {
|
try {
|
||||||
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
|
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
|
||||||
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||||
udpSipProvider.addSipListener(this);
|
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||||
// udpSipProvider.setAutomaticDialogSupportEnabled(false);
|
|
||||||
} catch (TransportNotSupportedException e) {
|
} catch (TransportNotSupportedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InvalidArgumentException e) {
|
} catch (InvalidArgumentException e) {
|
||||||
@ -135,140 +123,4 @@ public class SipLayer implements SipListener {
|
|||||||
return udpSipProvider;
|
return udpSipProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a
|
|
||||||
* new request arrives.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processRequest(RequestEvent evt) {
|
|
||||||
logger.debug(evt.getRequest().toString());
|
|
||||||
// 由于jainsip是单线程程序,为提高性能并发处理
|
|
||||||
processThreadPool.execute(() -> {
|
|
||||||
if (processorFactory != null) {
|
|
||||||
processorFactory.createRequestProcessor(evt).process();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processResponse(ResponseEvent evt) {
|
|
||||||
Response response = evt.getResponse();
|
|
||||||
logger.debug(evt.getResponse().toString());
|
|
||||||
int status = response.getStatusCode();
|
|
||||||
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
|
||||||
ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
|
||||||
try {
|
|
||||||
processor.process(evt, this, sipConfig);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
|
||||||
if (callIdHeader != null) {
|
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
|
|
||||||
if (subscribe != null) {
|
|
||||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(evt);
|
|
||||||
subscribe.response(eventResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((status >= 100) && (status < 200)) {
|
|
||||||
// 增加其它无需回复的响应,如101、180等
|
|
||||||
} else {
|
|
||||||
logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
|
|
||||||
if (evt.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
|
||||||
if (callIdHeader != null) {
|
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
|
||||||
if (subscribe != null) {
|
|
||||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(evt);
|
|
||||||
subscribe.response(eventResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processTimeout
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param timeoutEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processTimeout(TimeoutEvent timeoutEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
CallIdHeader callIdHeader = timeoutEvent.getClientTransaction().getDialog().getCallId();
|
|
||||||
String callId = callIdHeader.getCallId();
|
|
||||||
SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId);
|
|
||||||
SipSubscribe.EventResult<TimeoutEvent> timeoutEventEventResult = new SipSubscribe.EventResult<>(timeoutEvent);
|
|
||||||
errorSubscribe.response(timeoutEventEventResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processIOException
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param exceptionEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processIOException(IOExceptionEvent exceptionEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processTransactionTerminated
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param transactionTerminatedEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
// CallIdHeader callIdHeader = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId();
|
|
||||||
// String callId = callIdHeader.getCallId();
|
|
||||||
// SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId);
|
|
||||||
// SipSubscribe.EventResult<TransactionTerminatedEvent> eventResult = new SipSubscribe.EventResult<>(transactionTerminatedEvent);
|
|
||||||
// errorSubscribe.response(eventResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processDialogTerminated
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param dialogTerminatedEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
// CallIdHeader callIdHeader = dialogTerminatedEvent.getDialog().getCallId();
|
|
||||||
// String callId = callIdHeader.getCallId();
|
|
||||||
// SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId);
|
|
||||||
// SipSubscribe.EventResult<DialogTerminatedEvent> eventResult = new SipSubscribe.EventResult<>(dialogTerminatedEvent);
|
|
||||||
// errorSubscribe.response(eventResult);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:注册逻辑处理,当设备注册后触发逻辑。
|
* @description:注册逻辑处理,当设备注册后触发逻辑。
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午9:41:46
|
* @date: 2020年5月8日 下午9:41:46
|
||||||
*/
|
*/
|
||||||
|
@ -109,6 +109,11 @@ public class Device {
|
|||||||
*/
|
*/
|
||||||
private String charset ;
|
private String charset ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目录订阅周期,0为不订阅
|
||||||
|
*/
|
||||||
|
private int subscribeCycleForCatalog ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getDeviceId() {
|
public String getDeviceId() {
|
||||||
@ -270,4 +275,12 @@ public class Device {
|
|||||||
public void setCharset(String charset) {
|
public void setCharset(String charset) {
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSubscribeCycleForCatalog() {
|
||||||
|
return subscribeCycleForCatalog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscribeCycleForCatalog(int subscribeCycleForCatalog) {
|
||||||
|
this.subscribeCycleForCatalog = subscribeCycleForCatalog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 移动位置bean
|
* @description: 移动位置bean
|
||||||
* @author: lawrencehj
|
* @author: lawrencehj
|
||||||
* @date: 2021年1月23日
|
* @date: 2021年1月23日
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@ package com.genersoft.iot.vmp.gb28181.bean;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备录像信息bean
|
* @description:设备录像信息bean
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午2:05:56
|
* @date: 2020年5月8日 下午2:05:56
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备录像bean
|
* @description:设备录像bean
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午2:06:54
|
* @date: 2020年5月8日 下午2:06:54
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备离在线状态检测器,用于检测设备状态
|
* @description:设备离在线状态检测器,用于检测设备状态
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月13日 下午2:40:29
|
* @date: 2020年5月13日 下午2:40:29
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
|
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Event事件通知推送器,支持推送在线事件、离线事件
|
* @description:Event事件通知推送器,支持推送在线事件、离线事件
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:30:50
|
* @date: 2020年5月6日 上午11:30:50
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +12,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
* @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:35:46
|
* @date: 2020年5月6日 上午11:35:46
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +12,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
* @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:35:46
|
* @date: 2020年5月6日 上午11:35:46
|
||||||
*/
|
*/
|
||||||
|
@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.gb28181.event.offline;
|
|||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 离线事件类
|
* @description: 离线事件类
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:33:13
|
* @date: 2020年5月6日 上午11:33:13
|
||||||
*/
|
*/
|
||||||
|
@ -11,8 +11,8 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源:
|
* @description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源:
|
||||||
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
|
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor}
|
||||||
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}
|
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午1:51:23
|
* @date: 2020年5月6日 下午1:51:23
|
||||||
@ -54,5 +54,8 @@ public class OfflineEventListener implements ApplicationListener<OfflineEvent> {
|
|||||||
|
|
||||||
// 处理离线监听
|
// 处理离线监听
|
||||||
storager.outline(event.getDeviceId());
|
storager.outline(event.getDeviceId());
|
||||||
|
|
||||||
|
// TODO 离线取消订阅
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 在线事件类
|
* @description: 在线事件类
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:32:56
|
* @date: 2020年5月6日 上午11:32:56
|
||||||
*/
|
*/
|
||||||
|
@ -13,12 +13,11 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源:
|
* @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源:
|
||||||
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
|
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor}
|
||||||
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor}
|
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.MessageRequestProcessor}
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午1:51:23
|
* @date: 2020年5月6日 下午1:51:23
|
||||||
*/
|
*/
|
||||||
|
@ -18,7 +18,7 @@ import javax.sip.ResponseEvent;
|
|||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 平台心跳超时事件
|
* @description: 平台心跳超时事件
|
||||||
* @author: panll
|
* @author: panll
|
||||||
* @date: 2020年11月5日 10:00
|
* @date: 2020年11月5日 10:00
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 平台未注册事件,来源有二:
|
* @description: 平台未注册事件,来源有二:
|
||||||
* 1、平台新添加
|
* 1、平台新添加
|
||||||
* 2、平台心跳超时
|
* 2、平台心跳超时
|
||||||
* @author: panll
|
* @author: panll
|
||||||
|
@ -15,7 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
* @description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月13日 下午4:03:02
|
* @date: 2020年5月13日 下午4:03:02
|
||||||
*/
|
*/
|
||||||
|
@ -1,243 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit;
|
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
import javax.sip.SipProvider;
|
|
||||||
import javax.sip.header.CSeqHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
|
||||||
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.AckRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.ByeResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.CancelResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.InviteResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: SIP信令处理分配
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:24:37
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class SIPProcessorFactory {
|
|
||||||
|
|
||||||
// private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SipConfig sipConfig;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RegisterLogicHandler handler;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EventPublisher publisher;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SIPCommander cmder;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SIPCommanderFroPlatform cmderFroPlatform;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IDeviceAlarmService deviceAlarmService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisUtil redis;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeferredResultHolder deferredResultHolder;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceOffLineDetector offLineDetector;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private InviteResponseProcessor inviteResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ByeResponseProcessor byeResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CancelResponseProcessor cancelResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Lazy
|
|
||||||
private RegisterResponseProcessor registerResponseProcessor;
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private OtherResponseProcessor otherResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IPlayService playService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IMediaServerService mediaServerService;
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
|
||||||
private SipProvider tcpSipProvider;
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
|
||||||
private SipProvider udpSipProvider;
|
|
||||||
|
|
||||||
public ISIPRequestProcessor createRequestProcessor(RequestEvent evt) {
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
String method = request.getMethod();
|
|
||||||
// logger.info("接收到消息:"+request.getMethod());
|
|
||||||
// sipSubscribe.getSubscribe(evt.getServerTransaction().getBranchId()).response(evt);
|
|
||||||
if (Request.INVITE.equals(method)) {
|
|
||||||
InviteRequestProcessor processor = new InviteRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
|
|
||||||
processor.setCmder(cmder);
|
|
||||||
processor.setCmderFroPlatform(cmderFroPlatform);
|
|
||||||
processor.setPlayService(playService);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
|
||||||
processor.setMediaServerService(mediaServerService);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.REGISTER.equals(method)) {
|
|
||||||
RegisterRequestProcessor processor = new RegisterRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setHandler(handler);
|
|
||||||
processor.setPublisher(publisher);
|
|
||||||
processor.setSipConfig(sipConfig);
|
|
||||||
processor.setVideoManagerStorager(storager);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.SUBSCRIBE.equals(method)) {
|
|
||||||
SubscribeRequestProcessor processor = new SubscribeRequestProcessor();
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.ACK.equals(method)) {
|
|
||||||
AckRequestProcessor processor = new AckRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
|
||||||
processor.setMediaServerService(mediaServerService);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.BYE.equals(method)) {
|
|
||||||
ByeRequestProcessor processor = new ByeRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
|
||||||
processor.setSIPCommander(cmder);
|
|
||||||
processor.setMediaServerService(mediaServerService);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.CANCEL.equals(method)) {
|
|
||||||
CancelRequestProcessor processor = new CancelRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.MESSAGE.equals(method)) {
|
|
||||||
MessageRequestProcessor processor = new MessageRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setPublisher(publisher);
|
|
||||||
processor.setRedis(redis);
|
|
||||||
processor.setDeferredResultHolder(deferredResultHolder);
|
|
||||||
processor.setOffLineDetector(offLineDetector);
|
|
||||||
processor.setCmder(cmder);
|
|
||||||
processor.setCmderFroPlatform(cmderFroPlatform);
|
|
||||||
processor.setDeviceAlarmService(deviceAlarmService);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.NOTIFY.equalsIgnoreCase(method)) {
|
|
||||||
NotifyRequestProcessor processor = new NotifyRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setPublisher(publisher);
|
|
||||||
processor.setRedis(redis);
|
|
||||||
processor.setDeferredResultHolder(deferredResultHolder);
|
|
||||||
processor.setOffLineDetector(offLineDetector);
|
|
||||||
processor.setCmder(cmder);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
return processor;
|
|
||||||
} else {
|
|
||||||
OtherRequestProcessor processor = new OtherRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
return processor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) {
|
|
||||||
|
|
||||||
Response response = evt.getResponse();
|
|
||||||
CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
|
||||||
String method = cseqHeader.getMethod();
|
|
||||||
if(Request.INVITE.equals(method)){
|
|
||||||
return inviteResponseProcessor;
|
|
||||||
} else if (Request.BYE.equals(method)) {
|
|
||||||
return byeResponseProcessor;
|
|
||||||
} else if (Request.CANCEL.equals(method)) {
|
|
||||||
return cancelResponseProcessor;
|
|
||||||
}else if (Request.REGISTER.equals(method)) {
|
|
||||||
return registerResponseProcessor;
|
|
||||||
} else {
|
|
||||||
return otherResponseProcessor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SipProvider getTcpSipProvider() {
|
|
||||||
if (tcpSipProvider == null) {
|
|
||||||
tcpSipProvider = (SipProvider) SpringBeanFactory.getBean("tcpSipProvider");
|
|
||||||
}
|
|
||||||
return tcpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SipProvider getUdpSipProvider() {
|
|
||||||
if (udpSipProvider == null) {
|
|
||||||
udpSipProvider = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
|
|
||||||
}
|
|
||||||
return udpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,113 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.header.CSeqHeader;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: SIP信令处理类观察者
|
||||||
|
* @author: panlinlin
|
||||||
|
* @date: 2021年11月5日 下午15:32
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SIPProcessorObserver implements SipListener {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class);
|
||||||
|
|
||||||
|
private static Map<String, ISIPRequestProcessor> requestProcessorMap = new ConcurrentHashMap<>();
|
||||||
|
private static Map<String, ISIPResponseProcessor> responseProcessorMap = new ConcurrentHashMap<>();
|
||||||
|
private static ITimeoutProcessor timeoutProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 request订阅
|
||||||
|
* @param method 方法名
|
||||||
|
* @param processor 处理程序
|
||||||
|
*/
|
||||||
|
public void addRequestProcessor(String method, ISIPRequestProcessor processor) {
|
||||||
|
requestProcessorMap.put(method, processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 response订阅
|
||||||
|
* @param method 方法名
|
||||||
|
* @param processor 处理程序
|
||||||
|
*/
|
||||||
|
public void addResponseProcessor(String method, ISIPResponseProcessor processor) {
|
||||||
|
responseProcessorMap.put(method, processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 超时事件订阅
|
||||||
|
* @param processor 处理程序
|
||||||
|
*/
|
||||||
|
public void addTimeoutProcessor(ITimeoutProcessor processor) {
|
||||||
|
this.timeoutProcessor = processor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分发RequestEvent事件
|
||||||
|
* @param requestEvent RequestEvent事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void processRequest(RequestEvent requestEvent) {
|
||||||
|
String method = requestEvent.getRequest().getMethod();
|
||||||
|
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
|
||||||
|
if (sipRequestProcessor == null) {
|
||||||
|
logger.warn("不支持方法{}的request", method);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
requestProcessorMap.get(requestEvent.getRequest().getMethod()).process(requestEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分发ResponseEvent事件
|
||||||
|
* @param responseEvent responseEvent事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void processResponse(ResponseEvent responseEvent) {
|
||||||
|
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
|
||||||
|
String method = cseqHeader.getMethod();
|
||||||
|
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method);
|
||||||
|
if (sipRequestProcessor == null) {
|
||||||
|
logger.warn("不支持方法{}的response", method);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sipRequestProcessor.process(responseEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向超时订阅发送消息
|
||||||
|
* @param timeoutEvent timeoutEvent事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void processTimeout(TimeoutEvent timeoutEvent) {
|
||||||
|
if(timeoutProcessor != null) {
|
||||||
|
timeoutProcessor.process(timeoutEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processIOException(IOExceptionEvent exceptionEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -7,7 +7,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
|
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.MessageRequestProcessor;
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -11,7 +11,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 异步请求处理
|
* @description: 异步请求处理
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午7:59:05
|
* @date: 2020年5月8日 下午7:59:05
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 请求信息定义
|
* @description: 请求信息定义
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午1:09:18
|
* @date: 2020年5月8日 下午1:09:18
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|||||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午9:16:34
|
* @date: 2020年5月3日 下午9:16:34
|
||||||
*/
|
*/
|
||||||
@ -299,4 +299,11 @@ public interface ISIPCommander {
|
|||||||
* @return true = 命令发送成功
|
* @return true = 命令发送成功
|
||||||
*/
|
*/
|
||||||
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅、取消订阅目录信息
|
||||||
|
* @param device 视频设备
|
||||||
|
* @return true = 命令发送成功
|
||||||
|
*/
|
||||||
|
boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 平台命令request创造器 TODO 冗余代码太多待优化
|
* @description: 平台命令request创造器 TODO 冗余代码太多待优化
|
||||||
* @author: panll
|
* @author: panll
|
||||||
* @date: 2020年5月6日 上午9:29:02
|
* @date: 2020年5月6日 上午9:29:02
|
||||||
*/
|
*/
|
||||||
|
@ -18,7 +18,7 @@ import com.genersoft.iot.vmp.conf.SipConfig;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:摄像头命令request创造器 TODO 冗余代码太多待优化
|
* @description:摄像头命令request创造器 TODO 冗余代码太多待优化
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午9:29:02
|
* @date: 2020年5月6日 上午9:29:02
|
||||||
*/
|
*/
|
||||||
|
@ -1,20 +1,17 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.CallIdHeader;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||||
import com.genersoft.iot.vmp.media.zlm.*;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
@ -29,20 +26,20 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
import javax.sip.header.ViaHeader;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午9:22:48
|
* @date: 2020年5月3日 下午9:22:48
|
||||||
*/
|
*/
|
||||||
@ -55,12 +52,10 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Lazy
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="tcpSipProvider")
|
@Qualifier(value="tcpSipProvider")
|
||||||
private SipProviderImpl tcpSipProvider;
|
private SipProviderImpl tcpSipProvider;
|
||||||
|
|
||||||
@Lazy
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="udpSipProvider")
|
@Qualifier(value="udpSipProvider")
|
||||||
private SipProviderImpl udpSipProvider;
|
private SipProviderImpl udpSipProvider;
|
||||||
@ -89,11 +84,6 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
private SIPDialog dialog;
|
|
||||||
|
|
||||||
public SipConfig getSipConfig() {
|
|
||||||
return sipConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
||||||
@ -1490,6 +1480,33 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
|
||||||
|
try {
|
||||||
|
StringBuffer cmdXml = new StringBuffer(200);
|
||||||
|
cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||||
|
cmdXml.append("<Query>\r\n");
|
||||||
|
cmdXml.append("<CmdType>CataLog</CmdType>\r\n");
|
||||||
|
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||||
|
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||||
|
cmdXml.append("</Query>\r\n");
|
||||||
|
|
||||||
|
String tm = Long.toString(System.currentTimeMillis());
|
||||||
|
|
||||||
|
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
||||||
|
: udpSipProvider.getNewCallId();
|
||||||
|
|
||||||
|
Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "presence" , callIdHeader);
|
||||||
|
transmitRequest(device, request, errorEvent, okEvent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
||||||
return transmitRequest(device, request, null, null);
|
return transmitRequest(device, request, null, null);
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
public abstract class SIPResponseProcessorAbstract implements InitializingBean, ISIPResponseProcessor {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout;
|
||||||
|
|
||||||
|
import javax.sip.TimeoutEvent;
|
||||||
|
|
||||||
|
public interface ITimeoutProcessor {
|
||||||
|
void process(TimeoutEvent event);
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.TimeoutEvent;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver processorObserver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
processorObserver.addTimeoutProcessor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(TimeoutEvent event) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
CallIdHeader callIdHeader = event.getClientTransaction().getDialog().getCallId();
|
||||||
|
String callId = callIdHeader.getCallId();
|
||||||
|
SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId);
|
||||||
|
SipSubscribe.EventResult<TimeoutEvent> timeoutEventEventResult = new SipSubscribe.EventResult<>(event);
|
||||||
|
errorSubscribe.response(timeoutEventEventResult);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理接收IPCamera发来的SIP协议请求消息
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:42:22
|
|
||||||
*/
|
|
||||||
public interface ISIPRequestProcessor {
|
|
||||||
|
|
||||||
public void process();
|
|
||||||
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request;
|
|
||||||
|
|
||||||
import javax.sip.PeerUnavailableException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipFactory;
|
|
||||||
import javax.sip.SipProvider;
|
|
||||||
import javax.sip.TransactionAlreadyExistsException;
|
|
||||||
import javax.sip.TransactionUnavailableException;
|
|
||||||
import javax.sip.address.AddressFactory;
|
|
||||||
import javax.sip.header.HeaderFactory;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.MessageFactory;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
|
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
|
||||||
import gov.nist.javax.sip.stack.SIPServerTransaction;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理接收IPCamera发来的SIP协议请求消息
|
|
||||||
* @author: songww
|
|
||||||
* @date: 2020年5月3日 下午4:42:22
|
|
||||||
*/
|
|
||||||
public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcessor {
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SIPRequestAbstractProcessor.class);
|
|
||||||
|
|
||||||
protected RequestEvent evt;
|
|
||||||
|
|
||||||
private SipProvider tcpSipProvider;
|
|
||||||
|
|
||||||
private SipProvider udpSipProvider;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process() {
|
|
||||||
this.process(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void process(RequestEvent evt);
|
|
||||||
|
|
||||||
public ServerTransaction getServerTransaction(RequestEvent evt) {
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
ServerTransaction serverTransaction = evt.getServerTransaction();
|
|
||||||
// 判断TCP还是UDP
|
|
||||||
boolean isTcp = false;
|
|
||||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
|
||||||
String transport = reqViaHeader.getTransport();
|
|
||||||
if (transport.equals("TCP")) {
|
|
||||||
isTcp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serverTransaction == null) {
|
|
||||||
try {
|
|
||||||
if (isTcp) {
|
|
||||||
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
|
|
||||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
|
||||||
if (serverTransaction == null) {
|
|
||||||
serverTransaction = tcpSipProvider.getNewServerTransaction(request);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
|
|
||||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
|
||||||
if (serverTransaction == null) {
|
|
||||||
serverTransaction = udpSipProvider.getNewServerTransaction(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (TransactionAlreadyExistsException e) {
|
|
||||||
logger.error(e.getMessage());
|
|
||||||
} catch (TransactionUnavailableException e) {
|
|
||||||
logger.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return serverTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressFactory getAddressFactory() {
|
|
||||||
try {
|
|
||||||
return SipFactory.getInstance().createAddressFactory();
|
|
||||||
} catch (PeerUnavailableException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HeaderFactory getHeaderFactory() {
|
|
||||||
try {
|
|
||||||
return SipFactory.getInstance().createHeaderFactory();
|
|
||||||
} catch (PeerUnavailableException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageFactory getMessageFactory() {
|
|
||||||
try {
|
|
||||||
return SipFactory.getInstance().createMessageFactory();
|
|
||||||
} catch (PeerUnavailableException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestEvent getRequestEvent() {
|
|
||||||
return evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRequestEvent(RequestEvent evt) {
|
|
||||||
this.evt = evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SipProvider getTcpSipProvider() {
|
|
||||||
return tcpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTcpSipProvider(SipProvider tcpSipProvider) {
|
|
||||||
this.tcpSipProvider = tcpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SipProvider getUdpSipProvider() {
|
|
||||||
return udpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUdpSipProvider(SipProvider udpSipProvider) {
|
|
||||||
this.udpSipProvider = udpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,142 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.HeaderAddress;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:ACK请求处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:31:45
|
|
||||||
*/
|
|
||||||
public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class);
|
|
||||||
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
|
||||||
|
|
||||||
private IMediaServerService mediaServerService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理 ACK请求
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
//Request request = evt.getRequest();
|
|
||||||
Dialog dialog = evt.getDialog();
|
|
||||||
if (dialog == null) return;
|
|
||||||
//DialogState state = dialog.getState();
|
|
||||||
if (/*request.getMecodewwthod().equals(Request.INVITE) &&*/ dialog.getState()== DialogState.CONFIRMED) {
|
|
||||||
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
|
||||||
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
|
||||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId);
|
|
||||||
String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
|
|
||||||
String deviceId = sendRtpItem.getDeviceId();
|
|
||||||
StreamInfo streamInfo = null;
|
|
||||||
if (deviceId == null) {
|
|
||||||
streamInfo = new StreamInfo();
|
|
||||||
streamInfo.setApp(sendRtpItem.getApp());
|
|
||||||
streamInfo.setStreamId(sendRtpItem.getStreamId());
|
|
||||||
}else {
|
|
||||||
streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
|
||||||
sendRtpItem.setStreamId(streamInfo.getStreamId());
|
|
||||||
streamInfo.setApp("rtp");
|
|
||||||
}
|
|
||||||
|
|
||||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
|
||||||
logger.info(platformGbId);
|
|
||||||
logger.info(channelId);
|
|
||||||
Map<String, Object> param = new HashMap<>();
|
|
||||||
param.put("vhost","__defaultVhost__");
|
|
||||||
param.put("app",streamInfo.getApp());
|
|
||||||
param.put("stream",streamInfo.getStreamId());
|
|
||||||
param.put("ssrc", sendRtpItem.getSsrc());
|
|
||||||
param.put("dst_url",sendRtpItem.getIp());
|
|
||||||
param.put("dst_port", sendRtpItem.getPort());
|
|
||||||
param.put("is_udp", is_Udp);
|
|
||||||
//param.put ("src_port", sendRtpItem.getLocalPort());
|
|
||||||
// 设备推流查询,成功后才能转推
|
|
||||||
boolean rtpPushed = false;
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
while (!rtpPushed) {
|
|
||||||
try {
|
|
||||||
if (System.currentTimeMillis() - startTime < 30 * 1000) {
|
|
||||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
|
||||||
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
|
|
||||||
rtpPushed = true;
|
|
||||||
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
|
|
||||||
streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort());
|
|
||||||
zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
|
|
||||||
} else {
|
|
||||||
logger.info("等待设备推流[{}/{}].......",
|
|
||||||
streamInfo.getApp() ,streamInfo.getStreamId());
|
|
||||||
Thread.sleep(1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rtpPushed = true;
|
|
||||||
logger.info("设备推流[{}/{}]超时,终止向上级推流",
|
|
||||||
streamInfo.getApp() ,streamInfo.getStreamId());
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// try {
|
|
||||||
// Request ackRequest = null;
|
|
||||||
// CSeq csReq = (CSeq) request.getHeader(CSeq.NAME);
|
|
||||||
// ackRequest = dialog.createAck(csReq.getSeqNumber());
|
|
||||||
// dialog.sendAck(ackRequest);
|
|
||||||
// logger.info("send ack to callee:" + ackRequest.toString());
|
|
||||||
// } catch (SipException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// } catch (InvalidArgumentException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
|
||||||
return zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
|
||||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMediaServerService getMediaServerService() {
|
|
||||||
return mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
|
||||||
this.mediaServerService = mediaServerService;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.HeaderAddress;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: BYE请求处理器
|
|
||||||
* @author: lawrencehj
|
|
||||||
* @date: 2021年3月9日
|
|
||||||
*/
|
|
||||||
public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(ByeRequestProcessor.class);
|
|
||||||
|
|
||||||
private ISIPCommander cmder;
|
|
||||||
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
|
||||||
|
|
||||||
private IMediaServerService mediaServerService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理BYE请求
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
try {
|
|
||||||
responseAck(evt);
|
|
||||||
Dialog dialog = evt.getDialog();
|
|
||||||
if (dialog == null) return;
|
|
||||||
if (dialog.getState().equals(DialogState.TERMINATED)) {
|
|
||||||
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
|
||||||
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
|
||||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId);
|
|
||||||
logger.info("收到bye, [{}/{}]", platformGbId, channelId);
|
|
||||||
if (sendRtpItem != null){
|
|
||||||
String streamId = sendRtpItem.getStreamId();
|
|
||||||
Map<String, Object> param = new HashMap<>();
|
|
||||||
param.put("vhost","__defaultVhost__");
|
|
||||||
param.put("app",sendRtpItem.getApp());
|
|
||||||
param.put("stream",streamId);
|
|
||||||
param.put("ssrc",sendRtpItem.getSsrc());
|
|
||||||
logger.info("停止向上级推流:" + streamId);
|
|
||||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
|
||||||
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
|
|
||||||
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
|
|
||||||
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
|
|
||||||
logger.info(streamId + "无其它观看者,通知设备停止推流");
|
|
||||||
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 可能是设备主动停止
|
|
||||||
Device device = storager.queryVideoDeviceByChannelId(platformGbId);
|
|
||||||
if (device != null) {
|
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
|
|
||||||
if (streamInfo != null) {
|
|
||||||
redisCatchStorage.stopPlay(streamInfo);
|
|
||||||
}
|
|
||||||
storager.stopPlay(device.getDeviceId(), channelId);
|
|
||||||
mediaServerService.closeRTPServer(device, channelId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SipException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvalidArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复200 OK
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
|
||||||
return zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
|
||||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISIPCommander getSIPCommander() {
|
|
||||||
return cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSIPCommander(ISIPCommander cmder) {
|
|
||||||
this.cmder = cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMediaServerService getMediaServerService() {
|
|
||||||
return mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
|
||||||
this.mediaServerService = mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IVideoManagerStorager getStorager() {
|
|
||||||
return storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:CANCEL请求处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:23
|
|
||||||
*/
|
|
||||||
public class CancelRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理CANCEL请求
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param transaction
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
// TODO 优先级99 Cancel Request消息实现,此消息一般为级联消息,上级给下级发送请求取消指令
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,478 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import javax.sdp.*;
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.Address;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.*;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理INVITE请求
|
|
||||||
* @author: panll
|
|
||||||
* @date: 2021年1月14日
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(InviteRequestProcessor.class);
|
|
||||||
|
|
||||||
private SIPCommanderFroPlatform cmderFroPlatform;
|
|
||||||
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
private SIPCommander cmder;
|
|
||||||
|
|
||||||
private IPlayService playService;
|
|
||||||
|
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
|
||||||
|
|
||||||
private IMediaServerService mediaServerService;
|
|
||||||
|
|
||||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
|
||||||
return zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
|
||||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理invite请求
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* 请求消息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
// Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
|
|
||||||
try {
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
SipURI sipURI = (SipURI) request.getRequestURI();
|
|
||||||
String channelId = sipURI.getUser();
|
|
||||||
String requesterId = null;
|
|
||||||
|
|
||||||
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
|
|
||||||
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
|
||||||
SipUri uri = (SipUri) address.getURI();
|
|
||||||
requesterId = uri.getUser();
|
|
||||||
|
|
||||||
if (requesterId == null || channelId == null) {
|
|
||||||
logger.info("无法从FromHeader的Address中获取到平台id,返回400");
|
|
||||||
responseAck(evt, Response.BAD_REQUEST); // 参数不全, 发400,请求错误
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询请求方是否上级平台
|
|
||||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
|
|
||||||
if (platform != null) {
|
|
||||||
// 查询平台下是否有该通道
|
|
||||||
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
|
|
||||||
GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
|
|
||||||
MediaServerItem mediaServerItem = null;
|
|
||||||
// 不是通道可能是直播流
|
|
||||||
if (channel != null && gbStream == null ) {
|
|
||||||
if (channel.getStatus() == 0) {
|
|
||||||
logger.info("通道离线,返回400");
|
|
||||||
responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
|
||||||
}else if(channel == null && gbStream != null){
|
|
||||||
String mediaServerId = gbStream.getMediaServerId();
|
|
||||||
mediaServerItem = mediaServerService.getOne(mediaServerId);
|
|
||||||
if (mediaServerItem == null) {
|
|
||||||
logger.info("[ app={}, stream={} ]找不到zlm {},返回410",gbStream.getApp(), gbStream.getStream(), mediaServerId);
|
|
||||||
responseAck(evt, Response.GONE, "media server not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
|
|
||||||
if (!streamReady ) {
|
|
||||||
logger.info("[ app={}, stream={} ]通道离线,返回400",gbStream.getApp(), gbStream.getStream());
|
|
||||||
responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
|
||||||
}else {
|
|
||||||
logger.info("通道不存在,返回404");
|
|
||||||
responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 解析sdp消息, 使用jainsip 自带的sdp解析方式
|
|
||||||
String contentString = new String(request.getRawContent());
|
|
||||||
|
|
||||||
// jainSip不支持y=字段, 移除移除以解析。
|
|
||||||
int ssrcIndex = contentString.indexOf("y=");
|
|
||||||
//ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
|
|
||||||
String ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
|
|
||||||
String substring = contentString.substring(0, contentString.indexOf("y="));
|
|
||||||
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
|
|
||||||
|
|
||||||
// 获取支持的格式
|
|
||||||
Vector mediaDescriptions = sdp.getMediaDescriptions(true);
|
|
||||||
// 查看是否支持PS 负载96
|
|
||||||
//String ip = null;
|
|
||||||
int port = -1;
|
|
||||||
//boolean recvonly = false;
|
|
||||||
boolean mediaTransmissionTCP = false;
|
|
||||||
Boolean tcpActive = null;
|
|
||||||
for (Object description : mediaDescriptions) {
|
|
||||||
MediaDescription mediaDescription = (MediaDescription) description;
|
|
||||||
Media media = mediaDescription.getMedia();
|
|
||||||
|
|
||||||
Vector mediaFormats = media.getMediaFormats(false);
|
|
||||||
if (mediaFormats.contains("96")) {
|
|
||||||
port = media.getMediaPort();
|
|
||||||
//String mediaType = media.getMediaType();
|
|
||||||
String protocol = media.getProtocol();
|
|
||||||
|
|
||||||
// 区分TCP发流还是udp, 当前默认udp
|
|
||||||
if ("TCP/RTP/AVP".equals(protocol)) {
|
|
||||||
String setup = mediaDescription.getAttribute("setup");
|
|
||||||
if (setup != null) {
|
|
||||||
mediaTransmissionTCP = true;
|
|
||||||
if ("active".equals(setup)) {
|
|
||||||
tcpActive = true;
|
|
||||||
} else if ("passive".equals(setup)) {
|
|
||||||
tcpActive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (port == -1) {
|
|
||||||
logger.info("不支持的媒体格式,返回415");
|
|
||||||
// 回复不支持的格式
|
|
||||||
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String username = sdp.getOrigin().getUsername();
|
|
||||||
String addressStr = sdp.getOrigin().getAddress();
|
|
||||||
//String sessionName = sdp.getSessionName().getValue();
|
|
||||||
logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc);
|
|
||||||
Device device = null;
|
|
||||||
// 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标
|
|
||||||
if (channel != null) {
|
|
||||||
device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
|
|
||||||
if (device == null) {
|
|
||||||
logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel);
|
|
||||||
responseAck(evt, Response.SERVER_INTERNAL_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mediaServerItem = playService.getNewMediaServerItem(device);
|
|
||||||
if (mediaServerItem == null) {
|
|
||||||
logger.warn("未找到可用的zlm");
|
|
||||||
responseAck(evt, Response.BUSY_HERE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
|
|
||||||
device.getDeviceId(), channelId,
|
|
||||||
mediaTransmissionTCP);
|
|
||||||
if (tcpActive != null) {
|
|
||||||
sendRtpItem.setTcpActive(tcpActive);
|
|
||||||
}
|
|
||||||
if (sendRtpItem == null) {
|
|
||||||
logger.warn("服务器端口资源不足");
|
|
||||||
responseAck(evt, Response.BUSY_HERE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入redis, 超时时回复
|
|
||||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
|
||||||
// 通知下级推流,
|
|
||||||
PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{
|
|
||||||
// 收到推流, 回复200OK, 等待ack
|
|
||||||
// if (sendRtpItem == null) return;
|
|
||||||
sendRtpItem.setStatus(1);
|
|
||||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
|
||||||
// TODO 添加对tcp的支持
|
|
||||||
|
|
||||||
StringBuffer content = new StringBuffer(200);
|
|
||||||
content.append("v=0\r\n");
|
|
||||||
content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
|
||||||
content.append("s=Play\r\n");
|
|
||||||
content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
|
||||||
content.append("t=0 0\r\n");
|
|
||||||
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
|
|
||||||
content.append("a=sendonly\r\n");
|
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
|
||||||
content.append("y="+ ssrc + "\r\n");
|
|
||||||
content.append("f=\r\n");
|
|
||||||
|
|
||||||
try {
|
|
||||||
responseAck(evt, content.toString());
|
|
||||||
} catch (SipException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvalidArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} ,((event) -> {
|
|
||||||
// 未知错误。直接转发设备点播的错误
|
|
||||||
Response response = null;
|
|
||||||
try {
|
|
||||||
response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
} catch (ParseException | SipException | InvalidArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(playResult.getResult().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}else if (gbStream != null) {
|
|
||||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
|
|
||||||
gbStream.getApp(), gbStream.getStream(), channelId,
|
|
||||||
mediaTransmissionTCP);
|
|
||||||
|
|
||||||
if (tcpActive != null) {
|
|
||||||
sendRtpItem.setTcpActive(tcpActive);
|
|
||||||
}
|
|
||||||
if (sendRtpItem == null) {
|
|
||||||
logger.warn("服务器端口资源不足");
|
|
||||||
responseAck(evt, Response.BUSY_HERE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入redis, 超时时回复
|
|
||||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
|
||||||
|
|
||||||
sendRtpItem.setStatus(1);
|
|
||||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
|
||||||
// TODO 添加对tcp的支持
|
|
||||||
StringBuffer content = new StringBuffer(200);
|
|
||||||
content.append("v=0\r\n");
|
|
||||||
content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
|
||||||
content.append("s=Play\r\n");
|
|
||||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
|
||||||
content.append("t=0 0\r\n");
|
|
||||||
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
|
|
||||||
content.append("a=sendonly\r\n");
|
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
|
||||||
content.append("y="+ ssrc + "\r\n");
|
|
||||||
content.append("f=\r\n");
|
|
||||||
|
|
||||||
try {
|
|
||||||
responseAck(evt, content.toString());
|
|
||||||
} catch (SipException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvalidArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
|
|
||||||
Device device = storager.queryVideoDevice(requesterId);
|
|
||||||
if (device != null) {
|
|
||||||
logger.info("收到设备" + requesterId + "的语音广播Invite请求");
|
|
||||||
responseAck(evt, Response.TRYING);
|
|
||||||
|
|
||||||
String contentString = new String(request.getRawContent());
|
|
||||||
// jainSip不支持y=字段, 移除移除以解析。
|
|
||||||
String substring = contentString;
|
|
||||||
String ssrc = "0000000404";
|
|
||||||
int ssrcIndex = contentString.indexOf("y=");
|
|
||||||
if (ssrcIndex > 0) {
|
|
||||||
substring = contentString.substring(0, ssrcIndex);
|
|
||||||
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
|
|
||||||
}
|
|
||||||
ssrcIndex = substring.indexOf("f=");
|
|
||||||
if (ssrcIndex > 0) {
|
|
||||||
substring = contentString.substring(0, ssrcIndex);
|
|
||||||
}
|
|
||||||
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
|
|
||||||
|
|
||||||
// 获取支持的格式
|
|
||||||
Vector mediaDescriptions = sdp.getMediaDescriptions(true);
|
|
||||||
// 查看是否支持PS 负载96
|
|
||||||
int port = -1;
|
|
||||||
//boolean recvonly = false;
|
|
||||||
boolean mediaTransmissionTCP = false;
|
|
||||||
Boolean tcpActive = null;
|
|
||||||
for (int i = 0; i < mediaDescriptions.size(); i++) {
|
|
||||||
MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i);
|
|
||||||
Media media = mediaDescription.getMedia();
|
|
||||||
|
|
||||||
Vector mediaFormats = media.getMediaFormats(false);
|
|
||||||
if (mediaFormats.contains("8")) {
|
|
||||||
port = media.getMediaPort();
|
|
||||||
String protocol = media.getProtocol();
|
|
||||||
// 区分TCP发流还是udp, 当前默认udp
|
|
||||||
if ("TCP/RTP/AVP".equals(protocol)) {
|
|
||||||
String setup = mediaDescription.getAttribute("setup");
|
|
||||||
if (setup != null) {
|
|
||||||
mediaTransmissionTCP = true;
|
|
||||||
if ("active".equals(setup)) {
|
|
||||||
tcpActive = true;
|
|
||||||
} else if ("passive".equals(setup)) {
|
|
||||||
tcpActive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (port == -1) {
|
|
||||||
logger.info("不支持的媒体格式,返回415");
|
|
||||||
// 回复不支持的格式
|
|
||||||
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String username = sdp.getOrigin().getUsername();
|
|
||||||
String addressStr = sdp.getOrigin().getAddress();
|
|
||||||
logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
logger.warn("来自无效设备/平台的请求");
|
|
||||||
responseAck(evt, Response.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
logger.warn("sdp解析错误");
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SdpParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SdpException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复状态码
|
|
||||||
* 100 trying
|
|
||||||
* 200 OK
|
|
||||||
* 400
|
|
||||||
* 404
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (statusCode >= 200) {
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
|
|
||||||
response.setReasonPhrase(msg);
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (statusCode >= 200) {
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回复带sdp的200
|
|
||||||
* @param evt
|
|
||||||
* @param sdp
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
SipFactory sipFactory = SipFactory.getInstance();
|
|
||||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
|
||||||
response.setContent(sdp, contentTypeHeader);
|
|
||||||
|
|
||||||
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
|
|
||||||
|
|
||||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(
|
|
||||||
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
|
|
||||||
));
|
|
||||||
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
|
||||||
getServerTransaction(evt).sendResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SIPCommanderFroPlatform getCmderFroPlatform() {
|
|
||||||
return cmderFroPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) {
|
|
||||||
this.cmderFroPlatform = cmderFroPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IVideoManagerStorager getStorager() {
|
|
||||||
return storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SIPCommander getCmder() {
|
|
||||||
return cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmder(SIPCommander cmder) {
|
|
||||||
this.cmder = cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPlayService getPlayService() {
|
|
||||||
return playService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlayService(IPlayService playService) {
|
|
||||||
this.playService = playService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMediaServerService getMediaServerService() {
|
|
||||||
return mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
|
||||||
this.mediaServerService = mediaServerService;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,394 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import com.genersoft.iot.vmp.utils.GpsUtil;
|
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
||||||
|
|
||||||
import org.dom4j.Document;
|
|
||||||
import org.dom4j.DocumentException;
|
|
||||||
import org.dom4j.Element;
|
|
||||||
import org.dom4j.io.SAXReader;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: Notify请求处理器
|
|
||||||
* @author: lawrencehj
|
|
||||||
* @date: 2021年1月27日
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
|
||||||
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
private EventPublisher publisher;
|
|
||||||
|
|
||||||
private DeviceOffLineDetector offLineDetector;
|
|
||||||
|
|
||||||
private static final String NOTIFY_CATALOG = "Catalog";
|
|
||||||
private static final String NOTIFY_ALARM = "Alarm";
|
|
||||||
private static final String NOTIFY_MOBILE_POSITION = "MobilePosition";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
try {
|
|
||||||
Element rootElement = getRootElement(evt);
|
|
||||||
String cmd = XmlUtil.getText(rootElement, "CmdType");
|
|
||||||
|
|
||||||
if (NOTIFY_CATALOG.equals(cmd)) {
|
|
||||||
logger.info("接收到Catalog通知");
|
|
||||||
processNotifyCatalogList(evt);
|
|
||||||
} else if (NOTIFY_ALARM.equals(cmd)) {
|
|
||||||
logger.info("接收到Alarm通知");
|
|
||||||
processNotifyAlarm(evt);
|
|
||||||
} else if (NOTIFY_MOBILE_POSITION.equals(cmd)) {
|
|
||||||
logger.info("接收到MobilePosition通知");
|
|
||||||
processNotifyMobilePosition(evt);
|
|
||||||
} else {
|
|
||||||
logger.info("接收到消息:" + cmd);
|
|
||||||
response200Ok(evt);
|
|
||||||
}
|
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理MobilePosition移动位置Notify
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
private void processNotifyMobilePosition(RequestEvent evt) {
|
|
||||||
try {
|
|
||||||
// 回复 200 OK
|
|
||||||
Element rootElement = getRootElement(evt);
|
|
||||||
MobilePosition mobilePosition = new MobilePosition();
|
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
|
||||||
String deviceId = deviceIdElement.getTextTrim().toString();
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
if (device != null) {
|
|
||||||
if (!StringUtils.isEmpty(device.getName())) {
|
|
||||||
mobilePosition.setDeviceName(device.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID"));
|
|
||||||
mobilePosition.setTime(XmlUtil.getText(rootElement, "Time"));
|
|
||||||
mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
|
||||||
mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
|
|
||||||
mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed")));
|
|
||||||
} else {
|
|
||||||
mobilePosition.setSpeed(0.0);
|
|
||||||
}
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) {
|
|
||||||
mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction")));
|
|
||||||
} else {
|
|
||||||
mobilePosition.setDirection(0.0);
|
|
||||||
}
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) {
|
|
||||||
mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude")));
|
|
||||||
} else {
|
|
||||||
mobilePosition.setAltitude(0.0);
|
|
||||||
}
|
|
||||||
mobilePosition.setReportSource("Mobile Position");
|
|
||||||
BaiduPoint bp = new BaiduPoint();
|
|
||||||
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
|
|
||||||
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
|
|
||||||
mobilePosition.setGeodeticSystem("BD-09");
|
|
||||||
mobilePosition.setCnLng(bp.getBdLng());
|
|
||||||
mobilePosition.setCnLat(bp.getBdLat());
|
|
||||||
if (!userSetup.getSavePositionHistory()) {
|
|
||||||
storager.clearMobilePositionsByDeviceId(deviceId);
|
|
||||||
}
|
|
||||||
storager.insertMobilePosition(mobilePosition);
|
|
||||||
response200Ok(evt);
|
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 处理alarm设备报警Notify
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
private void processNotifyAlarm(RequestEvent evt) {
|
|
||||||
try {
|
|
||||||
Element rootElement = getRootElement(evt);
|
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
|
||||||
String deviceId = deviceIdElement.getText().toString();
|
|
||||||
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
if (device == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rootElement = getRootElement(evt, device.getCharset());
|
|
||||||
DeviceAlarm deviceAlarm = new DeviceAlarm();
|
|
||||||
deviceAlarm.setDeviceId(deviceId);
|
|
||||||
deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
|
|
||||||
deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
|
|
||||||
deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime"));
|
|
||||||
if (XmlUtil.getText(rootElement, "AlarmDescription") == null) {
|
|
||||||
deviceAlarm.setAlarmDescription("");
|
|
||||||
} else {
|
|
||||||
deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription"));
|
|
||||||
}
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) {
|
|
||||||
deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
|
||||||
} else {
|
|
||||||
deviceAlarm.setLongitude(0.00);
|
|
||||||
}
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) {
|
|
||||||
deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
|
||||||
} else {
|
|
||||||
deviceAlarm.setLatitude(0.00);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceAlarm.getAlarmMethod().equals("4")) {
|
|
||||||
MobilePosition mobilePosition = new MobilePosition();
|
|
||||||
mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
|
|
||||||
mobilePosition.setTime(deviceAlarm.getAlarmTime());
|
|
||||||
mobilePosition.setLongitude(deviceAlarm.getLongitude());
|
|
||||||
mobilePosition.setLatitude(deviceAlarm.getLatitude());
|
|
||||||
mobilePosition.setReportSource("GPS Alarm");
|
|
||||||
BaiduPoint bp = new BaiduPoint();
|
|
||||||
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
|
|
||||||
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
|
|
||||||
mobilePosition.setGeodeticSystem("BD-09");
|
|
||||||
mobilePosition.setCnLng(bp.getBdLng());
|
|
||||||
mobilePosition.setCnLat(bp.getBdLat());
|
|
||||||
if (!userSetup.getSavePositionHistory()) {
|
|
||||||
storager.clearMobilePositionsByDeviceId(deviceId);
|
|
||||||
}
|
|
||||||
storager.insertMobilePosition(mobilePosition);
|
|
||||||
}
|
|
||||||
// TODO: 需要实现存储报警信息、报警分类
|
|
||||||
|
|
||||||
// 回复200 OK
|
|
||||||
response200Ok(evt);
|
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
|
||||||
publisher.deviceAlarmEventPublish(deviceAlarm);
|
|
||||||
}
|
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 处理catalog设备目录列表Notify
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
private void processNotifyCatalogList(RequestEvent evt) {
|
|
||||||
try {
|
|
||||||
Element rootElement = getRootElement(evt);
|
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
|
||||||
String deviceId = deviceIdElement.getText();
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
if (device != null ) {
|
|
||||||
rootElement = getRootElement(evt, device.getCharset());
|
|
||||||
}
|
|
||||||
Element deviceListElement = rootElement.element("DeviceList");
|
|
||||||
if (deviceListElement == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
|
||||||
if (deviceListIterator != null) {
|
|
||||||
if (device == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 遍历DeviceList
|
|
||||||
while (deviceListIterator.hasNext()) {
|
|
||||||
Element itemDevice = deviceListIterator.next();
|
|
||||||
Element channelDeviceElement = itemDevice.element("DeviceID");
|
|
||||||
if (channelDeviceElement == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String channelDeviceId = channelDeviceElement.getTextTrim();
|
|
||||||
Element channdelNameElement = itemDevice.element("Name");
|
|
||||||
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
|
|
||||||
Element statusElement = itemDevice.element("Status");
|
|
||||||
String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
|
|
||||||
DeviceChannel deviceChannel = new DeviceChannel();
|
|
||||||
deviceChannel.setName(channelName);
|
|
||||||
deviceChannel.setChannelId(channelDeviceId);
|
|
||||||
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
|
|
||||||
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
|
|
||||||
deviceChannel.setStatus(1);
|
|
||||||
}
|
|
||||||
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
|
|
||||||
deviceChannel.setStatus(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
|
|
||||||
deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
|
|
||||||
deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
|
|
||||||
deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
|
|
||||||
deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
|
|
||||||
deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
|
|
||||||
if (XmlUtil.getText(itemDevice, "Parental") == null
|
|
||||||
|| XmlUtil.getText(itemDevice, "Parental") == "") {
|
|
||||||
deviceChannel.setParental(0);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
|
|
||||||
}
|
|
||||||
deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
|
|
||||||
if (XmlUtil.getText(itemDevice, "SafetyWay") == null
|
|
||||||
|| XmlUtil.getText(itemDevice, "SafetyWay") == "") {
|
|
||||||
deviceChannel.setSafetyWay(0);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
|
|
||||||
}
|
|
||||||
if (XmlUtil.getText(itemDevice, "RegisterWay") == null
|
|
||||||
|| XmlUtil.getText(itemDevice, "RegisterWay") == "") {
|
|
||||||
deviceChannel.setRegisterWay(1);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
|
|
||||||
}
|
|
||||||
deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
|
|
||||||
if (XmlUtil.getText(itemDevice, "Certifiable") == null
|
|
||||||
|| XmlUtil.getText(itemDevice, "Certifiable") == "") {
|
|
||||||
deviceChannel.setCertifiable(0);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
|
|
||||||
}
|
|
||||||
if (XmlUtil.getText(itemDevice, "ErrCode") == null
|
|
||||||
|| XmlUtil.getText(itemDevice, "ErrCode") == "") {
|
|
||||||
deviceChannel.setErrCode(0);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
|
|
||||||
}
|
|
||||||
deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
|
|
||||||
deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
|
|
||||||
deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
|
|
||||||
if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") {
|
|
||||||
deviceChannel.setPort(0);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
|
|
||||||
}
|
|
||||||
deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {
|
|
||||||
deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
|
|
||||||
} else {
|
|
||||||
deviceChannel.setLongitude(0.00);
|
|
||||||
}
|
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
|
|
||||||
deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
|
|
||||||
} else {
|
|
||||||
deviceChannel.setLatitude(0.00);
|
|
||||||
}
|
|
||||||
if (XmlUtil.getText(itemDevice, "PTZType") == null
|
|
||||||
|| XmlUtil.getText(itemDevice, "PTZType") == "") {
|
|
||||||
deviceChannel.setPTZType(0);
|
|
||||||
} else {
|
|
||||||
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
|
|
||||||
}
|
|
||||||
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
|
||||||
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestMessage msg = new RequestMessage();
|
|
||||||
// msg.setDeviceId(deviceId);
|
|
||||||
// msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
|
|
||||||
// msg.setData(device);
|
|
||||||
// deferredResultHolder.invokeResult(msg);
|
|
||||||
// 回复200 OK
|
|
||||||
response200Ok(evt);
|
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复200 OK
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void response200Ok(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
private Element getRootElement(RequestEvent evt) throws DocumentException {
|
|
||||||
return getRootElement(evt, "gb2312");
|
|
||||||
}
|
|
||||||
private Element getRootElement(RequestEvent evt, String charset) throws DocumentException {
|
|
||||||
if (charset == null) charset = "gb2312";
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
SAXReader reader = new SAXReader();
|
|
||||||
reader.setEncoding(charset);
|
|
||||||
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
|
||||||
return xml.getRootElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmder(SIPCommander cmder) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPublisher(EventPublisher publisher) {
|
|
||||||
this.publisher = publisher;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedis(RedisUtil redis) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffLineDetector(DeviceOffLineDetector offLineDetector) {
|
|
||||||
this.offLineDetector = offLineDetector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:暂不支持的消息请求处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:59
|
|
||||||
*/
|
|
||||||
public class OtherRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(OtherRequestProcessor.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Title: process</p>
|
|
||||||
* <p>Description: </p>
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param transaction
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
logger.info("Unsupported the method: " + evt.getRequest().getMethod());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,201 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.header.AuthorizationHeader;
|
|
||||||
import javax.sip.header.ContactHeader;
|
|
||||||
import javax.sip.header.ExpiresHeader;
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
|
|
||||||
import gov.nist.javax.sip.RequestEventExt;
|
|
||||||
import gov.nist.javax.sip.header.SIPDateHeader;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
|
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
|
||||||
import gov.nist.javax.sip.header.Expires;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:收到注册请求 处理
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:47:25
|
|
||||||
*/
|
|
||||||
public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
|
|
||||||
|
|
||||||
private SipConfig sipConfig;
|
|
||||||
|
|
||||||
private RegisterLogicHandler handler;
|
|
||||||
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
private EventPublisher publisher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 收到注册请求 处理
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
try {
|
|
||||||
RequestEventExt evtExt = (RequestEventExt)evt;
|
|
||||||
String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
|
|
||||||
logger.info("[{}] 收到注册请求,开始处理", requestAddress);
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
|
|
||||||
Response response = null;
|
|
||||||
boolean passwordCorrect = false;
|
|
||||||
// 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
|
|
||||||
int registerFlag = 0;
|
|
||||||
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
|
|
||||||
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
|
||||||
SipUri uri = (SipUri) address.getURI();
|
|
||||||
String deviceId = uri.getUser();
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
|
||||||
// 校验密码是否正确
|
|
||||||
if (authorhead != null) {
|
|
||||||
passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request,
|
|
||||||
sipConfig.getPassword());
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(sipConfig.getPassword())){
|
|
||||||
passwordCorrect = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 未携带授权头或者密码错误 回复401
|
|
||||||
if (authorhead == null ) {
|
|
||||||
|
|
||||||
logger.info("[{}] 未携带授权头 回复401", requestAddress);
|
|
||||||
response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
|
|
||||||
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
|
|
||||||
}else {
|
|
||||||
if (!passwordCorrect){
|
|
||||||
// 注册失败
|
|
||||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
|
||||||
response.setReasonPhrase("wrong password");
|
|
||||||
logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress);
|
|
||||||
}else {
|
|
||||||
// 携带授权头并且密码正确
|
|
||||||
response = getMessageFactory().createResponse(Response.OK, request);
|
|
||||||
// 添加date头
|
|
||||||
SIPDateHeader dateHeader = new SIPDateHeader();
|
|
||||||
// 使用自己修改的
|
|
||||||
WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());
|
|
||||||
dateHeader.setDate(wvpSipDate);
|
|
||||||
response.addHeader(dateHeader);
|
|
||||||
|
|
||||||
ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
|
|
||||||
if (expiresHeader == null) {
|
|
||||||
response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 添加Contact头
|
|
||||||
response.addHeader(request.getHeader(ContactHeader.NAME));
|
|
||||||
// 添加Expires头
|
|
||||||
response.addHeader(request.getExpires());
|
|
||||||
|
|
||||||
// 获取到通信地址等信息
|
|
||||||
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
|
||||||
String received = viaHeader.getReceived();
|
|
||||||
int rPort = viaHeader.getRPort();
|
|
||||||
// 解析本地地址替代
|
|
||||||
if (StringUtils.isEmpty(received) || rPort == -1) {
|
|
||||||
received = viaHeader.getHost();
|
|
||||||
rPort = viaHeader.getPort();
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
if (device == null) {
|
|
||||||
device = new Device();
|
|
||||||
device.setStreamMode("UDP");
|
|
||||||
device.setCharset("gb2312");
|
|
||||||
device.setDeviceId(deviceId);
|
|
||||||
device.setFirsRegister(true);
|
|
||||||
}
|
|
||||||
device.setIp(received);
|
|
||||||
device.setPort(rPort);
|
|
||||||
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
|
|
||||||
// 注销成功
|
|
||||||
if (expiresHeader.getExpires() == 0) {
|
|
||||||
registerFlag = 2;
|
|
||||||
}
|
|
||||||
// 注册成功
|
|
||||||
else {
|
|
||||||
device.setExpires(expiresHeader.getExpires());
|
|
||||||
registerFlag = 1;
|
|
||||||
// 判断TCP还是UDP
|
|
||||||
boolean isTcp = false;
|
|
||||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
|
||||||
String transport = reqViaHeader.getTransport();
|
|
||||||
if (transport.equals("TCP")) {
|
|
||||||
isTcp = true;
|
|
||||||
}
|
|
||||||
device.setTransport(isTcp ? "TCP" : "UDP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
// 注册成功
|
|
||||||
// 保存到redis
|
|
||||||
// 下发catelog查询目录
|
|
||||||
if (registerFlag == 1 ) {
|
|
||||||
logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress);
|
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER);
|
|
||||||
// 重新注册更新设备和通道,以免设备替换或更新后信息无法更新
|
|
||||||
handler.onRegister(device);
|
|
||||||
} else if (registerFlag == 2) {
|
|
||||||
logger.info("[{}] 注销成功! deviceId:" + device.getDeviceId(), requestAddress);
|
|
||||||
publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
|
|
||||||
}
|
|
||||||
} catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSipConfig(SipConfig sipConfig) {
|
|
||||||
this.sipConfig = sipConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHandler(RegisterLogicHandler handler) {
|
|
||||||
this.handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVideoManagerStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPublisher(EventPublisher publisher) {
|
|
||||||
this.publisher = publisher;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.header.ExpiresHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:SUBSCRIBE请求处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:31:20
|
|
||||||
*/
|
|
||||||
public class SubscribeRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(SubscribeRequestProcessor.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理SUBSCRIBE请求
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Response response = null;
|
|
||||||
response = getMessageFactory().createResponse(200, request);
|
|
||||||
if (response != null) {
|
|
||||||
ExpiresHeader expireHeader = getHeaderFactory().createExpiresHeader(30);
|
|
||||||
response.setExpires(expireHeader);
|
|
||||||
}
|
|
||||||
logger.info("response : " + response.toString());
|
|
||||||
ServerTransaction transaction = getServerTransaction(evt);
|
|
||||||
if (transaction != null) {
|
|
||||||
transaction.sendResponse(response);
|
|
||||||
transaction.getDialog().delete();
|
|
||||||
transaction.terminate();
|
|
||||||
} else {
|
|
||||||
logger.info("processRequest serverTransactionId is null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SipException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvalidArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理接收IPCamera发来的SIP协议响应消息
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:42:22
|
|
||||||
*/
|
|
||||||
public interface ISIPResponseProcessor {
|
|
||||||
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException;
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: BYE请求响应器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:05
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class ByeResponseProcessor implements ISIPResponseProcessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理BYE响应
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:CANCEL响应处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:23
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class CancelResponseProcessor implements ISIPResponseProcessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理CANCEL响应
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param transaction
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.CSeqHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
|
||||||
import gov.nist.javax.sip.ResponseEventExt;
|
|
||||||
import gov.nist.javax.sip.stack.SIPDialog;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理INVITE响应
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:43:52
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private VideoStreamSessionManager streamSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理invite响应
|
|
||||||
*
|
|
||||||
* @param evt 响应消息
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException {
|
|
||||||
try {
|
|
||||||
Response response = evt.getResponse();
|
|
||||||
int statusCode = response.getStatusCode();
|
|
||||||
// trying不会回复
|
|
||||||
if (statusCode == Response.TRYING) {
|
|
||||||
}
|
|
||||||
// 成功响应
|
|
||||||
// 下发ack
|
|
||||||
if (statusCode == Response.OK) {
|
|
||||||
ResponseEventExt event = (ResponseEventExt)evt;
|
|
||||||
SIPDialog dialog = (SIPDialog)evt.getDialog();
|
|
||||||
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
|
||||||
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
|
||||||
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
|
||||||
requestURI.setHost(event.getRemoteIpAddress());
|
|
||||||
requestURI.setPort(event.getRemotePort());
|
|
||||||
reqAck.setRequestURI(requestURI);
|
|
||||||
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
|
|
||||||
SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI();
|
|
||||||
String deviceId = requestURI.getUser();
|
|
||||||
String channelId = sipURI.getUser();
|
|
||||||
|
|
||||||
dialog.sendAck(reqAck);
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (InvalidArgumentException | SipException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:暂不支持的消息响应处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:59
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class OtherResponseProcessor implements ISIPResponseProcessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Title: process</p>
|
|
||||||
* <p>Description: </p>
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
import javax.sip.header.CallIdHeader;
|
|
||||||
import javax.sip.header.WWWAuthenticateHeader;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:Register响应处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:23
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class RegisterResponseProcessor implements ISIPResponseProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISIPCommanderForPlatform sipCommanderForPlatform;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
public RegisterResponseProcessor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理Register响应
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
|
|
||||||
Response response = evt.getResponse();
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
|
|
||||||
String callId = callIdHeader.getCallId();
|
|
||||||
|
|
||||||
String platformGBId = redisCatchStorage.queryPlatformRegisterInfo(callId);
|
|
||||||
if (platformGBId == null) {
|
|
||||||
logger.info(String.format("未找到callId: %s 的注册/注销平台id", callId ));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId);
|
|
||||||
if (parentPlatformCatch == null) {
|
|
||||||
logger.warn(String.format("收到 %s 的注册/注销%S请求, 但是平台缓存信息未查询到!!!", platformGBId, response.getStatusCode()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "注销" : "注册";
|
|
||||||
logger.info(String.format("收到 %s %s的%S响应", platformGBId, action, response.getStatusCode() ));
|
|
||||||
ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform();
|
|
||||||
if (parentPlatform == null) {
|
|
||||||
logger.warn(String.format("收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformGBId, action, response.getStatusCode()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.getStatusCode() == 401) {
|
|
||||||
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
|
|
||||||
sipCommanderForPlatform.register(parentPlatform, callId, www, null, null);
|
|
||||||
}else if (response.getStatusCode() == 200){
|
|
||||||
// 注册/注销成功
|
|
||||||
logger.info(String.format("%s %s成功", platformGBId, action));
|
|
||||||
redisCatchStorage.delPlatformRegisterInfo(callId);
|
|
||||||
parentPlatform.setStatus("注册".equals(action));
|
|
||||||
// 取回Expires设置,避免注销过程中被置为0
|
|
||||||
ParentPlatform parentPlatformTmp = storager.queryParentPlatByServerGBId(platformGBId);
|
|
||||||
String expires = parentPlatformTmp.getExpires();
|
|
||||||
parentPlatform.setExpires(expires);
|
|
||||||
parentPlatform.setId(parentPlatformTmp.getId());
|
|
||||||
storager.updateParentPlatformStatus(platformGBId, "注册".equals(action));
|
|
||||||
|
|
||||||
redisCatchStorage.updatePlatformRegister(parentPlatform);
|
|
||||||
|
|
||||||
redisCatchStorage.updatePlatformKeepalive(parentPlatform);
|
|
||||||
|
|
||||||
parentPlatformCatch.setParentPlatform(parentPlatform);
|
|
||||||
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -6,7 +6,7 @@ import java.util.Date;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:时间工具类,主要处理ISO 8601格式转换
|
* @description:时间工具类,主要处理ISO 8601格式转换
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午3:24:42
|
* @date: 2020年5月8日 下午3:24:42
|
||||||
*/
|
*/
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.genersoft.iot.vmp.utils;
|
package com.genersoft.iot.vmp.gb28181.utils;
|
||||||
|
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
import gov.nist.javax.sip.address.AddressImpl;
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
import gov.nist.javax.sip.address.SipUri;
|
||||||
@ -9,15 +9,20 @@ import javax.sip.message.Request;
|
|||||||
/**
|
/**
|
||||||
* @author panlinlin
|
* @author panlinlin
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @Description JAIN SIP的工具类
|
* @description JAIN SIP的工具类
|
||||||
* @createTime 2021年09月27日 15:12:00
|
* @createTime 2021年09月27日 15:12:00
|
||||||
*/
|
*/
|
||||||
public class SipUtils {
|
public class SipUtils {
|
||||||
|
|
||||||
public static String getUserIdFromFromHeader(Request request) {
|
public static String getUserIdFromFromHeader(Request request) {
|
||||||
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
|
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
|
||||||
|
return getUserIdFromFromHeader(fromHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUserIdFromFromHeader(FromHeader fromHeader) {
|
||||||
AddressImpl address = (AddressImpl)fromHeader.getAddress();
|
AddressImpl address = (AddressImpl)fromHeader.getAddress();
|
||||||
SipUri uri = (SipUri) address.getURI();
|
SipUri uri = (SipUri) address.getURI();
|
||||||
return uri.getUser();
|
return uri.getUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,15 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.utils;
|
package com.genersoft.iot.vmp.gb28181.utils;
|
||||||
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
import org.dom4j.Attribute;
|
import org.dom4j.Attribute;
|
||||||
import org.dom4j.Document;
|
import org.dom4j.Document;
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
@ -19,6 +11,12 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于dom4j的工具包
|
* 基于dom4j的工具包
|
||||||
*
|
*
|
||||||
@ -161,4 +159,23 @@ public class XmlUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static Element getRootElement(RequestEvent evt) throws DocumentException {
|
||||||
|
|
||||||
|
return getRootElement(evt, "gb2312");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Element getRootElement(RequestEvent evt, String charset) throws DocumentException {
|
||||||
|
Request request = evt.getRequest();
|
||||||
|
return getRootElement(request.getRawContent(), charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Element getRootElement(byte[] content, String charset) throws DocumentException {
|
||||||
|
if (charset == null) {
|
||||||
|
charset = "gb2312";
|
||||||
|
}
|
||||||
|
SAXReader reader = new SAXReader();
|
||||||
|
reader.setEncoding(charset);
|
||||||
|
Document xml = reader.read(new ByteArrayInputStream(content));
|
||||||
|
return xml.getRootElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:针对 ZLMediaServer的hook事件监听
|
* @description:针对 ZLMediaServer的hook事件监听
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 上午10:46:48
|
* @date: 2020年5月8日 上午10:46:48
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:针对 ZLMediaServer的hook事件订阅
|
* @description:针对 ZLMediaServer的hook事件订阅
|
||||||
* @author: pan
|
* @author: pan
|
||||||
* @date: 2020年12月2日 21:17:32
|
* @date: 2020年12月2日 21:17:32
|
||||||
*/
|
*/
|
||||||
|
@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
|||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:视频设备数据存储接口
|
* @description:视频设备数据存储接口
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午2:14:31
|
* @date: 2020年5月6日 下午2:14:31
|
||||||
*/
|
*/
|
||||||
|
@ -25,7 +25,7 @@ import org.springframework.transaction.TransactionStatus;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:视频设备数据存储-jdbc实现
|
* @description:视频设备数据存储-jdbc实现
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午2:31:42
|
* @date: 2020年5月6日 下午2:31:42
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@ import org.springframework.context.ApplicationContextAware;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:spring bean获取工厂,获取spring中的已初始化的bean
|
* @description:spring bean获取工厂,获取spring中的已初始化的bean
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年6月25日 下午4:51:52
|
* @date: 2019年6月25日 下午4:51:52
|
||||||
*
|
*
|
||||||
|
@ -9,7 +9,7 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:使用fastjson实现redis的序列化
|
* @description:使用fastjson实现redis的序列化
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午8:40:11
|
* @date: 2020年5月6日 下午8:40:11
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@ import redis.clients.jedis.JedisPool;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Jedis工具类
|
* @description:Jedis工具类
|
||||||
* @author: wangshaopeng@sunnybs.com
|
* @author: wangshaopeng@sunnybs.com
|
||||||
* @date: 2021年03月22日 下午8:27:29
|
* @date: 2021年03月22日 下午8:27:29
|
||||||
*/
|
*/
|
||||||
|
@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Redis工具类
|
* @description:Redis工具类
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午8:27:29
|
* @date: 2020年5月6日 下午8:27:29
|
||||||
*/
|
*/
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.gb28181.device;
|
package com.genersoft.iot.vmp.vmanager.gb28181.device;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
|
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -15,15 +25,6 @@ import org.springframework.util.StringUtils;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Api(tags = "国标设备查询", value = "国标设备查询")
|
@Api(tags = "国标设备查询", value = "国标设备查询")
|
||||||
@ -50,6 +51,9 @@ public class DeviceQuery {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeviceOffLineDetector offLineDetector;
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用ID查询国标设备
|
* 使用ID查询国标设备
|
||||||
* @param deviceId 国标ID
|
* @param deviceId 国标ID
|
||||||
@ -301,6 +305,18 @@ public class DeviceQuery {
|
|||||||
if (!StringUtils.isEmpty(device.getName())) deviceInStore.setName(device.getName());
|
if (!StringUtils.isEmpty(device.getName())) deviceInStore.setName(device.getName());
|
||||||
if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset());
|
if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset());
|
||||||
if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId());
|
if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId());
|
||||||
|
|
||||||
|
if (deviceInStore.getSubscribeCycleForCatalog() <=0 && device.getSubscribeCycleForCatalog() > 0) {
|
||||||
|
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
|
||||||
|
// 开启订阅
|
||||||
|
deviceService.addCatalogSubscribe(deviceInStore);
|
||||||
|
}
|
||||||
|
if (deviceInStore.getSubscribeCycleForCatalog() > 0 && device.getSubscribeCycleForCatalog() <= 0) {
|
||||||
|
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
|
||||||
|
// 取消订阅
|
||||||
|
deviceService.removeCatalogSubscribe(deviceInStore);
|
||||||
|
}
|
||||||
|
|
||||||
storager.updateDevice(deviceInStore);
|
storager.updateDevice(deviceInStore);
|
||||||
cmder.deviceInfoQuery(deviceInStore);
|
cmder.deviceInfoQuery(deviceInStore);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user