优化sip消息,去除自动dialog创建

This commit is contained in:
648540858 2022-09-21 18:18:37 +08:00
parent da6fb8e71b
commit 4f4bf33670
59 changed files with 892 additions and 865 deletions

View File

@ -64,8 +64,8 @@ public class MediaConfig{
@Value("${media.secret}") @Value("${media.secret}")
private String secret; private String secret;
@Value("${media.stream-none-reader-delay-ms:10000}") @Value("${media.stream-none-reader-delay-ms:15000}")
private int streamNoneReaderDelayMS = 10000; private int streamNoneReaderDelayMS = 15000;
@Value("${media.rtp.enable}") @Value("${media.rtp.enable}")
private boolean rtpEnable; private boolean rtpEnable;

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181; package com.genersoft.iot.vmp.gb28181;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
@ -41,43 +42,7 @@ public class SipLayer{
@Bean("sipStack") @Bean("sipStack")
@DependsOn({"sipFactory"}) @DependsOn({"sipFactory"})
SipStack createSipStack() throws PeerUnavailableException { SipStack createSipStack() throws PeerUnavailableException {
Properties properties = new Properties(); sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp());
/**
* 完整配置参考 gov.nist.javax.sip.SipStackImpl需要下载源码
* gov/nist/javax/sip/SipStackImpl.class
* sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
*/
// * gov/nist/javax/sip/SipStackImpl.class
if (logger.isDebugEnabled()) {
properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
}
// 接收所有notify请求即使没有订阅
properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
// 为_NULL _对话框传递_终止的_事件
properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
// 会话清理策略
properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
// 处理由该服务器处理的基于底层TCP的保持生存超时
properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
// 获取实际内容长度不使用header中的长度信息
properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
/**
* sip_server_log.log sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
*/
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
// properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", "com.genersoft.iot.vmp.gb28181.session.SipMessagePreprocessing");
// if (logger.isDebugEnabled()) {
// properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
// }
sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
return sipStack; return sipStack;
} }

View File

@ -380,4 +380,5 @@ public class Device {
public void setTreeType(String treeType) { public void setTreeType(String treeType) {
this.treeType = treeType; this.treeType = treeType;
} }
} }

View File

@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.gb28181.bean; package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.javax.sip.message.SIPRequest;
public class SendRtpItem { public class SendRtpItem {
/** /**
@ -77,10 +79,20 @@ public class SendRtpItem {
private String serverId; private String serverId;
/** /**
* invite的callId * invite callId
*/ */
private String CallId; private String CallId;
/**
* invite fromTag
*/
private String fromTag;
/**
* invite toTag
*/
private String toTag;
/** /**
* 发送时rtp的ptuint8_t,不传时默认为96 * 发送时rtp的ptuint8_t,不传时默认为96
*/ */
@ -96,15 +108,12 @@ public class SendRtpItem {
*/ */
private boolean onlyAudio = false; private boolean onlyAudio = false;
/** /**
* 播放类型 * 播放类型
*/ */
private InviteStreamType playType; private InviteStreamType playType;
private byte[] transaction;
private byte[] dialog;
public String getIp() { public String getIp() {
return ip; return ip;
} }
@ -225,22 +234,6 @@ public class SendRtpItem {
this.playType = playType; this.playType = playType;
} }
public byte[] getTransaction() {
return transaction;
}
public void setTransaction(byte[] transaction) {
this.transaction = transaction;
}
public byte[] getDialog() {
return dialog;
}
public void setDialog(byte[] dialog) {
this.dialog = dialog;
}
public int getPt() { public int getPt() {
return pt; return pt;
} }
@ -272,4 +265,20 @@ public class SendRtpItem {
public void setServerId(String serverId) { public void setServerId(String serverId) {
this.serverId = serverId; this.serverId = serverId;
} }
public String getFromTag() {
return fromTag;
}
public void setFromTag(String fromTag) {
this.fromTag = fromTag;
}
public String getToTag() {
return toTag;
}
public void setToTag(String toTag) {
this.toTag = toTag;
}
} }

View File

@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -23,15 +24,6 @@ public class SubscribeHolder {
@Autowired @Autowired
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform;
@Autowired
private IVideoManagerStorage storager;
private final String taskOverduePrefix = "subscribe_overdue_"; private final String taskOverduePrefix = "subscribe_overdue_";
private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>(); private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
@ -62,15 +54,13 @@ public class SubscribeHolder {
} }
// 添加任务处理订阅过期 // 添加任务处理订阅过期
dynamicTask.stop(taskOverdueKey); dynamicTask.stop(taskOverdueKey);
} }
public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
mobilePositionMap.put(platformId, subscribeInfo); mobilePositionMap.put(platformId, subscribeInfo);
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId; String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
// 添加任务处理GPS定时推送 // 添加任务处理GPS定时推送
dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId),
storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask),
subscribeInfo.getGpsInterval() * 1000); subscribeInfo.getGpsInterval() * 1000);
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
// 添加任务处理订阅过期 // 添加任务处理订阅过期

View File

@ -1,7 +1,10 @@
package com.genersoft.iot.vmp.gb28181.bean; package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.utils.SerializeUtils; import com.genersoft.iot.vmp.utils.SerializeUtils;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import javax.sip.ClientTransaction;
import javax.sip.Dialog; import javax.sip.Dialog;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction; import javax.sip.ServerTransaction;
@ -11,30 +14,24 @@ import javax.sip.message.Request;
public class SubscribeInfo { public class SubscribeInfo {
public SubscribeInfo(RequestEvent evt, String id) { public SubscribeInfo(ServerTransaction serverTransaction, String id) {
this.id = id; this.id = id;
Request request = evt.getRequest(); SIPRequest request = (SIPRequest)serverTransaction.getRequest();
ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME); this.request = request;
this.expires = expiresHeader.getExpires(); this.expires = request.getExpires().getExpires();
EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME); EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
this.eventId = eventHeader.getEventId(); this.eventId = eventHeader.getEventId();
this.eventType = eventHeader.getEventType(); this.eventType = eventHeader.getEventType();
this.transaction = evt.getServerTransaction();
this.dialog = evt.getDialog();
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
this.callId = callIdHeader.getCallId();
}
public SubscribeInfo() {
} }
private String id; private String id;
private SIPRequest request;
private int expires; private int expires;
private String callId;
private String eventId; private String eventId;
private String eventType; private String eventType;
private ServerTransaction transaction; private SIPResponse response;
private Dialog dialog;
/** /**
* 以下为可选字段 * 以下为可选字段
@ -43,29 +40,28 @@ public class SubscribeInfo {
private String sn; private String sn;
private int gpsInterval; private int gpsInterval;
public String getId() { public String getId() {
return id; return id;
} }
public int getExpires() {
return expires;
}
public String getCallId() {
return callId;
}
public void setId(String id) { public void setId(String id) {
this.id = id; this.id = id;
} }
public void setExpires(int expires) { public SIPRequest getRequest() {
this.expires = expires; return request;
} }
public void setCallId(String callId) { public void setRequest(SIPRequest request) {
this.callId = callId; this.request = request;
}
public int getExpires() {
return expires;
}
public void setExpires(int expires) {
this.expires = expires;
} }
public String getEventId() { public String getEventId() {
@ -84,20 +80,12 @@ public class SubscribeInfo {
this.eventType = eventType; this.eventType = eventType;
} }
public ServerTransaction getTransaction() { public SIPResponse getResponse() {
return transaction; return response;
} }
public void setTransaction(ServerTransaction transaction) { public void setResponse(SIPResponse response) {
this.transaction = transaction; this.response = response;
}
public Dialog getDialog() {
return dialog;
}
public void setDialog(Dialog dialog) {
this.dialog = dialog;
} }
public String getSn() { public String getSn() {

View File

@ -0,0 +1,46 @@
package com.genersoft.iot.vmp.gb28181.conf;
import java.util.Properties;
/**
* 获取sip默认配置
* @author lin
*/
public class DefaultProperties {
public static Properties getProperties(String ip, boolean isDebug) {
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
properties.setProperty("javax.sip.IP_ADDRESS", ip);
properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
/**
* 完整配置参考 gov.nist.javax.sip.SipStackImpl需要下载源码
* gov/nist/javax/sip/SipStackImpl.class
* sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
*/
// * gov/nist/javax/sip/SipStackImpl.class
if (isDebug) {
properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
}
// 接收所有notify请求即使没有订阅
properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
// 为_NULL _对话框传递_终止的_事件
properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
// 会话清理策略
properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
// 处理由该服务器处理的基于底层TCP的保持生存超时
properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
// 获取实际内容长度不使用header中的长度信息
properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
/**
* sip_server_log.log sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
*/
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
return properties;
}
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.event; package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
@ -104,22 +105,27 @@ public class SipSubscribe {
this.type = EventResultType.timeout; this.type = EventResultType.timeout;
this.msg = "消息超时未回复"; this.msg = "消息超时未回复";
this.statusCode = -1024; this.statusCode = -1024;
this.dialog = timeoutEvent.getClientTransaction().getDialog(); if (timeoutEvent.isServerTransaction()) {
this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null; this.callId = ((SIPRequest)timeoutEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
}else {
this.callId = ((SIPRequest)timeoutEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
}
}else if (event instanceof TransactionTerminatedEvent) { }else if (event instanceof TransactionTerminatedEvent) {
TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event; TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event;
this.type = EventResultType.transactionTerminated; this.type = EventResultType.transactionTerminated;
this.msg = "事务已结束"; this.msg = "事务已结束";
this.statusCode = -1024; this.statusCode = -1024;
this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId(); if (transactionTerminatedEvent.isServerTransaction()) {
this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog(); this.callId = ((SIPRequest)transactionTerminatedEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
}else {
this.callId = ((SIPRequest)transactionTerminatedEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
}
}else if (event instanceof DialogTerminatedEvent) { }else if (event instanceof DialogTerminatedEvent) {
DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event; DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event;
this.type = EventResultType.dialogTerminated; this.type = EventResultType.dialogTerminated;
this.msg = "会话已结束"; this.msg = "会话已结束";
this.statusCode = -1024; this.statusCode = -1024;
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
this.dialog = dialogTerminatedEvent.getDialog();
}else if (event instanceof DeviceNotFoundEvent) { }else if (event instanceof DeviceNotFoundEvent) {
DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event; DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
this.type = EventResultType.deviceNotFoundEvent; this.type = EventResultType.deviceNotFoundEvent;

View File

@ -7,6 +7,4 @@ import javax.sip.DialogState;
*/ */
public interface ISubscribeTask extends Runnable{ public interface ISubscribeTask extends Runnable{
void stop(); void stop();
DialogState getDialogState();
} }

View File

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
@ -12,6 +13,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sip.Dialog; import javax.sip.Dialog;
import javax.sip.DialogState; import javax.sip.DialogState;
import javax.sip.ResponseEvent; import javax.sip.ResponseEvent;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -23,7 +26,7 @@ public class CatalogSubscribeTask implements ISubscribeTask {
private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class); private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
private Device device; private Device device;
private final ISIPCommander sipCommander; private final ISIPCommander sipCommander;
private Dialog dialog; private SIPRequest request;
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
@ -41,24 +44,26 @@ public class CatalogSubscribeTask implements ISubscribeTask {
if (dynamicTask.get(taskKey) != null) { if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
sipCommander.catalogSubscribe(device, dialog, eventResult -> { SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
dialog = eventResult.dialog;
}
ResponseEvent event = (ResponseEvent) eventResult.event; ResponseEvent event = (ResponseEvent) eventResult.event;
if (event.getResponse().getRawContent() != null) { // 成功
// 成功 logger.info("[目录订阅]成功: {}", device.getDeviceId());
logger.info("[目录订阅]成功: {}", device.getDeviceId()); ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
}else { try {
// 成功 this.request.getToHeader().setTag(toHeader.getTag());
logger.info("[目录订阅]成功: {}", device.getDeviceId()); } catch (ParseException e) {
logger.info("[目录订阅]成功: 但为request设置ToTag失败");
this.request = null;
} }
},eventResult -> { },eventResult -> {
dialog = null; this.request = null;
// 失败 // 失败
logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000); dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
}); });
if (sipRequest != null) {
this.request = sipRequest;
}
} }
@Override @Override
@ -74,29 +79,19 @@ public class CatalogSubscribeTask implements ISubscribeTask {
if (dynamicTask.get(taskKey) != null) { if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { device.setSubscribeCycleForCatalog(0);
device.setSubscribeCycleForCatalog(0); sipCommander.catalogSubscribe(device, request, eventResult -> {
sipCommander.catalogSubscribe(device, dialog, eventResult -> { ResponseEvent event = (ResponseEvent) eventResult.event;
ResponseEvent event = (ResponseEvent) eventResult.event; if (event.getResponse().getRawContent() != null) {
if (event.getResponse().getRawContent() != null) { // 成功
// 成功 logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); }else {
}else { // 成功
// 成功 logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); }
} },eventResult -> {
},eventResult -> { // 失败
// 失败 logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); });
});
}
}
@Override
public DialogState getDialogState() {
if (dialog == null) {
return null;
}
return dialog.getState();
} }
} }

View File

@ -4,9 +4,11 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
@ -20,71 +22,23 @@ import java.util.List;
*/ */
public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
private Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeHandlerTask.class);
private IRedisCatchStorage redisCatchStorage; private IPlatformService platformService;
private IVideoManagerStorage storager; private String platformId;
private ISIPCommanderForPlatform sipCommanderForPlatform;
private SubscribeHolder subscribeHolder;
private ParentPlatform platform;
private String sn;
private String key;
public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, public MobilePositionSubscribeHandlerTask(String platformId) {
ISIPCommanderForPlatform sipCommanderForPlatform, this.platformService = SpringBeanFactory.getBean("platformServiceImpl");
IVideoManagerStorage storager, this.platformId = platformId;
String platformId,
String sn,
String key,
SubscribeHolder subscribeInfo,
DynamicTask dynamicTask) {
this.redisCatchStorage = redisCatchStorage;
this.storager = storager;
this.platform = storager.queryParentPlatByServerGBId(platformId);
this.sn = sn;
this.key = key;
this.sipCommanderForPlatform = sipCommanderForPlatform;
this.subscribeHolder = subscribeInfo;
} }
@Override @Override
public void run() { public void run() {
platformService.sendNotifyMobilePosition(this.platformId);
if (platform == null) {
return;
}
SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
if (subscribe != null) {
// TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
if (gbStreams.size() == 0) {
return;
}
for (DeviceChannel deviceChannel : gbStreams) {
String gbId = deviceChannel.getChannelId();
GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
// 无最新位置不发送
if (gpsMsgInfo != null) {
// 经纬度都为0不发送
if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
continue;
}
// 发送GPS消息
sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
}
}
}
} }
@Override @Override
public void stop() { public void stop() {
} }
@Override
public DialogState getDialogState() {
return null;
}
} }

