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