648540858
3 years ago
62 changed files with 345 additions and 3589 deletions
@ -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) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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
@ -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); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
Loading…
Reference in new issue