View File

@ -4,6 +4,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import org.dom4j.Element; import org.dom4j.Element;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -12,6 +14,8 @@ import org.springframework.scheduling.annotation.Async;
import javax.sip.Dialog; import javax.sip.Dialog;
import javax.sip.DialogState; import javax.sip.DialogState;
import javax.sip.ResponseEvent; import javax.sip.ResponseEvent;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -21,9 +25,10 @@ import java.util.TimerTask;
*/ */
public class MobilePositionSubscribeTask implements ISubscribeTask { public class MobilePositionSubscribeTask implements ISubscribeTask {
private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class); private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
private Device device; private Device device;
private ISIPCommander sipCommander; private ISIPCommander sipCommander;
private Dialog dialog;
private SIPRequest request;
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
private String taskKey = "mobile-position-subscribe-timeout"; private String taskKey = "mobile-position-subscribe-timeout";
@ -38,24 +43,26 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
if (dynamicTask.get(taskKey) != null) { if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) { // 成功
dialog = eventResult.dialog; logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
}
ResponseEvent event = (ResponseEvent) eventResult.event; ResponseEvent event = (ResponseEvent) eventResult.event;
if (event.getResponse().getRawContent() != null) { ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
// 成功 try {
logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); this.request.getToHeader().setTag(toHeader.getTag());
}else { } catch (ParseException e) {
// 成功 logger.info("[移动位置订阅]成功: 为request设置ToTag失败");
logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); this.request = null;
} }
},eventResult -> { },eventResult -> {
dialog = null; this.request = null;
// 失败 // 失败
logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000); dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
}); });
if (sipRequest != null) {
this.request = sipRequest;
}
} }
@ -71,29 +78,19 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
if (dynamicTask.get(taskKey) != null) { if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { device.setSubscribeCycleForMobilePosition(0);
logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
device.setSubscribeCycleForMobilePosition(0); ResponseEvent event = (ResponseEvent) eventResult.event;
sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { if (event.getResponse().getRawContent() != null) {
ResponseEvent event = (ResponseEvent) eventResult.event; // 成功
if (event.getResponse().getRawContent() != null) { logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
// 成功 }else {
logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); // 成功
}else { logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
// 成功 }
logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); },eventResult -> {
} // 失败
},eventResult -> { logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
// 失败 });
logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
});
}
}
@Override
public DialogState getDialogState() {
if (dialog == null) {
return null;
}
return dialog.getState();
} }
} }

View File

@ -72,9 +72,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
@Async("taskExecutor") @Async("taskExecutor")
public void processRequest(RequestEvent requestEvent) { public void processRequest(RequestEvent requestEvent) {
String method = requestEvent.getRequest().getMethod(); String method = requestEvent.getRequest().getMethod();
if ("NOTIFY".equalsIgnoreCase(requestEvent.getRequest().getMethod())) {
System.out.println();
}
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
if (sipRequestProcessor == null) { if (sipRequestProcessor == null) {
logger.warn("不支持方法{}的request", method); logger.warn("不支持方法{}的request", method);
@ -173,6 +170,12 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
@Override @Override
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
// if (transactionTerminatedEvent.isServerTransaction()) {
// ServerTransaction serverTransaction = transactionTerminatedEvent.getServerTransaction();
// serverTransaction.get
// }
// Transaction transaction = null; // Transaction transaction = null;
// System.out.println("processTransactionTerminated"); // System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) { // if (transactionTerminatedEvent.isServerTransaction()) {

View File

@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import gov.nist.javax.sip.message.SIPRequest;
import javax.sip.Dialog; import javax.sip.Dialog;
@ -313,7 +314,7 @@ public interface ISIPCommander {
* @param device 视频设备 * @param device 视频设备
* @return true = 命令发送成功 * @return true = 命令发送成功
*/ */
boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent); SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
/** /**
* 订阅取消订阅报警信息 * 订阅取消订阅报警信息
@ -333,7 +334,7 @@ public interface ISIPCommander {
* @param device 视频设备 * @param device 视频设备
* @return true = 命令发送成功 * @return true = 命令发送成功
*/ */
boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent); SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
/** /**
* 拉框控制命令 * 拉框控制命令

View File

@ -117,4 +117,5 @@ public interface ISIPCommanderForPlatform {
* @param callId callId * @param callId callId
*/ */
void streamByeCmd(ParentPlatform platform, String callId); void streamByeCmd(ParentPlatform platform, String callId);
void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem);
} }

View File

@ -2,10 +2,13 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.GitUtil; import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.MessageFactoryImpl;
import gov.nist.javax.sip.message.SIPRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils; import org.springframework.util.DigestUtils;
@ -154,8 +157,17 @@ public class SIPRequestHeaderPlarformProvider {
return registerRequest; return registerRequest;
} }
public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader);
}
public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException { public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
return createMessageRequest(parentPlatform, content, fromTag, viaTag, null, callIdHeader);
}
public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
Request request = null; Request request = null;
String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort(); String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort();
// sipuri // sipuri
@ -174,7 +186,7 @@ public class SIPRequestHeaderPlarformProvider {
// to // to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress);
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null); ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
// Forwards // Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
@ -192,4 +204,107 @@ public class SIPRequestHeaderPlarformProvider {
request.setContent(content, contentTypeHeader); request.setContent(content, contentTypeHeader);
return request; return request;
} }
public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
SIPRequest request = null;
// sipuri
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
// via
ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
parentPlatform.getTransport(), SipUtils.getNewViaTag());
viaHeader.setRPort();
viaHeaders.add(viaHeader);
// from
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
// to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
// Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
// ceq
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY);
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
// 设置编码 防止中文乱码
messageFactory.setDefaultContentEncodingCharset("gb2312");
CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwards);
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
if (subscribeInfo.getEventId() != null) {
event.setEventId(subscribeInfo.getEventId());
}
request.addHeader(event);
SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");
request.setHeader(active);
String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
.createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
request.setContent(content, contentTypeHeader);
return request;
}
public SIPRequest createByeRequest(ParentPlatform platform, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException {
if (sendRtpItem == null ) {
return null;
}
SIPRequest request = null;
// sipuri
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort());
// via
ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(platform.getDeviceIp(), Integer.parseInt(platform.getDevicePort()),
platform.getTransport(), SipUtils.getNewViaTag());
viaHeader.setRPort();
viaHeaders.add(viaHeader);
// from
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(),
platform.getDeviceIp() + ":" + platform.getDevicePort());
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag());
// to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain());
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag());
// Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
// ceq
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
// 设置编码 防止中文乱码
messageFactory.setDefaultContentEncodingCharset("gb2312");
CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwards);
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
.createSipURI(platform.getDeviceGBId(), sipAddress));
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
return request;
}
} }

View File

