修复 SiP消息超时未未回复无法识别的BUG
parent
b9738c6bfc
commit
2492b0d638
|
@ -1,13 +1,15 @@
|
||||||
package com.genersoft.iot.vmp.conf;
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.core.annotation.Order;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true)
|
@ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true)
|
||||||
@Order(0)
|
@Order(0)
|
||||||
|
@Data
|
||||||
public class SipConfig {
|
public class SipConfig {
|
||||||
|
|
||||||
private String ip;
|
private String ip;
|
||||||
|
@ -26,82 +28,7 @@ public class SipConfig {
|
||||||
|
|
||||||
Integer registerTimeInterval = 120;
|
Integer registerTimeInterval = 120;
|
||||||
|
|
||||||
private boolean alarm;
|
private boolean alarm = false;
|
||||||
|
|
||||||
public void setIp(String ip) {
|
private long timeout = 15;
|
||||||
this.ip = ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(Integer port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDomain(String domain) {
|
|
||||||
this.domain = domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPtzSpeed(Integer ptzSpeed) {
|
|
||||||
this.ptzSpeed = ptzSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setRegisterTimeInterval(Integer registerTimeInterval) {
|
|
||||||
this.registerTimeInterval = registerTimeInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIp() {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Integer getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getDomain() {
|
|
||||||
return domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Integer getPtzSpeed() {
|
|
||||||
return ptzSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getRegisterTimeInterval() {
|
|
||||||
return registerTimeInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAlarm() {
|
|
||||||
return alarm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarm(boolean alarm) {
|
|
||||||
this.alarm = alarm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShowIp() {
|
|
||||||
return showIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShowIp(String showIp) {
|
|
||||||
this.showIp = showIp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ public class SipLayer implements CommandLineRunner {
|
||||||
|
|
||||||
SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||||
udpSipProvider.addSipListener(sipProcessorObserver);
|
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||||
|
udpSipProvider.setDialogErrorsAutomaticallyHandled();
|
||||||
udpSipProviderMap.put(monitorIp, udpSipProvider);
|
udpSipProviderMap.put(monitorIp, udpSipProvider);
|
||||||
|
|
||||||
log.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port);
|
log.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port);
|
||||||
|
|
|
@ -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 com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
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.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -13,10 +14,9 @@ import javax.sip.ResponseEvent;
|
||||||
import javax.sip.TimeoutEvent;
|
import javax.sip.TimeoutEvent;
|
||||||
import javax.sip.TransactionTerminatedEvent;
|
import javax.sip.TransactionTerminatedEvent;
|
||||||
import javax.sip.header.WarningHeader;
|
import javax.sip.header.WarningHeader;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.DelayQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lin
|
* @author lin
|
||||||
|
@ -25,41 +25,36 @@ import java.util.concurrent.TimeUnit;
|
||||||
@Component
|
@Component
|
||||||
public class SipSubscribe {
|
public class SipSubscribe {
|
||||||
|
|
||||||
private final Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>();
|
private final Map<String, SipEvent> subscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
|
private final DelayQueue<SipEvent> delayQueue = new DelayQueue<>();
|
||||||
|
|
||||||
private final Map<String, Instant> okTimeSubscribes = new ConcurrentHashMap<>();
|
@Scheduled(fixedRate = 200) //每200毫秒执行
|
||||||
|
|
||||||
private final Map<String, Instant> errorTimeSubscribes = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
|
|
||||||
// @Scheduled(fixedRate= 100 * 60 * 60 )
|
|
||||||
@Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
|
|
||||||
public void execute(){
|
public void execute(){
|
||||||
if(log.isDebugEnabled()){
|
if (delayQueue.isEmpty()) {
|
||||||
log.info("[定时任务] 清理过期的SIP订阅信息");
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
SipEvent take = delayQueue.take();
|
||||||
|
// 出现超时异常
|
||||||
|
if(take.getErrorEvent() != null) {
|
||||||
|
EventResult<Object> eventResult = new EventResult<>();
|
||||||
|
eventResult.type = EventResultType.timeout;
|
||||||
|
eventResult.msg = "消息超时未回复";
|
||||||
|
eventResult.statusCode = -1024;
|
||||||
|
take.getErrorEvent().response(eventResult);
|
||||||
|
}
|
||||||
|
subscribes.remove(take.getKey());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
|
public void updateTimeout(String callId) {
|
||||||
|
SipEvent sipEvent = subscribes.get(callId);
|
||||||
for (String key : okTimeSubscribes.keySet()) {
|
if (sipEvent != null) {
|
||||||
if (okTimeSubscribes.get(key).isBefore(instant)){
|
delayQueue.remove(sipEvent);
|
||||||
okSubscribes.remove(key);
|
delayQueue.offer(sipEvent);
|
||||||
okTimeSubscribes.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String key : errorTimeSubscribes.keySet()) {
|
|
||||||
if (errorTimeSubscribes.get(key).isBefore(instant)){
|
|
||||||
errorSubscribes.remove(key);
|
|
||||||
errorTimeSubscribes.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(log.isDebugEnabled()){
|
|
||||||
log.debug("okTimeSubscribes.size:{}",okTimeSubscribes.size());
|
|
||||||
log.debug("okSubscribes.size:{}",okSubscribes.size());
|
|
||||||
log.debug("errorTimeSubscribes.size:{}",errorTimeSubscribes.size());
|
|
||||||
log.debug("errorSubscribes.size:{}",errorSubscribes.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,43 +151,33 @@ public class SipSubscribe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addErrorSubscribe(String key, SipSubscribe.Event event) {
|
|
||||||
errorSubscribes.put(key, event);
|
public void addSubscribe(String key, SipEvent event) {
|
||||||
errorTimeSubscribes.put(key, Instant.now());
|
SipEvent sipEvent = subscribes.get(key);
|
||||||
|
if (sipEvent != null) {
|
||||||
|
subscribes.remove(key);
|
||||||
|
delayQueue.remove(sipEvent);
|
||||||
|
}
|
||||||
|
subscribes.put(key, event);
|
||||||
|
delayQueue.offer(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOkSubscribe(String key, SipSubscribe.Event event) {
|
public SipEvent getSubscribe(String key) {
|
||||||
okSubscribes.put(key, event);
|
return subscribes.get(key);
|
||||||
okTimeSubscribes.put(key, Instant.now());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SipSubscribe.Event getErrorSubscribe(String key) {
|
public void removeSubscribe(String key) {
|
||||||
return errorSubscribes.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeErrorSubscribe(String key) {
|
|
||||||
if(key == null){
|
if(key == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
errorSubscribes.remove(key);
|
SipEvent sipEvent = subscribes.get(key);
|
||||||
errorTimeSubscribes.remove(key);
|
if (sipEvent != null) {
|
||||||
|
subscribes.remove(key);
|
||||||
|
delayQueue.remove(sipEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SipSubscribe.Event getOkSubscribe(String key) {
|
public boolean isEmpty(){
|
||||||
return okSubscribes.get(key);
|
return subscribes.isEmpty();
|
||||||
}
|
|
||||||
|
|
||||||
public void removeOkSubscribe(String key) {
|
|
||||||
if(key == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
okSubscribes.remove(key);
|
|
||||||
okTimeSubscribes.remove(key);
|
|
||||||
}
|
|
||||||
public int getErrorSubscribesSize(){
|
|
||||||
return errorSubscribes.size();
|
|
||||||
}
|
|
||||||
public int getOkSubscribesSize(){
|
|
||||||
return okSubscribes.size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.event.sip;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SipEvent implements Delayed {
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功的回调
|
||||||
|
*/
|
||||||
|
private SipSubscribe.Event okEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误的回调,包括超时
|
||||||
|
*/
|
||||||
|
private SipSubscribe.Event errorEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间
|
||||||
|
*/
|
||||||
|
private long delay;
|
||||||
|
|
||||||
|
public static SipEvent getInstance(String key, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, long delay) {
|
||||||
|
SipEvent sipEvent = new SipEvent();
|
||||||
|
sipEvent.setKey(key);
|
||||||
|
sipEvent.setOkEvent(okEvent);
|
||||||
|
sipEvent.setErrorEvent(errorEvent);
|
||||||
|
sipEvent.setDelay(delay);
|
||||||
|
return sipEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelay(@NotNull TimeUnit unit) {
|
||||||
|
return unit.convert(delay - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull Delayed o) {
|
||||||
|
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
}
|
|
@ -380,7 +380,9 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||||
commanderForPlatform.register(platform, sipTransactionInfo, eventResult -> {
|
commanderForPlatform.register(platform, sipTransactionInfo, eventResult -> {
|
||||||
log.info("[国标级联] 平台:{}注册失败,{}:{}", platform.getServerGBId(),
|
log.info("[国标级联] 平台:{}注册失败,{}:{}", platform.getServerGBId(),
|
||||||
eventResult.statusCode, eventResult.msg);
|
eventResult.statusCode, eventResult.msg);
|
||||||
|
if (platform.isStatus()) {
|
||||||
offline(platform, false);
|
offline(platform, false);
|
||||||
|
}
|
||||||
}, null);
|
}, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
|
log.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
|
||||||
|
|
|
@ -436,7 +436,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
// 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
|
// 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
|
||||||
InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel, callback, inviteInfo, InviteSessionType.PLAY);
|
InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel, callback, inviteInfo, InviteSessionType.PLAY);
|
||||||
}, (event) -> {
|
}, (event) -> {
|
||||||
log.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channel.getDeviceId(), event.statusCode, event.msg);
|
log.info("[点播失败]{}:{} deviceId: {}, channelId:{}",event.statusCode, event.msg, device.getDeviceId(), channel.getDeviceId());
|
||||||
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
||||||
|
|
||||||
sessionManager.removeByStream(ssrcInfo.getStream());
|
sessionManager.removeByStream(ssrcInfo.getStream());
|
||||||
|
@ -447,7 +447,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
event.statusCode, event.msg, null);
|
event.statusCode, event.msg, null);
|
||||||
|
|
||||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, channel.getId());
|
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, channel.getId());
|
||||||
});
|
}, userSetting.getPlayTimeout().longValue());
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
log.error("[命令发送失败] 点播消息: {}", e.getMessage());
|
log.error("[命令发送失败] 点播消息: {}", e.getMessage());
|
||||||
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
||||||
|
@ -565,7 +565,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
|
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
|
||||||
sessionManager.removeByStream(sendRtpInfo.getStream());
|
sessionManager.removeByStream(sendRtpInfo.getStream());
|
||||||
errorEvent.response(event);
|
errorEvent.response(event);
|
||||||
});
|
}, userSetting.getPlayTimeout().longValue());
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
|
|
||||||
log.error("[命令发送失败] 对讲消息: {}", e.getMessage());
|
log.error("[命令发送失败] 对讲消息: {}", e.getMessage());
|
||||||
|
@ -820,7 +820,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
||||||
sessionManager.removeByStream(ssrcInfo.getStream());
|
sessionManager.removeByStream(ssrcInfo.getStream());
|
||||||
inviteStreamService.removeInviteInfo(inviteInfo);
|
inviteStreamService.removeInviteInfo(inviteInfo);
|
||||||
});
|
}, userSetting.getPlayTimeout().longValue());
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
log.error("[命令发送失败] 录像回放: {}", e.getMessage());
|
log.error("[命令发送失败] 录像回放: {}", e.getMessage());
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
|
@ -1044,7 +1044,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
// 设置过期时间,下载失败时自动处理订阅数据
|
// 设置过期时间,下载失败时自动处理订阅数据
|
||||||
hook.setExpireTime(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
|
hook.setExpireTime(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
|
||||||
subscribe.addSubscribe(hook, hookEventForRecord);
|
subscribe.addSubscribe(hook, hookEventForRecord);
|
||||||
});
|
}, userSetting.getPlayTimeout().longValue());
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
log.error("[命令发送失败] 录像下载: {}", e.getMessage());
|
log.error("[命令发送失败] 录像下载: {}", e.getMessage());
|
||||||
callback.run(InviteErrorCode.FAIL.getCode(),e.getMessage(), null);
|
callback.run(InviteErrorCode.FAIL.getCode(),e.getMessage(), null);
|
||||||
|
|
|
@ -2,18 +2,18 @@ package com.genersoft.iot.vmp.gb28181.transmit;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
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.response.ISIPResponseProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
||||||
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.sip.*;
|
import javax.sip.*;
|
||||||
import javax.sip.header.CSeqHeader;
|
|
||||||
import javax.sip.header.CallIdHeader;
|
import javax.sip.header.CallIdHeader;
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -88,40 +88,40 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
|
||||||
@Override
|
@Override
|
||||||
@Async("taskExecutor")
|
@Async("taskExecutor")
|
||||||
public void processResponse(ResponseEvent responseEvent) {
|
public void processResponse(ResponseEvent responseEvent) {
|
||||||
Response response = responseEvent.getResponse();
|
SIPResponse response = (SIPResponse)responseEvent.getResponse();
|
||||||
int status = response.getStatusCode();
|
int status = response.getStatusCode();
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
|
if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
|
||||||
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
|
if (status != Response.UNAUTHORIZED && responseEvent.getResponse() != null && !sipSubscribe.isEmpty() ) {
|
||||||
String method = cseqHeader.getMethod();
|
CallIdHeader callIdHeader = response.getCallIdHeader();
|
||||||
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method);
|
if (callIdHeader != null) {
|
||||||
|
SipEvent sipEvent = sipSubscribe.getSubscribe(callIdHeader.getCallId());
|
||||||
|
if (sipEvent != null && sipEvent.getOkEvent() != null) {
|
||||||
|
SipSubscribe.EventResult<ResponseEvent> eventResult = new SipSubscribe.EventResult<>(responseEvent);
|
||||||
|
sipSubscribe.removeSubscribe(callIdHeader.getCallId());
|
||||||
|
sipEvent.getOkEvent().response(eventResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(response.getCSeqHeader().getMethod());
|
||||||
if (sipRequestProcessor != null) {
|
if (sipRequestProcessor != null) {
|
||||||
sipRequestProcessor.process(responseEvent);
|
sipRequestProcessor.process(responseEvent);
|
||||||
}
|
}
|
||||||
if (status != Response.UNAUTHORIZED && responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
|
|
||||||
if (callIdHeader != null) {
|
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
|
|
||||||
if (subscribe != null) {
|
|
||||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
|
|
||||||
sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
|
|
||||||
subscribe.response(eventResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((status >= Response.TRYING) && (status < Response.OK)) {
|
} else if ((status >= Response.TRYING) && (status < Response.OK)) {
|
||||||
// 增加其它无需回复的响应,如101、180等
|
// 增加其它无需回复的响应,如101、180等
|
||||||
|
// 更新sip订阅的时间
|
||||||
|
// sipSubscribe.updateTimeout(response.getCallIdHeader().getCallId());
|
||||||
} else {
|
} else {
|
||||||
log.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase());
|
log.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase());
|
||||||
if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
|
if (responseEvent.getResponse() != null && !sipSubscribe.isEmpty() ) {
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
|
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
|
||||||
if (callIdHeader != null) {
|
if (callIdHeader != null) {
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
SipEvent sipEvent = sipSubscribe.getSubscribe(callIdHeader.getCallId());
|
||||||
if (subscribe != null) {
|
if (sipEvent != null && sipEvent.getErrorEvent() != null) {
|
||||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
|
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
|
||||||
subscribe.response(eventResult);
|
sipSubscribe.removeSubscribe(callIdHeader.getCallId());
|
||||||
sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
|
sipEvent.getErrorEvent().response(eventResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,27 +140,27 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
|
||||||
@Override
|
@Override
|
||||||
public void processTimeout(TimeoutEvent timeoutEvent) {
|
public void processTimeout(TimeoutEvent timeoutEvent) {
|
||||||
log.info("[消息发送超时]");
|
log.info("[消息发送超时]");
|
||||||
ClientTransaction clientTransaction = timeoutEvent.getClientTransaction();
|
// ClientTransaction clientTransaction = timeoutEvent.getClientTransaction();
|
||||||
|
//
|
||||||
if (clientTransaction != null) {
|
// if (clientTransaction != null) {
|
||||||
log.info("[发送错误订阅] clientTransaction != null");
|
// log.info("[发送错误订阅] clientTransaction != null");
|
||||||
Request request = clientTransaction.getRequest();
|
// Request request = clientTransaction.getRequest();
|
||||||
if (request != null) {
|
// if (request != null) {
|
||||||
log.info("[发送错误订阅] request != null");
|
// log.info("[发送错误订阅] request != null");
|
||||||
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
|
// CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
|
||||||
if (callIdHeader != null) {
|
// if (callIdHeader != null) {
|
||||||
log.info("[发送错误订阅]");
|
// log.info("[发送错误订阅]");
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
// SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
||||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent);
|
// SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent);
|
||||||
if (subscribe != null){
|
// if (subscribe != null){
|
||||||
subscribe.response(eventResult);
|
// subscribe.response(eventResult);
|
||||||
}
|
// }
|
||||||
sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
|
// sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
|
||||||
sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
|
// sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
eventPublisher.requestTimeOut(timeoutEvent);
|
// eventPublisher.requestTimeOut(timeoutEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,4 +199,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.transmit;
|
package com.genersoft.iot.vmp.gb28181.transmit;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
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.SipProviderImpl;
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
@ -21,6 +23,7 @@ import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送SIP消息
|
* 发送SIP消息
|
||||||
|
*
|
||||||
* @author lin
|
* @author lin
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -35,16 +38,22 @@ public class SIPSender {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipSubscribe sipSubscribe;
|
private SipSubscribe sipSubscribe;
|
||||||
|
@Autowired
|
||||||
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
public void transmitRequest(String ip, Message message) throws SipException, ParseException {
|
public void transmitRequest(String ip, Message message) throws SipException, ParseException {
|
||||||
transmitRequest(ip, message, null, null);
|
transmitRequest(ip, message, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent) throws SipException, ParseException {
|
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent) throws SipException, ParseException {
|
||||||
transmitRequest(ip, message, errorEvent, null);
|
transmitRequest(ip, message, errorEvent, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException {
|
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException {
|
||||||
|
transmitRequest(ip, message, errorEvent, okEvent, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, Long timeout) throws SipException {
|
||||||
ViaHeader viaHeader = (ViaHeader) message.getHeader(ViaHeader.NAME);
|
ViaHeader viaHeader = (ViaHeader) message.getHeader(ViaHeader.NAME);
|
||||||
String transport = "UDP";
|
String transport = "UDP";
|
||||||
if (viaHeader == null) {
|
if (viaHeader == null) {
|
||||||
|
@ -60,23 +69,22 @@ public class SIPSender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (okEvent != null || errorEvent != null) {
|
||||||
CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
|
CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
|
||||||
// 添加错误订阅
|
SipEvent sipEvent = SipEvent.getInstance(callIdHeader.getCallId(), eventResult -> {
|
||||||
if (errorEvent != null) {
|
sipSubscribe.removeSubscribe(eventResult.callId);
|
||||||
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
|
|
||||||
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
|
||||||
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
|
||||||
errorEvent.response(eventResult);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
// 添加订阅
|
|
||||||
if(okEvent != null) {
|
if(okEvent != null) {
|
||||||
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
|
|
||||||
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
|
||||||
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
|
||||||
okEvent.response(eventResult);
|
okEvent.response(eventResult);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}, (eventResult -> {
|
||||||
|
sipSubscribe.removeSubscribe(eventResult.callId);
|
||||||
|
if (errorEvent != null) {
|
||||||
|
errorEvent.response(eventResult);
|
||||||
|
}
|
||||||
|
}), timeout == null ? sipConfig.getTimeout() : timeout);
|
||||||
|
sipSubscribe.addSubscribe(callIdHeader.getCallId(), sipEvent);
|
||||||
|
}
|
||||||
|
|
||||||
if ("TCP".equals(transport)) {
|
if ("TCP".equals(transport)) {
|
||||||
SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip);
|
SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip);
|
||||||
if (tcpSipProvider == null) {
|
if (tcpSipProvider == null) {
|
||||||
|
@ -127,4 +135,6 @@ public class SIPSender {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ public interface ISIPCommander {
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channel 预览通道
|
* @param channel 预览通道
|
||||||
*/
|
*/
|
||||||
void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求回放视频流
|
* 请求回放视频流
|
||||||
|
@ -110,7 +110,7 @@ public interface ISIPCommander {
|
||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
*/
|
*/
|
||||||
void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInf, Device device, DeviceChannel channel, String startTime, String endTime, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInf, Device device, DeviceChannel channel, String startTime, String endTime, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求历史媒体下载
|
* 请求历史媒体下载
|
||||||
|
@ -123,7 +123,7 @@ public interface ISIPCommander {
|
||||||
*/
|
*/
|
||||||
void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||||
String startTime, String endTime, int downloadSpeed,
|
String startTime, String endTime, int downloadSpeed,
|
||||||
SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,7 +131,7 @@ public interface ISIPCommander {
|
||||||
*/
|
*/
|
||||||
void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
|
void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
|
||||||
|
|
||||||
void talkStreamCmd(MediaServer mediaServerItem, SendRtpInfo sendRtpItem, Device device, DeviceChannel channelId, String callId, HookSubscribe.Event event, HookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
void talkStreamCmd(MediaServer mediaServerItem, SendRtpInfo sendRtpItem, Device device, DeviceChannel channelId, String callId, HookSubscribe.Event event, HookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
|
|
||||||
void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
|
void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
|
||||||
|
|
|
@ -262,7 +262,7 @@ public class SIPCommander implements ISIPCommander {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
public void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||||
SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException {
|
||||||
String stream = ssrcInfo.getStream();
|
String stream = ssrcInfo.getStream();
|
||||||
|
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
|
@ -335,8 +335,6 @@ public class SIPCommander implements ISIPCommander {
|
||||||
// f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
|
// f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
|
||||||
// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
|
// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Request request = headerProvider.createInviteRequest(device, channel.getDeviceId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
Request request = headerProvider.createInviteRequest(device, channel.getDeviceId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
|
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
|
||||||
sessionManager.removeByStream(ssrcInfo.getStream());
|
sessionManager.removeByStream(ssrcInfo.getStream());
|
||||||
|
@ -350,7 +348,7 @@ public class SIPCommander implements ISIPCommander {
|
||||||
InviteSessionType.PLAY);
|
InviteSessionType.PLAY);
|
||||||
sessionManager.put(ssrcTransaction);
|
sessionManager.put(ssrcTransaction);
|
||||||
okEvent.response(e);
|
okEvent.response(e);
|
||||||
});
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -364,7 +362,7 @@ public class SIPCommander implements ISIPCommander {
|
||||||
@Override
|
@Override
|
||||||
public void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
public void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||||
String startTime, String endTime,
|
String startTime, String endTime,
|
||||||
SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException {
|
||||||
|
|
||||||
|
|
||||||
log.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
|
log.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
|
||||||
|
@ -445,7 +443,7 @@ public class SIPCommander implements ISIPCommander {
|
||||||
channel.getId(), sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK);
|
channel.getId(), sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK);
|
||||||
sessionManager.put(ssrcTransaction);
|
sessionManager.put(ssrcTransaction);
|
||||||
okEvent.response(event);
|
okEvent.response(event);
|
||||||
});
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,7 +452,7 @@ public class SIPCommander implements ISIPCommander {
|
||||||
@Override
|
@Override
|
||||||
public void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
public void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||||
String startTime, String endTime, int downloadSpeed,
|
String startTime, String endTime, int downloadSpeed,
|
||||||
SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
|
SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException {
|
||||||
|
|
||||||
log.info("[发送-请求历史媒体下载-命令] 流ID: {},节点为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
|
log.info("[发送-请求历史媒体下载-命令] 流ID: {},节点为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
|
||||||
String sdpIp;
|
String sdpIp;
|
||||||
|
@ -536,11 +534,13 @@ public class SIPCommander implements ISIPCommander {
|
||||||
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(), response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD);
|
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(), response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD);
|
||||||
sessionManager.put(ssrcTransaction);
|
sessionManager.put(ssrcTransaction);
|
||||||
okEvent.response(event);
|
okEvent.response(event);
|
||||||
});
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void talkStreamCmd(MediaServer mediaServerItem, SendRtpInfo sendRtpItem, Device device, DeviceChannel channel, String callId, HookSubscribe.Event event, HookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
public void talkStreamCmd(MediaServer mediaServerItem, SendRtpInfo sendRtpItem, Device device, DeviceChannel channel,
|
||||||
|
String callId, HookSubscribe.Event event, HookSubscribe.Event eventForPush, SipSubscribe.Event okEvent,
|
||||||
|
SipSubscribe.Event errorEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException {
|
||||||
|
|
||||||
String stream = sendRtpItem.getStream();
|
String stream = sendRtpItem.getStream();
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ public class SIPCommander implements ISIPCommander {
|
||||||
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(), "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK);
|
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(), "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK);
|
||||||
sessionManager.put(ssrcTransaction);
|
sessionManager.put(ssrcTransaction);
|
||||||
okEvent.response(e);
|
okEvent.response(e);
|
||||||
});
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -127,23 +127,19 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
||||||
// 将 callid 写入缓存, 等注册成功可以更新状态
|
// 将 callid 写入缓存, 等注册成功可以更新状态
|
||||||
String callIdFromHeader = callIdHeader.getCallId();
|
String callIdFromHeader = callIdHeader.getCallId();
|
||||||
redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister));
|
redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister));
|
||||||
|
|
||||||
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{
|
|
||||||
if (event != null) {
|
|
||||||
log.info("向上级平台 [ {} ] 注册发生错误: {} ",
|
|
||||||
parentPlatform.getServerGBId(),
|
|
||||||
event.msg);
|
|
||||||
}
|
|
||||||
redisCatchStorage.delPlatformRegisterInfo(callIdFromHeader);
|
|
||||||
if (errorEvent != null ) {
|
|
||||||
errorEvent.response(event);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}else {
|
}else {
|
||||||
request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, fromTag, toTag, www, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, fromTag, toTag, www, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, okEvent);
|
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, (event)->{
|
||||||
|
if (event != null) {
|
||||||
|
log.info("[国标级联]:{}, 注册失败: {} ", parentPlatform.getServerGBId(), event.msg);
|
||||||
|
}
|
||||||
|
redisCatchStorage.delPlatformRegisterInfo(callIdHeader.getCallId());
|
||||||
|
if (errorEvent != null ) {
|
||||||
|
errorEvent.response(event);
|
||||||
|
}
|
||||||
|
}, okEvent, 5L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -167,6 +163,7 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
||||||
SipUtils.getNewFromTag(),
|
SipUtils.getNewFromTag(),
|
||||||
SipUtils.getNewViaTag(),
|
SipUtils.getNewViaTag(),
|
||||||
callIdHeader);
|
callIdHeader);
|
||||||
|
|
||||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
|
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
|
||||||
return callIdHeader.getCallId();
|
return callIdHeader.getCallId();
|
||||||
}
|
}
|
||||||
|
@ -249,16 +246,17 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
||||||
log.debug(catalogXml);
|
log.debug(catalogXml);
|
||||||
if (sendAfterResponse) {
|
if (sendAfterResponse) {
|
||||||
// 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。
|
// 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。
|
||||||
dynamicTask.startDelay(timeoutTaskKey, ()->{
|
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, eventResult -> {
|
||||||
sipSubscribe.removeOkSubscribe(callId);
|
if (eventResult.type.equals(SipSubscribe.EventResultType.timeout)) {
|
||||||
|
// 消息发送超时, 以30毫秒的间隔直接发送
|
||||||
int indexNext = index + parentPlatform.getCatalogGroup();
|
int indexNext = index + parentPlatform.getCatalogGroup();
|
||||||
try {
|
try {
|
||||||
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, false);
|
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, false);
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||||
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}, 3000);
|
return;
|
||||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, eventResult -> {
|
}
|
||||||
log.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
log.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
||||||
dynamicTask.stop(timeoutTaskKey);
|
dynamicTask.stop(timeoutTaskKey);
|
||||||
}, eventResult -> {
|
}, eventResult -> {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
@ -93,11 +94,12 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
|
||||||
// 不存在则回复404
|
// 不存在则回复404
|
||||||
responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found");
|
responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found");
|
||||||
log.warn("[设备未找到 ]deviceId: {}, callId: {}", deviceId, callIdHeader.getCallId());
|
log.warn("[设备未找到 ]deviceId: {}, callId: {}", deviceId, callIdHeader.getCallId());
|
||||||
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
|
SipEvent sipEvent = sipSubscribe.getSubscribe(callIdHeader.getCallId());
|
||||||
|
if (sipEvent != null && sipEvent.getErrorEvent() != null){
|
||||||
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
|
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
|
||||||
deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
|
deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
|
||||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
|
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
|
||||||
sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
|
sipEvent.getErrorEvent().response(eventResult);
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
Element rootElement;
|
Element rootElement;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.transmit.event.response;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response;
|
||||||
|
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
import javax.sip.ResponseEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,6 +11,7 @@ import javax.sip.ResponseEvent;
|
||||||
*/
|
*/
|
||||||
public interface ISIPResponseProcessor {
|
public interface ISIPResponseProcessor {
|
||||||
|
|
||||||
|
|
||||||
void process(ResponseEvent evt);
|
void process(ResponseEvent evt);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,14 +38,12 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPProcessorObserver sipProcessorObserver;
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPSender sipSender;
|
private SIPSender sipSender;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPRequestHeaderProvider headerProvider;
|
private SIPRequestHeaderProvider headerProvider;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
// 添加消息处理的订阅
|
// 添加消息处理的订阅
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -32,11 +33,12 @@ public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
CallIdHeader callIdHeader = event.getClientTransaction().getDialog().getCallId();
|
CallIdHeader callIdHeader = event.getClientTransaction().getDialog().getCallId();
|
||||||
String callId = callIdHeader.getCallId();
|
String callId = callIdHeader.getCallId();
|
||||||
SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId);
|
SipEvent sipEvent = sipSubscribe.getSubscribe(callId);
|
||||||
|
if (sipEvent != null && sipEvent.getErrorEvent() != null) {
|
||||||
SipSubscribe.EventResult<TimeoutEvent> timeoutEventEventResult = new SipSubscribe.EventResult<>(event);
|
SipSubscribe.EventResult<TimeoutEvent> timeoutEventEventResult = new SipSubscribe.EventResult<>(event);
|
||||||
errorSubscribe.response(timeoutEventEventResult);
|
sipEvent.getErrorEvent().response(timeoutEventEventResult);
|
||||||
sipSubscribe.removeErrorSubscribe(callId);
|
sipSubscribe.removeSubscribe(callId);
|
||||||
sipSubscribe.removeOkSubscribe(callId);
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[超时事件失败]: {}", e.getMessage());
|
log.error("[超时事件失败]: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,8 @@ sip:
|
||||||
# keepalliveToOnline: false
|
# keepalliveToOnline: false
|
||||||
# 是否存储alarm信息
|
# 是否存储alarm信息
|
||||||
alarm: false
|
alarm: false
|
||||||
|
# 命令发送等待回复的超时时间, 单位:秒
|
||||||
|
timeout: 15
|
||||||
|
|
||||||
# 做为JT1078服务器的配置
|
# 做为JT1078服务器的配置
|
||||||
jt1078:
|
jt1078:
|
||||||
|
|
Loading…
Reference in New Issue