@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.GitUtil; import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPDialog;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -199,24 +200,24 @@ public class SIPRequestHeaderProvider {
return request; return request;
} }
public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
Request request = null; Request request = null;
// sipuri // sipuri
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
// via // via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(),
device.getTransport(), viaTag); device.getTransport(), SipUtils.getNewViaTag());
viaHeader.setRPort(); viaHeader.setRPort();
viaHeaders.add(viaHeader); viaHeaders.add(viaHeader);
// from // from
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
// to // to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
// Forwards // Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
@ -238,7 +239,7 @@ public class SIPRequestHeaderProvider {
// Event // Event
EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
int random = (int)Math.random() * 1000000000; int random = (int) Math.floor(Math.random() * 10000);
eventHeader.setEventId(random + ""); eventHeader.setEventId(random + "");
request.addHeader(eventHeader); request.addHeader(eventHeader);

View File

@ -1424,7 +1424,7 @@ public class SIPCommander implements ISIPCommander {
* @return true = 命令发送成功 * @return true = 命令发送成功
*/ */
@Override @Override
public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) { public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
try { try {
StringBuffer subscribePostitionXml = new StringBuffer(200); StringBuffer subscribePostitionXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
@ -1434,38 +1434,27 @@ public class SIPCommander implements ISIPCommander {
subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
if (device.getSubscribeCycleForMobilePosition() > 0) { if (device.getSubscribeCycleForMobilePosition() > 0) {
subscribePostitionXml.append("<Interval>" + String.valueOf(device.getMobilePositionSubmissionInterval()) + "</Interval>\r\n"); subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");
} }
subscribePostitionXml.append("</Query>\r\n"); subscribePostitionXml.append("</Query>\r\n");
Request request; CallIdHeader callIdHeader;
if (dialog != null) {
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
request = dialog.createRequest(Request.SUBSCRIBE);
ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
request.setExpires(expiresHeader);
request.setRequestURI(requestURI); if (requestOld != null) {
callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
request.removeHeader(CSeqHeader.NAME);
request.addHeader(cSeqHeader);
}else { }else {
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
} }
SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
transmitRequest(device, request, errorEvent, okEvent); transmitRequest(device, request, errorEvent, okEvent);
return true; return request;
} catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
e.printStackTrace(); e.printStackTrace();
return false; return null;
} }
} }
@ -1515,7 +1504,7 @@ public class SIPCommander implements ISIPCommander {
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, expires, "presence" , callIdHeader); Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence" , callIdHeader);
transmitRequest(device, request); transmitRequest(device, request);
return true; return true;
@ -1527,7 +1516,7 @@ public class SIPCommander implements ISIPCommander {
} }
@Override @Override
public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
try { try {
StringBuffer cmdXml = new StringBuffer(200); StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset(); String charset = device.getCharset();
@ -1538,40 +1527,24 @@ public class SIPCommander implements ISIPCommander {
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
cmdXml.append("</Query>\r\n"); cmdXml.append("</Query>\r\n");
CallIdHeader callIdHeader ;
Request request; if (requestOld != null) {
if (dialog != null) { callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
request = dialog.createRequest(Request.SUBSCRIBE);
ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog());
request.setExpires(expiresHeader);
request.setRequestURI(requestURI);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
request.setContent(cmdXml.toString(), contentTypeHeader);
CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
request.removeHeader(CSeqHeader.NAME);
request.addHeader(cSeqHeader);
}else { }else {
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
// 有效时间默认为60秒以上
request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(),
SipUtils.getNewFromTag(), null, device.getSubscribeCycleForCatalog(), "Catalog" ,
callIdHeader);
} }
// 有效时间默认为60秒以上
SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog" ,
callIdHeader);
transmitRequest(device, request, errorEvent, okEvent); transmitRequest(device, request, errorEvent, okEvent);
return true; return request;
} catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
e.printStackTrace(); e.printStackTrace();
return false; return null;
} }
} }
@ -1847,61 +1820,4 @@ public class SIPCommander implements ISIPCommander {
} }
return true; return true;
} }
private void sendNotify(Device device, String catalogXmlContent,
SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
throws SipException, ParseException {
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
String characterSet = device.getCharset();
// 设置编码 防止中文乱码
messageFactory.setDefaultContentEncodingCharset(characterSet);
Dialog dialog = subscribeInfo.getDialog();
if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
return;
}
SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
.createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
notifyRequest.addHeader(subscriptionState);
EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
if (subscribeInfo.getEventId() != null) {
event.setEventId(subscribeInfo.getEventId());
}
notifyRequest.addHeader(event);
SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
if (subscribeInfo.getTransaction() != null) {
SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
sipURI.setHost(request.getRemoteAddress().getHostAddress());
sipURI.setPort(request.getRemotePort());
}else {
sipURI.setHost(device.getIp());
sipURI.setPort(device.getPort());
}
ClientTransaction transaction = null;
if ("TCP".equals(device.getTransport())) {
transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
} else if ("UDP".equals(device.getTransport())) {
transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
}
// 添加错误订阅
if (errorEvent != null) {
sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
}
// 添加订阅
if (okEvent != null) {
sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
}
if (transaction == null) {
logger.error("平台{}的Transport错误{}",device.getDeviceId(), device.getTransport());
return;
}
dialog.sendRequest(transaction);
}
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
@ -45,7 +46,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class); private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class);
@Autowired @Autowired
private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider; private SIPRequestHeaderPlarformProvider headerProviderPlatformProvider;
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@ -72,6 +73,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
@Autowired @Autowired
private SipFactory sipFactory; private SipFactory sipFactory;
@Autowired
private SubscribeHolder subscribeHolder;
@Override @Override
public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
return register(parentPlatform, null, null, errorEvent, okEvent, false, true); return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
@ -96,7 +100,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
callIdHeader = udpSipProvider.getNewCallId(); callIdHeader = udpSipProvider.getNewCallId();
} }
request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform,
redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(), redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(),
SipUtils.getNewViaTag(), callIdHeader, isRegister); SipUtils.getNewViaTag(), callIdHeader, isRegister);
// callid 写入缓存 等注册成功可以更新状态 // callid 写入缓存 等注册成功可以更新状态
@ -118,7 +122,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else { }else {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister); request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister);
} }
transmitRequest(parentPlatform, request, null, okEvent); transmitRequest(parentPlatform, request, null, okEvent);
@ -152,7 +156,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest( Request request = headerProviderPlatformProvider.createMessageRequest(
parentPlatform, parentPlatform,
keepaliveXml.toString(), keepaliveXml.toString(),
SipUtils.getNewFromTag(), SipUtils.getNewFromTag(),
@ -218,7 +222,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
@ -312,7 +316,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request, null, eventResult -> { transmitRequest(parentPlatform, request, null, eventResult -> {
int indexNext = index + parentPlatform.getCatalogGroup(); int indexNext = index + parentPlatform.getCatalogGroup();
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext); sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
@ -352,7 +356,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
@ -390,7 +394,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
@ -425,11 +429,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n"); deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
deviceStatusXml.append("</Notify>\r\n"); deviceStatusXml.append("</Notify>\r\n");
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
: udpSipProvider.getNewCallId();
callIdHeader.setCallId(subscribeInfo.getCallId());
sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg); logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
}, null); }, null);
@ -451,8 +451,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
if (parentPlatform == null) { if (parentPlatform == null) {
return false; return false;
} }
logger.info("[发送 报警订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
try { try {
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600); StringBuffer deviceStatusXml = new StringBuffer(600);
@ -475,7 +475,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException e) { } catch (SipException | ParseException e) {
@ -527,18 +527,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return true; return true;
} }
private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException { throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException {
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
// 设置编码 防止中文乱码 // 设置编码 防止中文乱码
messageFactory.setDefaultContentEncodingCharset(characterSet); messageFactory.setDefaultContentEncodingCharset(characterSet);
Dialog dialog = subscribeInfo.getDialog();
if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) { SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
return;
}
SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ()); notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());
@ -558,26 +555,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
sipURI.setHost(parentPlatform.getServerIP()); sipURI.setHost(parentPlatform.getServerIP());
sipURI.setPort(parentPlatform.getServerPort()); sipURI.setPort(parentPlatform.getServerPort());
// ClientTransaction transaction = subscribeInfo.getClientTransaction();
// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {
// if ("TCP".equals(parentPlatform.getTransport())) {
// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
// } else if ("UDP".equals(parentPlatform.getTransport())) {
// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
// }
// }
ClientTransaction transaction = null; ClientTransaction transaction = null;
if ("TCP".equals(parentPlatform.getTransport())) { if ("TCP".equals(parentPlatform.getTransport())) {
transaction = tcpSipProvider.getNewClientTransaction(notifyRequest); transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
} else if ("UDP".equals(parentPlatform.getTransport())) { } else if ("UDP".equals(parentPlatform.getTransport())) {
transaction = udpSipProvider.getNewClientTransaction(notifyRequest); transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
} }
// 添加错误订阅 // 添加错误订阅
if (errorEvent != null) { if (errorEvent != null) {
sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent); sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);
} }
// 添加订阅 // 添加订阅
if (okEvent != null) { if (okEvent != null) {
sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent); sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);
} }
if (transaction == null) { transaction.sendRequest();
logger.error("平台{}的Transport错误{}",parentPlatform.getServerGBId(), parentPlatform.getTransport()); return transaction;
return;
}
dialog.sendRequest(transaction);
} }
private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) { private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
@ -753,7 +756,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
// callid // callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
@ -772,36 +775,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return false; return false;
} }
byte[] dialogByteArray = sendRtpItem.getDialog();
if (dialogByteArray == null) {
return false;
}
try{ try{
SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray);
SipStack sipStack;
if ("TCP".equals(platform.getTransport())) {
sipStack = tcpSipProvider.getSipStack();
} else {
sipStack = udpSipProvider.getSipStack();
}
SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
if (dialog != sipDialog) {
dialog = sipDialog;
}
if ("TCP".equals(platform.getTransport())) {
dialog.setSipProvider(tcpSipProvider);
} else {
dialog.setSipProvider(udpSipProvider);
}
Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
sipStackField.setAccessible(true);
sipStackField.set(dialog, sipStack);
Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
eventListenersField.setAccessible(true);
eventListenersField.set(dialog, new HashSet<>());
SIPRequest messageRequest = (SIPRequest)dialog.createRequest(Request.MESSAGE);
String characterSet = platform.getCharacterSet(); String characterSet = platform.getCharacterSet();
StringBuffer mediaStatusXml = new StringBuffer(200); StringBuffer mediaStatusXml = new StringBuffer(200);
mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -811,6 +786,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n"); mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n"); mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
mediaStatusXml.append("</Notify>\r\n"); mediaStatusXml.append("</Notify>\r\n");
SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
sendRtpItem);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader); messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);
SipURI sipURI = (SipURI) messageRequest.getRequestURI(); SipURI sipURI = (SipURI) messageRequest.getRequestURI();
@ -822,17 +801,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else { }else {
clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest); clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
} }
dialog.sendRequest(clientTransaction); clientTransaction.sendRequest();
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
} catch (NoSuchFieldException e) { } catch (InvalidArgumentException e) {
e.printStackTrace(); throw new RuntimeException(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
return true; return true;
@ -846,61 +823,46 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platform.getServerGBId(), null, null, callId); SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platform.getServerGBId(), null, null, callId);
if (sendRtpItem != null) { if (sendRtpItem != null) {
String mediaServerId = sendRtpItem.getMediaServerId(); streamByeCmd(platform, sendRtpItem);
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); }
if (mediaServerItem != null) { }
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId()); @Override
public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) {
if (sendRtpItem == null ) {
logger.info("[向上级发送BYE] sendRtpItem 为NULL");
return;
}
if (platform == null) {
logger.info("[向上级发送BYE] platform 为NULL");
return;
}
logger.info("[向上级发送BYE] {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId());
String mediaServerId = sendRtpItem.getMediaServerId();
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem != null) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
}
try {
SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
if (byeRequest == null) {
logger.warn("[向上级发送bye]:无法创建 byeRequest");
} }
byte[] dialogByteArray = sendRtpItem.getDialog(); ClientTransaction clientTransaction;
if (dialogByteArray != null) { if ("TCP".equals(platform.getTransport())) {
SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray); clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
SipStack sipStack; } else {
if ("TCP".equals(platform.getTransport())) { clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
sipStack = tcpSipProvider.getSipStack();
} else {
sipStack = udpSipProvider.getSipStack();
}
SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
if (dialog != sipDialog) {
dialog = sipDialog;
}
try {
if ("TCP".equals(platform.getTransport())) {
dialog.setSipProvider(tcpSipProvider);
} else {
dialog.setSipProvider(udpSipProvider);
}
Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
sipStackField.setAccessible(true);
sipStackField.set(dialog, sipStack);
Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
eventListenersField.setAccessible(true);
eventListenersField.set(dialog, new HashSet<>());
Request byeRequest = dialog.createRequest(Request.BYE);
SipURI byeURI = (SipURI) byeRequest.getRequestURI();
byeURI.setHost(platform.getServerIP());
byeURI.setPort(platform.getServerPort());
ClientTransaction clientTransaction;
if ("TCP".equals(platform.getTransport())) {
clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
} else {
clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
}
dialog.sendRequest(clientTransaction);
} catch (SipException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} }
clientTransaction.sendRequest();
} catch (SipException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
} }
} }
} }

View File

@ -1,9 +1,11 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request; package com.genersoft.iot.vmp.gb28181.transmit.event.request;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPServerTransaction; import gov.nist.javax.sip.stack.SIPServerTransaction;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.dom4j.Document; import org.dom4j.Document;
@ -19,10 +21,7 @@ import javax.sip.*;
import javax.sip.address.Address; import javax.sip.address.Address;
import javax.sip.address.AddressFactory; import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI; import javax.sip.address.SipURI;
import javax.sip.header.ContentTypeHeader; import javax.sip.header.*;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory; import javax.sip.message.MessageFactory;
import javax.sip.message.Request; import javax.sip.message.Request;
import javax.sip.message.Response; import javax.sip.message.Response;
@ -59,9 +58,6 @@ public abstract class SIPRequestProcessorParent {
public ServerTransaction getServerTransaction(RequestEvent evt) { public ServerTransaction getServerTransaction(RequestEvent evt) {
Request request = evt.getRequest(); Request request = evt.getRequest();
ServerTransaction serverTransaction = evt.getServerTransaction(); ServerTransaction serverTransaction = evt.getServerTransaction();
if (serverTransaction != null) {
System.out.println(serverTransaction.getState().toString());
}
// 判断TCP还是UDP // 判断TCP还是UDP
boolean isTcp = false; boolean isTcp = false;
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
@ -123,105 +119,107 @@ public abstract class SIPRequestProcessorParent {
return null; return null;
} }
class ResponseAckExtraParam{
String content;
ContentTypeHeader contentTypeHeader;
SipURI sipURI;
int expires = -1;
}
/*** /***
* 回复状态码 * 回复状态码
* 100 trying * 100 trying
* 200 OK * 200 OK
* 400 * 400
* 404 * 404
* @param evt
* @throws SipException
* @throws InvalidArgumentException
* @throws ParseException
*/ */
public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode) throws SipException, InvalidArgumentException, ParseException {
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); return responseAck(serverTransaction, statusCode, null);
ServerTransaction serverTransaction = getServerTransaction(evt);
if (serverTransaction == null) {
logger.warn("回复失败:{}", response);
return;
}
serverTransaction.sendResponse(response);
if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) {
if (serverTransaction.getDialog() != null) {
serverTransaction.getDialog().delete();
}
}
} }
public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException { public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); return responseAck(serverTransaction, statusCode, msg, null);
response.setReasonPhrase(msg); }
ServerTransaction serverTransaction = getServerTransaction(evt);
public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException {
ToHeader toHeader = (ToHeader) serverTransaction.getRequest().getHeader(ToHeader.NAME);
if (toHeader.getTag() == null) {
toHeader.setTag(SipUtils.getNewTag());
}
SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, serverTransaction.getRequest());
if (msg != null) {
response.setReasonPhrase(msg);
}
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && serverTransaction.getRequest().getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(
SipFactory.getInstance().createAddressFactory().createSipURI(responseAckExtraParam.sipURI.getUser(), responseAckExtraParam.sipURI.getHost()+":"+responseAckExtraParam.sipURI.getPort()
));
response.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
}
if (responseAckExtraParam.contentTypeHeader != null) {
response.setContent(responseAckExtraParam.content, responseAckExtraParam.contentTypeHeader);
}
if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
if (responseAckExtraParam.expires == -1) {
logger.error("[参数不全] 2xx的SUBSCRIBE回复必须设置Expires header");
}else {
ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(responseAckExtraParam.expires);
response.addHeader(expiresHeader);
}
}
}else {
if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
logger.error("[参数不全] 2xx的SUBSCRIBE回复必须设置Expires header");
}
}
serverTransaction.sendResponse(response); serverTransaction.sendResponse(response);
if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) { if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(serverTransaction.getRequest().getMethod())) {
if (serverTransaction.getDialog() != null) { if (serverTransaction.getDialog() != null) {
serverTransaction.getDialog().delete(); serverTransaction.getDialog().delete();
} }
} }
return response;
} }
/** /**
* 回复带sdp的200 * 回复带sdp的200
* @param evt
* @param sdp
* @throws SipException
* @throws InvalidArgumentException
* @throws ParseException
*/ */
public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { public SIPResponse responseSdpAck(ServerTransaction serverTransaction, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
SipFactory sipFactory = SipFactory.getInstance(); ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
response.setContent(sdp, contentTypeHeader);
// 兼容国标中的使用编码@域名作为RequestURI的情况 // 兼容国标中的使用编码@域名作为RequestURI的情况
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
if (sipURI.getPort() == -1) { if (sipURI.getPort() == -1) {
sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
} }
logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam();
responseAckExtraParam.contentTypeHeader = contentTypeHeader;
responseAckExtraParam.content = sdp;
responseAckExtraParam.sipURI = sipURI;
Address concatAddress = sipFactory.createAddressFactory().createAddress( return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
));
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
ServerTransaction serverTransaction = getServerTransaction(evt);
if (serverTransaction == null) {
}
getServerTransaction(evt).sendResponse(response);
} }
/** /**
* 回复带xml的200 * 回复带xml的200
* @param evt
* @param xml
* @throws SipException
* @throws InvalidArgumentException
* @throws ParseException
*/ */
public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { public SIPResponse responseXmlAck(ServerTransaction serverTransaction, String xml, ParentPlatform platform, Integer expires) throws SipException, InvalidArgumentException, ParseException {
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
SipFactory sipFactory = SipFactory.getInstance();
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
response.setContent(xml, contentTypeHeader);
// 兼容国标中的使用编码@域名作为RequestURI的情况 SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
if (sipURI.getPort() == -1) { if (sipURI.getPort() == -1) {
sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
} }
logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam();
responseAckExtraParam.contentTypeHeader = contentTypeHeader;
Address concatAddress = sipFactory.createAddressFactory().createAddress( responseAckExtraParam.content = xml;
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() responseAckExtraParam.sipURI = sipURI;
)); responseAckExtraParam.expires = expires;
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
response.addHeader(evt.getRequest().getHeader(ExpiresHeader.NAME));
getServerTransaction(evt).sendResponse(response);
return response;
} }
public Element getRootElement(RequestEvent evt) throws DocumentException { public Element getRootElement(RequestEvent evt) throws DocumentException {

View File

@ -87,53 +87,46 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
*/ */
@Override @Override
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
Dialog dialog = evt.getDialog();
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
if (dialog == null) {
return; String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
logger.info("[收到ACK] platformGbId->{}", platformGbId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
// 取消设置的超时任务
dynamicTask.stop(callIdHeader.getCallId());
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
logger.info("收到ACKrtp/{}开始向上级推流, 目标 {}:{}SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
Map<String, Object> param = new HashMap<>();
param.put("vhost","__defaultVhost__");
param.put("app",sendRtpItem.getApp());
param.put("stream",sendRtpItem.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());
param.put("pt", sendRtpItem.getPt());
param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
// 开启rtcp保活
param.put("udp_rtcp_timeout", "1");
} }
if (dialog.getState()== DialogState.CONFIRMED) {
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
logger.info("ACK请求 platformGbId->{}", platformGbId);
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
// 取消设置的超时任务
dynamicTask.stop(callIdHeader.getCallId());
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
logger.info("收到ACKrtp/{}开始向上级推流, 目标 {}:{}SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
Map<String, Object> param = new HashMap<>();
param.put("vhost","__defaultVhost__");
param.put("app",sendRtpItem.getApp());
param.put("stream",sendRtpItem.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());
param.put("pt", sendRtpItem.getPt());
param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
// 开启rtcp保活
param.put("udp_rtcp_timeout", "1");
}
if (mediaInfo == null) { if (mediaInfo == null) {
RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(),
sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(),
sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio());
redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{ redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{
startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
});
}else {
JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
} });
}else {
JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
} }
} }
private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform, private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform,
@ -141,12 +134,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
if (jsonObject == null) { if (jsonObject == null) {
logger.error("RTP推流失败: 请检查ZLM服务"); logger.error("RTP推流失败: 请检查ZLM服务");
} else if (jsonObject.getInteger("code") == 0) { } else if (jsonObject.getInteger("code") == 0) {
logger.info("调用ZLM推流接口, 结果: {}", jsonObject);
logger.info("RTP推流成功[ {}/{} ]{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); logger.info("RTP推流成功[ {}/{} ]{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
sendRtpItem.setDialog(dialogByteArray);
byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
sendRtpItem.setTransaction(transactionByteArray);
redisCatchStorage.updateSendRTPSever(sendRtpItem);
} else { } else {
logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
if (sendRtpItem.isOnlyAudio()) { if (sendRtpItem.isOnlyAudio()) {

View File

@ -78,73 +78,67 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
@Override @Override
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
Dialog dialog = evt.getDialog();
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
if (dialog == null) { String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
return; String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
} SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
if (dialog.getState().equals(DialogState.TERMINATED)) { logger.info("[收到bye] {}/{}", platformGbId, channelId);
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); if (sendRtpItem != null){
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); String streamId = sendRtpItem.getStreamId();
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); Map<String, Object> param = new HashMap<>();
logger.info("收到bye, [{}/{}]", platformGbId, channelId); param.put("vhost","__defaultVhost__");
if (sendRtpItem != null){ param.put("app",sendRtpItem.getApp());
String streamId = sendRtpItem.getStreamId(); param.put("stream",streamId);
Map<String, Object> param = new HashMap<>(); param.put("ssrc",sendRtpItem.getSsrc());
param.put("vhost","__defaultVhost__"); logger.info("[收到bye] 停止向上级推流:{}", streamId);
param.put("app",sendRtpItem.getApp()); MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
param.put("stream",streamId); redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);
param.put("ssrc",sendRtpItem.getSsrc()); zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
logger.info("收到bye:停止向上级推流:" + streamId); int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); if (totalReaderCount <= 0) {
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null); logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null);
if (totalReaderCount <= 0) { }
logger.info("收到bye: {} 无其它观看者,通知设备停止推流", streamId); if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null); sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
} sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId());
redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
}
} }
} }
// 可能是设备主动停止 }
Device device = storager.queryVideoDeviceByChannelId(platformGbId); // 可能是设备主动停止
if (device != null) { Device device = storager.queryVideoDeviceByChannelId(platformGbId);
storager.stopPlay(device.getDeviceId(), channelId); if (device != null) {
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); storager.stopPlay(device.getDeviceId(), channelId);
if (streamInfo != null) { StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
redisCatchStorage.stopPlay(streamInfo); if (streamInfo != null) {
mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream()); redisCatchStorage.stopPlay(streamInfo);
} mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); }
if (ssrcTransactionForPlay != null){ SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog()); if (ssrcTransactionForPlay != null){
if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){ SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
// 释放ssrc if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
if (mediaServerItem != null) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
}
streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
}
}
SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
if (ssrcTransactionForPlayBack != null) {
// 释放ssrc // 释放ssrc
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId()); MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
if (mediaServerItem != null) { if (mediaServerItem != null) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());
} }
streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
} }
} }
SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);
if (ssrcTransactionForPlayBack != null) {
// 释放ssrc
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());
if (mediaServerItem != null) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc());
}
streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
}
} }
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -8,7 +8,6 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
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.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@ -28,9 +27,10 @@ import com.genersoft.iot.vmp.service.impl.RedisPushStreamResponseListener;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.SerializeUtils;
import gov.nist.javax.sdp.TimeDescriptionImpl; import gov.nist.javax.sdp.TimeDescriptionImpl;
import gov.nist.javax.sdp.fields.TimeField; import gov.nist.javax.sdp.fields.TimeField;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
@ -128,17 +128,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
String channelId = SipUtils.getChannelIdFromRequest(request); String channelId = SipUtils.getChannelIdFromRequest(request);
String requesterId = SipUtils.getUserIdFromFromHeader(request); String requesterId = SipUtils.getUserIdFromFromHeader(request);
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
ServerTransaction serverTransaction = getServerTransaction(evt);
if (requesterId == null || channelId == null) { if (requesterId == null || channelId == null) {
logger.info("无法从FromHeader的Address中获取到平台id返回400"); logger.info("无法从FromHeader的Address中获取到平台id返回400");
// 参数不全 发400请求错误 // 参数不全 发400请求错误
responseAck(evt, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
return; return;
} }
// 查询请求是否来自上级平台\设备 // 查询请求是否来自上级平台\设备
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
if (platform == null) { if (platform == null) {
inviteFromDeviceHandle(evt, requesterId); inviteFromDeviceHandle(serverTransaction, requesterId);
} else { } else {
// 查询平台下是否有该通道 // 查询平台下是否有该通道
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
@ -150,12 +152,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
StreamProxyItem proxyByAppAndStream =null; StreamProxyItem proxyByAppAndStream =null;
// 不是通道可能是直播流 // 不是通道可能是直播流
if (channel != null && gbStream == null) { if (channel != null && gbStream == null) {
if (channel.getStatus() == 0) { // if (channel.getStatus() == 0) {
logger.info("通道离线返回400"); // logger.info("通道离线返回400");
responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); // responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
return; // return;
} // }
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在发181呼叫转接中 // 通道存在发100TRYING
responseAck(serverTransaction, Response.TRYING);
} else if (channel == null && gbStream != null) { } else if (channel == null && gbStream != null) {
String mediaServerId = gbStream.getMediaServerId(); String mediaServerId = gbStream.getMediaServerId();
@ -163,13 +166,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (mediaServerItem == null) { if (mediaServerItem == null) {
if ("proxy".equals(gbStream.getStreamType())) { if ("proxy".equals(gbStream.getStreamType())) {
logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
responseAck(evt, Response.GONE); responseAck(serverTransaction, Response.GONE);
return; return;
} else { } else {
streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) { if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) {
logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
responseAck(evt, Response.GONE); responseAck(serverTransaction, Response.GONE);
return; return;
} }
} }
@ -178,25 +181,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
if (streamPushItem == null) { if (streamPushItem == null) {
logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
responseAck(evt, Response.GONE); responseAck(serverTransaction, Response.GONE);
return; return;
} }
}else if("proxy".equals(gbStream.getStreamType())){ }else if("proxy".equals(gbStream.getStreamType())){
proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream()); proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
if (proxyByAppAndStream == null) { if (proxyByAppAndStream == null) {
logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); logger.info("[ app={}, stream={} ]找不到zlm {}返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
responseAck(evt, Response.GONE); responseAck(serverTransaction, Response.GONE);
return; return;
} }
} }
} }
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在发181呼叫转接中 responseAck(serverTransaction, Response.CALL_IS_BEING_FORWARDED); // 通道存在发181呼叫转接中
} else if (catalog != null) { } else if (catalog != null) {
responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播 responseAck(serverTransaction, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播
return; return;
} else { } else {
logger.info("通道不存在返回404"); logger.info("通道不存在返回404");
responseAck(evt, Response.NOT_FOUND); // 通道不存在发404资源不存在 responseAck(serverTransaction, Response.NOT_FOUND); // 通道不存在发404资源不存在
return; return;
} }
// 解析sdp消息, 使用jainsip 自带的sdp解析方式 // 解析sdp消息, 使用jainsip 自带的sdp解析方式
@ -209,7 +212,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
String ssrc; String ssrc;
SessionDescription sdp; SessionDescription sdp;
if (ssrcIndex >= 0) { if (ssrcIndex >= 0) {
//ssrc规定长度为10字节不取余下长度以避免后续还有f=字段 //ssrc规定长度为10字节不取余下长度以避免后续还有f=字段
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
String substring = contentString.substring(0, contentString.indexOf("y=")); String substring = contentString.substring(0, contentString.indexOf("y="));
sdp = SdpFactory.getInstance().createSessionDescription(substring); sdp = SdpFactory.getInstance().createSessionDescription(substring);
@ -256,9 +259,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
mediaTransmissionTCP = true; mediaTransmissionTCP = true;
if ("active".equalsIgnoreCase(setup)) { if ("active".equalsIgnoreCase(setup)) {
tcpActive = true; tcpActive = true;
// 不支持tcp主动
responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 目录不支持点播
return;
} else if ("passive".equalsIgnoreCase(setup)) { } else if ("passive".equalsIgnoreCase(setup)) {
tcpActive = false; tcpActive = false;
} }
@ -270,7 +270,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (port == -1) { if (port == -1) {
logger.info("不支持的媒体格式返回415"); logger.info("不支持的媒体格式返回415");
// 回复不支持的格式 // 回复不支持的格式
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式发415 responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式发415
return; return;
} }
String username = sdp.getOrigin().getUsername(); String username = sdp.getOrigin().getUsername();
@ -283,24 +283,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
if (device == null) { if (device == null) {
logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel); logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel);
responseAck(evt, Response.SERVER_INTERNAL_ERROR); responseAck(serverTransaction, Response.SERVER_INTERNAL_ERROR);
return; return;
} }
mediaServerItem = playService.getNewMediaServerItem(device); mediaServerItem = playService.getNewMediaServerItem(device);
if (mediaServerItem == null) { if (mediaServerItem == null) {
logger.warn("未找到可用的zlm"); logger.warn("未找到可用的zlm");
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
return; return;
} }
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
device.getDeviceId(), channelId, device.getDeviceId(), channelId,
mediaTransmissionTCP); mediaTransmissionTCP);
if (tcpActive != null) { if (tcpActive != null) {
sendRtpItem.setTcpActive(tcpActive); sendRtpItem.setTcpActive(tcpActive);
} }
if (sendRtpItem == null) { if (sendRtpItem == null) {
logger.warn("服务器端口资源不足"); logger.warn("服务器端口资源不足");
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
return; return;
} }
sendRtpItem.setCallId(callIdHeader.getCallId()); sendRtpItem.setCallId(callIdHeader.getCallId());
@ -342,7 +343,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 回复bye // 回复bye
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId()); cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
}, 60 * 1000); }, 60 * 1000);
responseSdpAck(evt, content.toString(), platform); responseSdpAck(serverTransaction, content.toString(), platform);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
@ -357,8 +358,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
Response response = null; Response response = null;
try { try {
response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
ServerTransaction serverTransaction = getServerTransaction(evt);
serverTransaction.sendResponse(response); serverTransaction.sendResponse(response);
System.out.println("未知错误。直接转发设备点播的错误");
if (serverTransaction.getDialog() != null) { if (serverTransaction.getDialog() != null) {
serverTransaction.getDialog().delete(); serverTransaction.getDialog().delete();
} }
@ -382,7 +383,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} }
redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
try { try {
responseAck(evt, Response.REQUEST_TIMEOUT); responseAck(serverTransaction, Response.REQUEST_TIMEOUT);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -420,6 +421,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
logger.info(JSONObject.toJSONString(ssrcInfo)); logger.info(JSONObject.toJSONString(ssrcInfo));
sendRtpItem.setStreamId(ssrcInfo.getStream()); sendRtpItem.setStreamId(ssrcInfo.getStream());
// 写入redis 超时时回复 // 写入redis 超时时回复
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);
playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> { playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> {
@ -440,26 +442,26 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if("push".equals(gbStream.getStreamType())) { if("push".equals(gbStream.getStreamType())) {
if (streamPushItem != null && streamPushItem.isPushIng()) { if (streamPushItem != null && streamPushItem.isPushIng()) {
// 推流状态 // 推流状态
pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} else { } else {
// 未推流 拉起 // 未推流 拉起
notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} }
}else if ("proxy".equals(gbStream.getStreamType())){ }else if ("proxy".equals(gbStream.getStreamType())){
if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){ if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){
pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
}else{ }else{
//开启代理拉流 //开启代理拉流
boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream()); boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
if(start1) { if(start1) {
pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
}else{ }else{
//失败后通知 //失败后通知
notifyStreamOnline(evt, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, notifyStreamOnline(evt, serverTransaction,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} }
} }
@ -482,7 +484,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
/** /**
* 安排推流 * 安排推流
*/ */
private void pushProxyStream(RequestEvent evt, GbStream gbStream, ParentPlatform platform, private void pushProxyStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, ParentPlatform platform,
CallIdHeader callIdHeader, MediaServerItem mediaServerItem, CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
int port, Boolean tcpActive, boolean mediaTransmissionTCP, int port, Boolean tcpActive, boolean mediaTransmissionTCP,
String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
@ -495,7 +497,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (sendRtpItem == null) { if (sendRtpItem == null) {
logger.warn("服务器端口资源不足"); logger.warn("服务器端口资源不足");
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
return; return;
} }
if (tcpActive != null) { if (tcpActive != null) {
@ -505,17 +507,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 写入redis 超时时回复 // 写入redis 超时时回复
sendRtpItem.setStatus(1); sendRtpItem.setStatus(1);
sendRtpItem.setCallId(callIdHeader.getCallId()); sendRtpItem.setCallId(callIdHeader.getCallId());
byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); SIPRequest request = (SIPRequest) evt.getRequest();
sendRtpItem.setDialog(dialogByteArray); sendRtpItem.setFromTag(request.getFromTag());
byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
sendRtpItem.setTransaction(transactionByteArray); SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
if (response != null) {
sendRtpItem.setToTag(response.getToTag());
}
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);
sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
} }
} }
private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, private void pushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
CallIdHeader callIdHeader, MediaServerItem mediaServerItem, CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
int port, Boolean tcpActive, boolean mediaTransmissionTCP, int port, Boolean tcpActive, boolean mediaTransmissionTCP,
String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
@ -530,7 +534,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (sendRtpItem == null) { if (sendRtpItem == null) {
logger.warn("服务器端口资源不足"); logger.warn("服务器端口资源不足");
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
return; return;
} }
if (tcpActive != null) { if (tcpActive != null) {
@ -540,39 +544,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 写入redis 超时时回复 // 写入redis 超时时回复
sendRtpItem.setStatus(1); sendRtpItem.setStatus(1);
sendRtpItem.setCallId(callIdHeader.getCallId()); sendRtpItem.setCallId(callIdHeader.getCallId());
byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
sendRtpItem.setDialog(dialogByteArray); SIPRequest request = (SIPRequest) evt.getRequest();
byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); sendRtpItem.setFromTag(request.getFromTag());
sendRtpItem.setTransaction(transactionByteArray); SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
if (response != null) {
sendRtpItem.setToTag(response.getToTag());
}
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);
sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
} else { } else {
// 不在线 拉起 // 不在线 拉起
notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} }
} else { } else {
// 其他平台内容 // 其他平台内容
otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} }
} }
/** /**
* 通知流上线 * 通知流上线
*/ */
private void notifyStreamOnline(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, private void notifyStreamOnline(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
CallIdHeader callIdHeader, MediaServerItem mediaServerItem, CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
int port, Boolean tcpActive, boolean mediaTransmissionTCP, int port, Boolean tcpActive, boolean mediaTransmissionTCP,
String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
if ("proxy".equals(gbStream.getStreamType())) { if ("proxy".equals(gbStream.getStreamType())) {
// TODO 控制启用以使设备上线 // TODO 控制启用以使设备上线
logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream()); logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream());
responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
} else if ("push".equals(gbStream.getStreamType())) { } else if ("push".equals(gbStream.getStreamType())) {
if (!platform.isStartOfflinePush()) { if (!platform.isStartOfflinePush()) {
// 平台设置中关闭了拉起离线的推流则直接回复 // 平台设置中关闭了拉起离线的推流则直接回复
responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing"); responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
return; return;
} }
// 发送redis消息以使设备上线 // 发送redis消息以使设备上线
@ -587,7 +595,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream()); logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
try { try {
mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
responseAck(evt, Response.REQUEST_TIMEOUT); // 超时 responseAck(serverTransaction, Response.REQUEST_TIMEOUT); // 超时
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -610,7 +618,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (sendRtpItem == null) { if (sendRtpItem == null) {
logger.warn("上级点时创建sendRTPItem失败可能是服务器端口资源不足"); logger.warn("上级点时创建sendRTPItem失败可能是服务器端口资源不足");
try { try {
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -627,15 +635,17 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 写入redis 超时时回复 // 写入redis 超时时回复
sendRtpItem.setStatus(1); sendRtpItem.setStatus(1);
sendRtpItem.setCallId(callIdHeader.getCallId()); sendRtpItem.setCallId(callIdHeader.getCallId());
byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
sendRtpItem.setDialog(dialogByteArray); SIPRequest request = (SIPRequest) evt.getRequest();
byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); sendRtpItem.setFromTag(request.getFromTag());
sendRtpItem.setTransaction(transactionByteArray); SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
if (response != null) {
sendRtpItem.setToTag(response.getToTag());
}
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);
sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
} else { } else {
// 其他平台内容 // 其他平台内容
otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} }
}); });
@ -646,7 +656,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
dynamicTask.stop(callIdHeader.getCallId()); dynamicTask.stop(callIdHeader.getCallId());
mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
try { try {
responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, response.getMsg()); responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
} catch (SipException e) { } catch (SipException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -662,7 +672,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
/** /**
* 来自其他wvp的推流 * 来自其他wvp的推流
*/ */
private void otherWvpPushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, private void otherWvpPushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
CallIdHeader callIdHeader, MediaServerItem mediaServerItem, CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
int port, Boolean tcpActive, boolean mediaTransmissionTCP, int port, Boolean tcpActive, boolean mediaTransmissionTCP,
String channelId, String addressStr, String ssrc, String requesterId) { String channelId, String addressStr, String ssrc, String requesterId) {
@ -675,7 +685,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) { if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
logger.warn("服务器端口资源不足"); logger.warn("服务器端口资源不足");
try { try {
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -693,12 +703,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 写入redis 超时时回复 // 写入redis 超时时回复
sendRtpItem.setStatus(1); sendRtpItem.setStatus(1);
sendRtpItem.setCallId(callIdHeader.getCallId()); sendRtpItem.setCallId(callIdHeader.getCallId());
byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
sendRtpItem.setDialog(dialogByteArray); SIPRequest request = (SIPRequest) evt.getRequest();
byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); sendRtpItem.setFromTag(request.getFromTag());
sendRtpItem.setTransaction(transactionByteArray); SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), serverTransaction,sendRtpItem, platform, evt);
if (response != null) {
sendRtpItem.setToTag(response.getToTag());
}
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);
sendStreamAck(responseSendItemMsg.getMediaServerItem(), sendRtpItem, platform, evt);
}, (wvpResult) -> { }, (wvpResult) -> {
try { try {
// 错误 // 错误
@ -708,12 +720,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream()); StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
if (currentStreamPushItem.isPushIng()) { if (currentStreamPushItem.isPushIng()) {
// 在线状态 // 在线状态
pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} else { } else {
// 不在线 拉起 // 不在线 拉起
notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, notifyStreamOnline(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
} }
} }
@ -727,7 +739,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
try { try {
responseAck(evt, Response.BUSY_HERE); responseAck(serverTransaction, Response.BUSY_HERE);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -739,7 +751,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}); });
} }
public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, ServerTransaction serverTransaction, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
StringBuffer content = new StringBuffer(200); StringBuffer content = new StringBuffer(200);
content.append("v=0\r\n"); content.append("v=0\r\n");
@ -762,7 +774,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
content.append("f=\r\n"); content.append("f=\r\n");
try { try {
responseSdpAck(evt, content.toString(), platform); return responseSdpAck(serverTransaction, content.toString(), platform);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -770,18 +782,18 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null;
} }
public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { public void inviteFromDeviceHandle(ServerTransaction serverTransaction, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException {
// 非上级平台请求查询是否设备请求通常为接收语音广播的设备 // 非上级平台请求查询是否设备请求通常为接收语音广播的设备
Device device = redisCatchStorage.getDevice(requesterId); Device device = redisCatchStorage.getDevice(requesterId);
Request request = evt.getRequest();
if (device != null) { if (device != null) {
logger.info("收到设备" + requesterId + "的语音广播Invite请求"); logger.info("收到设备" + requesterId + "的语音广播Invite请求");
responseAck(evt, Response.TRYING); responseAck(serverTransaction, Response.TRYING);
String contentString = new String(request.getRawContent()); String contentString = new String(serverTransaction.getRequest().getRawContent());
// jainSip不支持y=字段 移除移除以解析 // jainSip不支持y=字段 移除移除以解析
String substring = contentString; String substring = contentString;
String ssrc = "0000000404"; String ssrc = "0000000404";
@ -829,7 +841,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (port == -1) { if (port == -1) {
logger.info("不支持的媒体格式返回415"); logger.info("不支持的媒体格式返回415");
// 回复不支持的格式 // 回复不支持的格式
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式发415 responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式发415
return; return;
} }
String username = sdp.getOrigin().getUsername(); String username = sdp.getOrigin().getUsername();
@ -838,7 +850,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} else { } else {
logger.warn("来自无效设备/平台的请求"); logger.warn("来自无效设备/平台的请求");
responseAck(evt, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
} }
} }
} }

View File

@ -34,6 +34,7 @@ import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.header.FromHeader; import javax.sip.header.FromHeader;
import javax.sip.message.Response; import javax.sip.message.Response;
@ -94,7 +95,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
try { try {
taskQueue.offer(new HandlerCatchData(evt, null, null)); taskQueue.offer(new HandlerCatchData(evt, null, null));
responseAck(evt, Response.OK); ServerTransaction serverTransaction = getServerTransaction(evt);
responseAck(serverTransaction, Response.OK);
if (!taskQueueHandlerRun) { if (!taskQueueHandlerRun) {
taskQueueHandlerRun = true; taskQueueHandlerRun = true;
taskExecutor.execute(()-> { taskExecutor.execute(()-> {

View File

@ -17,6 +17,12 @@ import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPClientTransaction;
import gov.nist.javax.sip.stack.SIPDialog;
import gov.nist.javax.sip.stack.SIPServerTransaction;
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
import org.dom4j.Element; import org.dom4j.Element;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -49,22 +55,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
@Autowired @Autowired
private IVideoManagerStorage storager; private IVideoManagerStorage storager;
@Lazy
@Autowired
@Qualifier(value="tcpSipProvider")
private SipProviderImpl tcpSipProvider;
@Lazy
@Autowired
@Qualifier(value="udpSipProvider")
private SipProviderImpl udpSipProvider;
@Autowired
private DynamicTask dynamicTask;
@Autowired
private UserSetting userSetting;
@Autowired @Autowired
private SubscribeHolder subscribeHolder; private SubscribeHolder subscribeHolder;
@ -81,6 +71,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
*/ */
@Override @Override
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
ServerTransaction serverTransaction = getServerTransaction(evt);
Request request = evt.getRequest(); Request request = evt.getRequest();
try { try {
Element rootElement = getRootElement(evt); Element rootElement = getRootElement(evt);
@ -90,12 +81,12 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
} }
String cmd = XmlUtil.getText(rootElement, "CmdType"); String cmd = XmlUtil.getText(rootElement, "CmdType");
if (CmdType.MOBILE_POSITION.equals(cmd)) { if (CmdType.MOBILE_POSITION.equals(cmd)) {
processNotifyMobilePosition(evt, rootElement); processNotifyMobilePosition(serverTransaction, rootElement);
// } else if (CmdType.ALARM.equals(cmd)) { // } else if (CmdType.ALARM.equals(cmd)) {
// logger.info("接收到Alarm订阅"); // logger.info("接收到Alarm订阅");
// processNotifyAlarm(evt, rootElement); // processNotifyAlarm(serverTransaction, rootElement);
} else if (CmdType.CATALOG.equals(cmd)) { } else if (CmdType.CATALOG.equals(cmd)) {
processNotifyCatalogList(evt, rootElement); processNotifyCatalogList(serverTransaction, rootElement);
} else { } else {
logger.info("接收到消息:" + cmd); logger.info("接收到消息:" + cmd);
@ -108,7 +99,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
ServerTransaction transaction = getServerTransaction(evt); ServerTransaction transaction = getServerTransaction(evt);
if (transaction != null) { if (transaction != null) {
transaction.sendResponse(response); transaction.sendResponse(response);
transaction.getDialog().delete();
transaction.terminate(); transaction.terminate();
} else { } else {
logger.info("processRequest serverTransactionId is null."); logger.info("processRequest serverTransactionId is null.");
@ -123,24 +113,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
/** /**
* 处理移动位置订阅消息 * 处理移动位置订阅消息
*/ */
private void processNotifyMobilePosition(RequestEvent evt, Element rootElement) throws SipException { private void processNotifyMobilePosition(ServerTransaction serverTransaction, Element rootElement) throws SipException {
String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); if (serverTransaction == null) {
return;
}
String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
String deviceId = XmlUtil.getText(rootElement, "DeviceID"); String deviceId = XmlUtil.getText(rootElement, "DeviceID");
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
if (platform == null) { if (platform == null) {
return; return;
} }
if (evt.getServerTransaction() == null) {
ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
: udpSipProvider.getNewServerTransaction(evt.getRequest());
subscribeInfo.setTransaction(serverTransaction);
Dialog dialog = serverTransaction.getDialog();
dialog.terminateOnBye(false);
subscribeInfo.setDialog(dialog);
}
String sn = XmlUtil.getText(rootElement, "SN"); String sn = XmlUtil.getText(rootElement, "SN");
logger.info("[回复 移动位置订阅]: {}", platformId); logger.info("[回复上级的移动位置订阅请求]: {}", platformId);
StringBuilder resultXml = new StringBuilder(200); StringBuilder resultXml = new StringBuilder(200);
resultXml.append("<?xml version=\"1.0\" ?>\r\n") resultXml.append("<?xml version=\"1.0\" ?>\r\n")
.append("<Response>\r\n") .append("<Response>\r\n")
@ -158,17 +144,19 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
}else { }else {
subscribeInfo.setGpsInterval(Integer.parseInt(interval)); subscribeInfo.setGpsInterval(Integer.parseInt(interval));
} }
subscribeInfo.setSn(sn); subscribeInfo.setSn(sn);
subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
}else if (subscribeInfo.getExpires() == 0) {
subscribeHolder.removeMobilePositionSubscribe(platformId);
} }
try { try {
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
responseXmlAck(evt, resultXml.toString(), parentPlatform); SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
if (subscribeInfo.getExpires() == 0) {
subscribeHolder.removeMobilePositionSubscribe(platformId);
}else {
subscribeInfo.setResponse(response);
subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo);
}
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -178,25 +166,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
} }
private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException { private void processNotifyCatalogList(ServerTransaction serverTransaction, Element rootElement) throws SipException {
if (serverTransaction == null) {
String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); return;
}
String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
String deviceId = XmlUtil.getText(rootElement, "DeviceID"); String deviceId = XmlUtil.getText(rootElement, "DeviceID");
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
if (platform == null){ if (platform == null){
return; return;
} }
SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
if (evt.getServerTransaction() == null) {
ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
: udpSipProvider.getNewServerTransaction(evt.getRequest());
subscribeInfo.setTransaction(serverTransaction);
Dialog dialog = serverTransaction.getDialog();
dialog.terminateOnBye(false);
subscribeInfo.setDialog(dialog);
}
String sn = XmlUtil.getText(rootElement, "SN"); String sn = XmlUtil.getText(rootElement, "SN");
logger.info("[回复 目录订阅]: {}/{}", platformId, deviceId); logger.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId);
StringBuilder resultXml = new StringBuilder(200); StringBuilder resultXml = new StringBuilder(200);
resultXml.append("<?xml version=\"1.0\" ?>\r\n") resultXml.append("<?xml version=\"1.0\" ?>\r\n")
.append("<Response>\r\n") .append("<Response>\r\n")
@ -213,7 +196,13 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
} }
try { try {
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
responseXmlAck(evt, resultXml.toString(), parentPlatform); SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
if (subscribeInfo.getExpires() == 0) {
subscribeHolder.removeCatalogSubscribe(platformId);
}else {
subscribeInfo.setResponse(response);
subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
}
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.header.*; import javax.sip.header.*;
import javax.sip.message.Response; import javax.sip.message.Response;
@ -65,9 +66,12 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
// 先从会话内查找 // 先从会话内查找
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
// 兼容海康 媒体通知 消息from字段不是设备ID的问题
if (ssrcTransaction != null) {
deviceId = ssrcTransaction.getDeviceId(); deviceId = ssrcTransaction.getDeviceId();
} }
ServerTransaction serverTransaction = getServerTransaction(evt);
// 查询设备是否存在 // 查询设备是否存在
Device device = redisCatchStorage.getDevice(deviceId); Device device = redisCatchStorage.getDevice(deviceId);
// 查询上级平台是否存在 // 查询上级平台是否存在
@ -86,7 +90,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
} }
if (device == null && parentPlatform == null) { if (device == null && parentPlatform == null) {
// 不存在则回复404 // 不存在则回复404
responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found"); responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
logger.warn("[设备未找到 ] {}", deviceId); logger.warn("[设备未找到 ] {}", deviceId);
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog())); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
@ -101,14 +105,14 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
String streamId = sendRtpItem.getStreamId(); String streamId = sendRtpItem.getStreamId();
StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
if (null == streamInfo) { if (null == streamInfo) {
responseAck(evt, Response.NOT_FOUND, "stream " + streamId + " not found"); responseAck(serverTransaction, Response.NOT_FOUND, "stream " + streamId + " not found");
return; return;
} }
Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID()); Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID());
cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> { cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> {
// 失败的回复 // 失败的回复
try { try {
responseAck(evt, eventResult.statusCode, eventResult.msg); responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -119,7 +123,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
}, eventResult -> { }, eventResult -> {
// 成功的回复 // 成功的回复
try { try {
responseAck(evt, eventResult.statusCode); responseAck(serverTransaction, eventResult.statusCode);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -23,6 +23,7 @@ import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.address.SipURI; import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader; import javax.sip.header.CSeqHeader;
@ -79,6 +80,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
if (ssrcTransaction != null) { if (ssrcTransaction != null) {
deviceId = ssrcTransaction.getDeviceId(); deviceId = ssrcTransaction.getDeviceId();
} }
ServerTransaction serverTransaction = getServerTransaction(evt);
// 查询设备是否存在 // 查询设备是否存在
Device device = redisCatchStorage.getDevice(deviceId); Device device = redisCatchStorage.getDevice(deviceId);
// 查询上级平台是否存在 // 查询上级平台是否存在
@ -98,7 +102,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
} }
if (device == null && parentPlatform == null) { if (device == null && parentPlatform == null) {
// 不存在则回复404 // 不存在则回复404
responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found"); responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
logger.warn("[设备未找到 ] {}", deviceId); logger.warn("[设备未找到 ] {}", deviceId);
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog())); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
@ -110,13 +114,13 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
rootElement = getRootElement(evt); rootElement = getRootElement(evt);
if (rootElement == null) { if (rootElement == null) {
logger.error("处理MESSAGE请求 未获取到消息体{}", evt.getRequest()); logger.error("处理MESSAGE请求 未获取到消息体{}", evt.getRequest());
responseAck(evt, Response.BAD_REQUEST, "content is null"); responseAck(serverTransaction, Response.BAD_REQUEST, "content is null");
return; return;
} }
} catch (DocumentException e) { } catch (DocumentException e) {
logger.warn("解析XML消息内容异常", e); logger.warn("解析XML消息内容异常", e);
// 不存在则回复404 // 不存在则回复404
responseAck(evt, Response.BAD_REQUEST, e.getMessage()); responseAck(serverTransaction, Response.BAD_REQUEST, e.getMessage());
} }
String name = rootElement.getName(); String name = rootElement.getName();
IMessageHandler messageHandler = messageHandlerMap.get(name); IMessageHandler messageHandler = messageHandlerMap.get(name);
@ -129,7 +133,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
}else { }else {
// 不支持的message // 不支持的message
// 不存在则回复415 // 不存在则回复415
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response"); responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
} }
} }
} catch (SipException e) { } catch (SipException e) {

View File

@ -61,6 +61,8 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
@Override @Override
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
ServerTransaction serverTransaction = getServerTransaction(evt);
// 此处是上级发出的DeviceControl指令 // 此处是上级发出的DeviceControl指令
String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
String channelId = getText(rootElement, "DeviceID"); String channelId = getText(rootElement, "DeviceID");
@ -107,7 +109,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
if (deviceForPlatform == null) { if (deviceForPlatform == null) {
try { try {
responseAck(evt, Response.NOT_FOUND); responseAck(serverTransaction, Response.NOT_FOUND);
return; return;
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
@ -120,7 +122,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> { cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
// 失败的回复 // 失败的回复
try { try {
responseAck(evt, eventResult.statusCode, eventResult.msg); responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -131,7 +133,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
}, eventResult -> { }, eventResult -> {
// 成功的回复 // 成功的回复
try { try {
responseAck(evt, eventResult.statusCode); responseAck(serverTransaction, eventResult.statusCode);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -77,7 +77,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
logger.info("[收到报警通知]设备:{}", device.getDeviceId()); logger.info("[收到报警通知]设备:{}", device.getDeviceId());
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[收到报警通知], 回复200OK失败", e); logger.error("[收到报警通知], 回复200OK失败", e);
} }
@ -179,7 +179,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
if (sipConfig.isAlarm()) { if (sipConfig.isAlarm()) {
deviceAlarmService.add(deviceAlarm); deviceAlarmService.add(deviceAlarm);
} }
logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm));
if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) { if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) {
publisher.deviceAlarmEventPublish(deviceAlarm); publisher.deviceAlarmEventPublish(deviceAlarm);
} }
@ -190,7 +190,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId()); logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId());
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -69,7 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
} }
device.setKeepaliveTime(DateUtil.getNow()); device.setKeepaliveTime(DateUtil.getNow());
// 回复200 OK // 回复200 OK
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
if (device.getOnline() == 1) { if (device.getOnline() == 1) {
deviceService.updateDevice(device); deviceService.updateDevice(device);
}else { }else {

View File

@ -66,7 +66,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -65,7 +65,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
rootElement = getRootElement(evt, device.getCharset()); rootElement = getRootElement(evt, device.getCharset());
if (rootElement == null) { if (rootElement == null) {
logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest()); logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest());
responseAck(evt, Response.BAD_REQUEST); responseAck(getServerTransaction(evt), Response.BAD_REQUEST);
return; return;
} }
MobilePosition mobilePosition = new MobilePosition(); MobilePosition mobilePosition = new MobilePosition();
@ -116,7 +116,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
} }
storager.updateChannelPosition(deviceChannel); storager.updateChannelPosition(deviceChannel);
//回复 200 OK //回复 200 OK
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
// 发送redis消息 通知位置信息的变化 // 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();

View File

@ -58,7 +58,7 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen
logger.info("不支持alarm查询"); logger.info("不支持alarm查询");
try { try {
responseAck(evt, Response.NOT_FOUND, "not support alarm query"); responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query");
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -66,7 +66,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
try { try {
// 回复200 OK // 回复200 OK
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
Element snElement = rootElement.element("SN"); Element snElement = rootElement.element("SN");
String sn = snElement.getText(); String sn = snElement.getText();
// 准备回复通道信息 // 准备回复通道信息

View File

@ -48,7 +48,7 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
try { try {
// 回复200 OK // 回复200 OK
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -61,7 +61,7 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.header.FromHeader; import javax.sip.header.FromHeader;
import javax.sip.message.Response; import javax.sip.message.Response;
@ -68,7 +69,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
ServerTransaction serverTransaction = getServerTransaction(evt);
Element snElement = rootElement.element("SN"); Element snElement = rootElement.element("SN");
int sn = Integer.parseInt(snElement.getText()); int sn = Integer.parseInt(snElement.getText());
Element deviceIDElement = rootElement.element("DeviceID"); Element deviceIDElement = rootElement.element("DeviceID");
@ -108,7 +109,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> { DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(serverTransaction, Response.OK);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -119,7 +120,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
}),(eventResult -> { }),(eventResult -> {
// 查询失败 // 查询失败
try { try {
responseAck(evt, eventResult.statusCode, eventResult.msg); responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -132,7 +133,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
}else if (channelSources.get(1).getCount() > 0) { // 直播流 }else if (channelSources.get(1).getCount() > 0) { // 直播流
// TODO // TODO
try { try {
responseAck(evt, Response.NOT_IMPLEMENTED); // 回复未实现 responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -142,7 +143,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
} }
}else { // 错误的请求 }else { // 错误的请求
try { try {
responseAck(evt, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -18,6 +18,7 @@ import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -46,8 +47,9 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
try { try {
String channelId = getText(rootElement, "DeviceID"); String channelId = getText(rootElement, "DeviceID");
String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId; String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId;
ServerTransaction serverTransaction = getServerTransaction(evt);
// 回复200 OK // 回复200 OK
responseAck(evt, Response.OK); responseAck(serverTransaction, Response.OK);
// 此处是对本平台发出Broadcast指令的应答 // 此处是对本平台发出Broadcast指令的应答
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
XmlUtil.node2Json(rootElement, json); XmlUtil.node2Json(rootElement, json);

View File

@ -27,6 +27,7 @@ import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -87,7 +88,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
taskQueue.offer(new HandlerCatchData(evt, device, element)); taskQueue.offer(new HandlerCatchData(evt, device, element));
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); ServerTransaction serverTransaction = getServerTransaction(evt);
responseAck(serverTransaction, Response.OK);
if (!taskQueueHandlerRun) { if (!taskQueueHandlerRun) {
taskQueueHandlerRun = true; taskQueueHandlerRun = true;
taskExecutor.execute(()-> { taskExecutor.execute(()-> {
@ -103,7 +105,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
Element sumNumElement = rootElement.element("SumNum"); Element sumNumElement = rootElement.element("SumNum");
Element snElement = rootElement.element("SN"); Element snElement = rootElement.element("SN");
if (snElement == null || sumNumElement == null || deviceListElement == null) { if (snElement == null || sumNumElement == null || deviceListElement == null) {
responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error"); responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
continue; continue;
} }
int sumNum = Integer.parseInt(sumNumElement.getText()); int sumNum = Integer.parseInt(sumNumElement.getText());

View File

@ -52,7 +52,7 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId; String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
try { try {
// 回复200 OK // 回复200 OK
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
// 此处是对本平台发出DeviceControl指令的应答 // 此处是对本平台发出DeviceControl指令的应答
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
XmlUtil.node2Json(element, json); XmlUtil.node2Json(element, json);

View File

@ -46,7 +46,7 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare
public void handForDevice(RequestEvent evt, Device device, Element element) { public void handForDevice(RequestEvent evt, Device device, Element element) {
// 此处是对本平台发出DeviceControl指令的应答 // 此处是对本平台发出DeviceControl指令的应答
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
String channelId = getText(element, "DeviceID"); String channelId = getText(element, "DeviceID");
XmlUtil.node2Json(element, json); XmlUtil.node2Json(element, json);

View File

@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -74,11 +75,12 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]" + (device != null ? device.getDeviceId():"" )); logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]" + (device != null ? device.getDeviceId():"" ));
return; return;
} }
ServerTransaction serverTransaction = getServerTransaction(evt);
try { try {
rootElement = getRootElement(evt, device.getCharset()); rootElement = getRootElement(evt, device.getCharset());
if (rootElement == null) { if (rootElement == null) {
logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest()); logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest());
responseAck(evt, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
return; return;
} }
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
@ -99,7 +101,7 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
msg.setData(device); msg.setData(device);
deferredResultHolder.invokeAllResult(msg); deferredResultHolder.invokeAllResult(msg);
// 回复200 OK // 回复200 OK
responseAck(evt, Response.OK); responseAck(serverTransaction, Response.OK);
} catch (DocumentException e) { } catch (DocumentException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -59,7 +59,7 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
} }
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -64,11 +65,13 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
@Override @Override
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
ServerTransaction serverTransaction = getServerTransaction(evt);
try { try {
rootElement = getRootElement(evt, device.getCharset()); rootElement = getRootElement(evt, device.getCharset());
if (rootElement == null) { if (rootElement == null) {
logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest()); logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest());
responseAck(evt, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
return; return;
} }
MobilePosition mobilePosition = new MobilePosition(); MobilePosition mobilePosition = new MobilePosition();
@ -130,7 +133,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
jsonObject.put("speed", mobilePosition.getSpeed()); jsonObject.put("speed", mobilePosition.getSpeed());
redisCatchStorage.sendMobilePositionMsg(jsonObject); redisCatchStorage.sendMobilePositionMsg(jsonObject);
//回复 200 OK //回复 200 OK
responseAck(evt, Response.OK); responseAck(serverTransaction, Response.OK);
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -17,6 +17,7 @@ import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -51,10 +52,13 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
public void handForDevice(RequestEvent evt, Device device, Element element) { public void handForDevice(RequestEvent evt, Device device, Element element) {
Element rootElement = null; Element rootElement = null;
try { try {
ServerTransaction serverTransaction = getServerTransaction(evt);
rootElement = getRootElement(evt, device.getCharset()); rootElement = getRootElement(evt, device.getCharset());
if (rootElement == null) { if (rootElement == null) {
logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest()); logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
responseAck(evt, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
return; return;
} }
Element presetListNumElement = rootElement.element("PresetList"); Element presetListNumElement = rootElement.element("PresetList");
@ -63,7 +67,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
String deviceId = getText(rootElement, "DeviceID"); String deviceId = getText(rootElement, "DeviceID");
String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId; String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
if (snElement == null || presetListNumElement == null) { if (snElement == null || presetListNumElement == null) {
responseAck(evt, Response.BAD_REQUEST, "xml error"); responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
return; return;
} }
int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num")); int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
@ -93,7 +97,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
requestMessage.setKey(key); requestMessage.setKey(key);
requestMessage.setData(presetQuerySipReqList); requestMessage.setData(presetQuerySipReqList);
deferredResultHolder.invokeAllResult(requestMessage); deferredResultHolder.invokeAllResult(requestMessage);
responseAck(evt, Response.OK); responseAck(serverTransaction, Response.OK);
} catch (DocumentException e) { } catch (DocumentException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -72,7 +72,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
// 回复200 OK // 回复200 OK
try { try {
responseAck(evt, Response.OK); responseAck(getServerTransaction(evt), Response.OK);
taskQueue.offer(new HandlerCatchData(evt, device, rootElement)); taskQueue.offer(new HandlerCatchData(evt, device, rootElement));
if (!taskQueueHandlerRun) { if (!taskQueueHandlerRun) {
taskQueueHandlerRun = true; taskQueueHandlerRun = true;

View File

@ -7,6 +7,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcesso
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.utils.GitUtil; import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.ResponseEventExt; import gov.nist.javax.sip.ResponseEventExt;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPClientTransaction;
import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPDialog;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -78,7 +80,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
// 下发ack // 下发ack
if (statusCode == Response.OK) { if (statusCode == Response.OK) {
ResponseEventExt event = (ResponseEventExt)evt; ResponseEventExt event = (ResponseEventExt)evt;
SIPDialog dialog = (SIPDialog)evt.getDialog(); SIPDialog dialog = new SIPDialog((SIPClientTransaction) event.getClientTransaction(), (SIPResponse) event.getResponse());
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
Request reqAck = dialog.createAck(cseq.getSeqNumber()); Request reqAck = dialog.createAck(cseq.getSeqNumber());
SipURI requestURI = (SipURI) reqAck.getRequestURI(); SipURI requestURI = (SipURI) reqAck.getRequestURI();

View File

@ -103,7 +103,7 @@ public class ZLMHttpHookListener {
@PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
public JSONObject onServerKeepalive(@RequestBody JSONObject json){ public JSONObject onServerKeepalive(@RequestBody JSONObject json){
logger.info("[ ZLM HOOK ] on_server_keepalive API调用参数" + json.toString()); logger.info("[ ZLM HOOK ]on_server_keepalive API调用参数" + json.toString());
String mediaServerId = json.getString("mediaServerId"); String mediaServerId = json.getString("mediaServerId");
List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
if (subscribes != null && subscribes.size() > 0) { if (subscribes != null && subscribes.size() > 0) {
@ -453,6 +453,7 @@ public class ZLMHttpHookListener {
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
// 如果正在给上级推送则发送bye // 如果正在给上级推送则发送bye
}else{ }else{
streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null); streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null);
if (streamInfo != null) { if (streamInfo != null) {
@ -509,6 +510,19 @@ public class ZLMHttpHookListener {
} }
} }
} }
if (!regist) {
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(stream);
if (sendRtpItems.size() > 0) {
for (SendRtpItem sendRtpItem : sendRtpItems) {
if (sendRtpItem.getApp().equals(app)) {
String platformId = sendRtpItem.getPlatformId();
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
}
}
}
}
} }
JSONObject ret = new JSONObject(); JSONObject ret = new JSONObject();

View File

@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -83,7 +84,11 @@ public class ZLMMediaListManager {
} }
if (transform != null) { if (transform != null) {
if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) { if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) {
getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId()); try {
getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
} catch (ParseException e) {
throw new RuntimeException(e);
}
removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
} }
} }
@ -95,7 +100,11 @@ public class ZLMMediaListManager {
// 查看推流状态 // 查看推流状态
if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
if (getChannelOnlineEventLister(app, stream) != null) { if (getChannelOnlineEventLister(app, stream) != null) {
getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId); try {
getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
} catch (ParseException e) {
throw new RuntimeException(e);
}
removedChannelOnlineEventLister(app, stream); removedChannelOnlineEventLister(app, stream);
} }
} }

View File

@ -330,12 +330,12 @@ public class ZLMRTPServerFactory {
Boolean result = false; Boolean result = false;
JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
if (jsonObject == null) { if (jsonObject == null) {
logger.error("停止RTP推流失败: 请检查ZLM服务"); logger.error("[停止RTP推流] 失败: 请检查ZLM服务");
} else if (jsonObject.getInteger("code") == 0) { } else if (jsonObject.getInteger("code") == 0) {
result= true; result= true;
logger.info("停止RTP推流成功"); logger.info("[停止RTP推流] 成功");
} else { } else {
logger.error("停止RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"),JSONObject.toJSON(param), jsonObject);
} }
return result; return result;
} }

View File

@ -137,8 +137,6 @@ public class ZlmHttpHookSubscribe {
@Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
public void execute(){ public void execute(){
logger.info("[hook订阅] 清理");
Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
int total = 0; int total = 0;
for (HookType hookType : allSubscribes.keySet()) { for (HookType hookType : allSubscribes.keySet()) {
@ -153,6 +151,5 @@ public class ZlmHttpHookSubscribe {
} }
} }
} }
logger.info("[hook订阅] 清理结束,共清理{}条过期数据", total);
} }
} }

View File

@ -1,9 +1,11 @@
package com.genersoft.iot.vmp.media.zlm.dto; package com.genersoft.iot.vmp.media.zlm.dto;
import java.text.ParseException;
/** /**
* @author lin * @author lin
*/ */
public interface ChannelOnlineEvent { public interface ChannelOnlineEvent {
void run(String app, String stream, String serverId); void run(String app, String stream, String serverId) throws ParseException;
} }

View File

@ -1,8 +1,13 @@
package com.genersoft.iot.vmp.service; package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import java.util.List;
/** /**
* 国标平台的业务类 * 国标平台的业务类
* @author lin * @author lin
@ -42,4 +47,10 @@ public interface IPlatformService {
* @param parentPlatform * @param parentPlatform
*/ */
void login(ParentPlatform parentPlatform); void login(ParentPlatform parentPlatform);
/**
* 向上级平台发送位置订阅
* @param platformId 平台
*/
void sendNotifyMobilePosition(String platformId);
} }

View File

@ -73,7 +73,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
result = platformChannelMapper.addChannels(platformId, channelReducesToAdd); result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
// TODO 后续给平台增加控制开关以控制是否响应目录订阅 // TODO 后续给平台增加控制开关以控制是否响应目录订阅
List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform); List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); if (deviceChannelList != null) {
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
}
} }
return result; return result;
@ -83,7 +85,7 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
List<DeviceChannel> deviceChannelList = new ArrayList<>(); List<DeviceChannel> deviceChannelList = new ArrayList<>();
if (channelReduces.size() > 0){ if (channelReduces.size() > 0){
PlatformCatalog catalog = catalogManager.select(catalogId); PlatformCatalog catalog = catalogManager.select(catalogId);
if (catalog == null && !catalogId.equals(platform.getServerGBId())) { if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) {
logger.warn("未查询到目录{}的信息", catalogId); logger.warn("未查询到目录{}的信息", catalogId);
return null; return null;
} }

View File

@ -1,17 +1,16 @@
package com.genersoft.iot.vmp.service.impl; package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlatformService; import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -57,6 +56,9 @@ public class PlatformServiceImpl implements IPlatformService {
@Autowired @Autowired
private SubscribeHolder subscribeHolder; private SubscribeHolder subscribeHolder;
@Autowired
private GbStreamMapper gbStreamMapper;
@Override @Override
@ -228,4 +230,34 @@ public class PlatformServiceImpl implements IPlatformService {
60*1000); 60*1000);
}, null); }, null);
} }
@Override
public void sendNotifyMobilePosition(String platformId) {
ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
if (platform == null) {
return;
}
SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
if (subscribe != null) {
// TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
List<DeviceChannel> gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId());
if (gbStreams.size() == 0) {
return;
}
for (DeviceChannel deviceChannel : gbStreams) {
String gbId = deviceChannel.getChannelId();
GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
// 无最新位置不发送
if (gpsMsgInfo != null) {
// 经纬度都为0不发送
if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
continue;
}
// 发送GPS消息
commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
}
}
}
}
} }

View File

@ -23,6 +23,7 @@ import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -86,7 +87,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
public interface PlayMsgCallback{ public interface PlayMsgCallback{
void handler(ResponseSendItemMsg responseSendItemMsg); void handler(ResponseSendItemMsg responseSendItemMsg) throws ParseException;
} }
public interface PlayMsgCallbackForStartSendRtpStream{ public interface PlayMsgCallbackForStartSendRtpStream{
@ -134,7 +135,11 @@ public class RedisGbPlayMsgListener implements MessageListener {
PlayMsgCallback playMsgCallback = callbacks.get(key); PlayMsgCallback playMsgCallback = callbacks.get(key);
if (playMsgCallback != null) { if (playMsgCallback != null) {
callbacksForError.remove(key); callbacksForError.remove(key);
playMsgCallback.handler(responseSendItemMsg); try {
playMsgCallback.handler(responseSendItemMsg);
} catch (ParseException e) {
throw new RuntimeException(e);
}
} }
break; break;
case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: case ERROR_CODE_MEDIA_SERVER_NOT_FOUND:

View File

@ -710,14 +710,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override @Override
public void sendMobilePositionMsg(JSONObject jsonObject) { public void sendMobilePositionMsg(JSONObject jsonObject) {
String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION; String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
logger.info("[redis发送通知]移动位置 {}: {}", key, jsonObject.toString()); logger.info("[redis发送通知] 移动位置 {}: {}", key, jsonObject.toString());
RedisUtil.convertAndSend(key, jsonObject); RedisUtil.convertAndSend(key, jsonObject);
} }
@Override @Override
public void sendStreamPushRequestedMsg(MessageForPushChannel msg) { public void sendStreamPushRequestedMsg(MessageForPushChannel msg) {
String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED; String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
logger.info("[redis发送通知]推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream()); logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
} }

View File

@ -413,24 +413,20 @@ public class DeviceQuery {
@GetMapping("/{deviceId}/subscribe_info") @GetMapping("/{deviceId}/subscribe_info")
@Operation(summary = "获取设备的订阅状态") @Operation(summary = "获取设备的订阅状态")
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
public WVPResult<Map<String, String>> getSubscribeInfo(@PathVariable String deviceId) { public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) {
Set<String> allKeys = dynamicTask.getAllKeys(); Set<String> allKeys = dynamicTask.getAllKeys();
Map<String, String> dialogStateMap = new HashMap<>(); Map<String, Integer> dialogStateMap = new HashMap<>();
for (String key : allKeys) { for (String key : allKeys) {
if (key.startsWith(deviceId)) { if (key.startsWith(deviceId)) {
ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key); ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key);
DialogState dialogState = subscribeTask.getDialogState();
if (dialogState == null) {
continue;
}
if (subscribeTask instanceof CatalogSubscribeTask) { if (subscribeTask instanceof CatalogSubscribeTask) {
dialogStateMap.put("catalog", dialogState.toString()); dialogStateMap.put("catalog", 1);
}else if (subscribeTask instanceof MobilePositionSubscribeTask) { }else if (subscribeTask instanceof MobilePositionSubscribeTask) {
dialogStateMap.put("mobilePosition", dialogState.toString()); dialogStateMap.put("mobilePosition", 1);
} }
} }
} }
WVPResult<Map<String, String>> wvpResult = new WVPResult<>(); WVPResult<Map<String, Integer>> wvpResult = new WVPResult<>();
wvpResult.setCode(0); wvpResult.setCode(0);
wvpResult.setData(dialogStateMap); wvpResult.setData(dialogStateMap);
return wvpResult; return wvpResult;

View File

@ -84,12 +84,13 @@ export default {
method: 'get', method: 'get',
url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}` url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
}).then((res)=> { }).then((res)=> {
console.log(res)
if (res.data.code === 0) { if (res.data.code === 0) {
this.streamInfo = res.data.data; this.streamInfo = res.data.data;
if (parseFloat(res.data.progress) == 1) { if (parseFloat(res.data.progress) == 1) {
this.percentage = 100; this.percentage = 100;
}else { }else {
this.percentage = (res.data.data.progress*100).toFixed(1); this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1);
} }
if (callback)callback(); if (callback)callback();
} }