Commit 2de4c322f6dc79ecfb120106af07e3335994657a
1 parent
d47902bd
去除对redis key过期事件的使用;重构国标级联的注册保活
Showing
45 changed files
with
513 additions
and
693 deletions
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
| ... | ... | @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 7 | +import com.genersoft.iot.vmp.service.IPlatformService; | |
| 7 | 8 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 8 | 9 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; |
| ... | ... | @@ -15,6 +16,7 @@ import java.util.List; |
| 15 | 16 | |
| 16 | 17 | /** |
| 17 | 18 | * 系统启动时控制上级平台重新注册 |
| 19 | + * @author lin | |
| 18 | 20 | */ |
| 19 | 21 | @Component |
| 20 | 22 | @Order(value=3) |
| ... | ... | @@ -27,7 +29,7 @@ public class SipPlatformRunner implements CommandLineRunner { |
| 27 | 29 | private IRedisCatchStorage redisCatchStorage; |
| 28 | 30 | |
| 29 | 31 | @Autowired |
| 30 | - private EventPublisher publisher; | |
| 32 | + private IPlatformService platformService; | |
| 31 | 33 | |
| 32 | 34 | @Autowired |
| 33 | 35 | private ISIPCommanderForPlatform sipCommanderForPlatform; |
| ... | ... | @@ -35,33 +37,26 @@ public class SipPlatformRunner implements CommandLineRunner { |
| 35 | 37 | |
| 36 | 38 | @Override |
| 37 | 39 | public void run(String... args) throws Exception { |
| 38 | - // 设置所有平台离线 | |
| 39 | - storager.outlineForAllParentPlatform(); | |
| 40 | - | |
| 41 | - // 清理所有平台注册缓存 | |
| 42 | - redisCatchStorage.cleanPlatformRegisterInfos(); | |
| 43 | - | |
| 44 | - // 停止所有推流 | |
| 45 | -// zlmrtpServerFactory.closeAllSendRtpStream(); | |
| 46 | - | |
| 40 | + // 获取所有启用的平台 | |
| 47 | 41 | List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true); |
| 48 | 42 | |
| 49 | 43 | for (ParentPlatform parentPlatform : parentPlatforms) { |
| 50 | - redisCatchStorage.updatePlatformRegister(parentPlatform); | |
| 51 | - | |
| 52 | - redisCatchStorage.updatePlatformKeepalive(parentPlatform); | |
| 53 | - | |
| 44 | + // 更新缓存 | |
| 54 | 45 | ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); |
| 55 | - | |
| 56 | 46 | parentPlatformCatch.setParentPlatform(parentPlatform); |
| 57 | 47 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); |
| 58 | 48 | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); |
| 49 | + if (parentPlatform.isStatus()) { | |
| 50 | + // 设置所有平台离线 | |
| 51 | + platformService.offline(parentPlatform); | |
| 52 | + // 取消订阅 | |
| 53 | + sipCommanderForPlatform.unregister(parentPlatform, null, (eventResult)->{ | |
| 54 | + platformService.login(parentPlatform); | |
| 55 | + }); | |
| 56 | + }else { | |
| 57 | + platformService.login(parentPlatform); | |
| 58 | + } | |
| 59 | 59 | |
| 60 | - // 取消订阅 | |
| 61 | - sipCommanderForPlatform.unregister(parentPlatform, null, (eventResult)->{ | |
| 62 | - // 发送平台未注册消息 | |
| 63 | - publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId()); | |
| 64 | - }); | |
| 65 | 60 | } |
| 66 | 61 | } |
| 67 | 62 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
| ... | ... | @@ -31,8 +31,6 @@ public class UserSetting { |
| 31 | 31 | |
| 32 | 32 | private Boolean logInDatebase = Boolean.TRUE; |
| 33 | 33 | |
| 34 | - private Boolean redisConfig = Boolean.TRUE; | |
| 35 | - | |
| 36 | 34 | private String serverId = "000000"; |
| 37 | 35 | |
| 38 | 36 | private String thirdPartyGBIdReg = "[\\s\\S]*"; |
| ... | ... | @@ -123,14 +121,6 @@ public class UserSetting { |
| 123 | 121 | this.thirdPartyGBIdReg = thirdPartyGBIdReg; |
| 124 | 122 | } |
| 125 | 123 | |
| 126 | - public Boolean getRedisConfig() { | |
| 127 | - return redisConfig; | |
| 128 | - } | |
| 129 | - | |
| 130 | - public void setRedisConfig(Boolean redisConfig) { | |
| 131 | - this.redisConfig = redisConfig; | |
| 132 | - } | |
| 133 | - | |
| 134 | 124 | public Boolean getRecordSip() { |
| 135 | 125 | return recordSip; |
| 136 | 126 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisKeyExpirationEventMessageListener.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.conf.redis; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.conf.UserSetting; | |
| 4 | -import org.springframework.data.redis.connection.RedisConnection; | |
| 5 | -import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; | |
| 6 | -import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 7 | - | |
| 8 | -import java.util.Properties; | |
| 9 | - | |
| 10 | -public class RedisKeyExpirationEventMessageListener extends KeyExpirationEventMessageListener { | |
| 11 | - | |
| 12 | - private UserSetting userSetting; | |
| 13 | - private RedisMessageListenerContainer listenerContainer; | |
| 14 | - private String keyspaceNotificationsConfigParameter = "EA"; | |
| 15 | - | |
| 16 | - public RedisKeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) { | |
| 17 | - super(listenerContainer); | |
| 18 | - this.listenerContainer = listenerContainer; | |
| 19 | - this.userSetting = userSetting; | |
| 20 | - } | |
| 21 | - | |
| 22 | - @Override | |
| 23 | - public void init() { | |
| 24 | - if (!userSetting.getRedisConfig()) { | |
| 25 | - // 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用 | |
| 26 | - setKeyspaceNotificationsConfigParameter(""); | |
| 27 | - }else { | |
| 28 | - | |
| 29 | - RedisConnection connection = this.listenerContainer.getConnectionFactory().getConnection(); | |
| 30 | - Properties config = connection.getConfig("notify-keyspace-events"); | |
| 31 | - try { | |
| 32 | - if (!keyspaceNotificationsConfigParameter.equals(config.getProperty("notify-keyspace-events"))) { | |
| 33 | - connection.setConfig("notify-keyspace-events", keyspaceNotificationsConfigParameter); | |
| 34 | - } | |
| 35 | - } finally { | |
| 36 | - connection.close(); | |
| 37 | - } | |
| 38 | - } | |
| 39 | - super.init(); | |
| 40 | - } | |
| 41 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
| ... | ... | @@ -56,7 +56,7 @@ public class SipLayer{ |
| 56 | 56 | * gov/nist/javax/sip/SipStackImpl.class |
| 57 | 57 | */ |
| 58 | 58 | if (logger.isDebugEnabled()) { |
| 59 | - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true"); | |
| 59 | + properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); | |
| 60 | 60 | } |
| 61 | 61 | // 接收所有notify请求,即使没有订阅 |
| 62 | 62 | properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); |
| ... | ... | @@ -68,14 +68,13 @@ public class SipLayer{ |
| 68 | 68 | properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60"); |
| 69 | 69 | |
| 70 | 70 | /** |
| 71 | - * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = | |
| 72 | - * 0; public static final int TRACE_MESSAGES = 16; public static final int | |
| 73 | - * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32; | |
| 71 | + * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE | |
| 74 | 72 | */ |
| 75 | - if (logger.isDebugEnabled()) { | |
| 76 | - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); | |
| 77 | - } | |
| 78 | - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO"); | |
| 73 | + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); | |
| 74 | +// if (logger.isDebugEnabled()) { | |
| 75 | +// properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); | |
| 76 | +// } | |
| 77 | + | |
| 79 | 78 | sipStack = (SipStackImpl) sipFactory.createSipStack(properties); |
| 80 | 79 | |
| 81 | 80 | return sipStack; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
| ... | ... | @@ -84,7 +84,7 @@ public class ParentPlatform { |
| 84 | 84 | * 注册周期 (秒) |
| 85 | 85 | */ |
| 86 | 86 | @Schema(description = "注册周期 (秒)") |
| 87 | - private String expires; | |
| 87 | + private int expires; | |
| 88 | 88 | |
| 89 | 89 | /** |
| 90 | 90 | * 心跳周期(秒) |
| ... | ... | @@ -286,11 +286,11 @@ public class ParentPlatform { |
| 286 | 286 | this.password = password; |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | - public String getExpires() { | |
| 289 | + public int getExpires() { | |
| 290 | 290 | return expires; |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | - public void setExpires(String expires) { | |
| 293 | + public void setExpires(int expires) { | |
| 294 | 294 | this.expires = expires; |
| 295 | 295 | } |
| 296 | 296 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
| ... | ... | @@ -2,9 +2,6 @@ package com.genersoft.iot.vmp.gb28181.event; |
| 2 | 2 | |
| 3 | 3 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; |
| 5 | -import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; | |
| 6 | -import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformCycleRegisterEvent; | |
| 7 | -import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; | |
| 8 | 5 | import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; |
| 9 | 6 | import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; |
| 10 | 7 | import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; |
| ... | ... | @@ -31,36 +28,6 @@ public class EventPublisher { |
| 31 | 28 | |
| 32 | 29 | @Autowired |
| 33 | 30 | private ApplicationEventPublisher applicationEventPublisher; |
| 34 | - | |
| 35 | - /** | |
| 36 | - * 平台心跳到期事件 | |
| 37 | - * @param platformGbId | |
| 38 | - */ | |
| 39 | - public void platformKeepaliveExpireEventPublish(String platformGbId){ | |
| 40 | - PlatformKeepaliveExpireEvent platformKeepaliveExpireEvent = new PlatformKeepaliveExpireEvent(this); | |
| 41 | - platformKeepaliveExpireEvent.setPlatformGbID(platformGbId); | |
| 42 | - applicationEventPublisher.publishEvent(platformKeepaliveExpireEvent); | |
| 43 | - } | |
| 44 | - | |
| 45 | - /** | |
| 46 | - * 平台未注册事件 | |
| 47 | - * @param platformGbId | |
| 48 | - */ | |
| 49 | - public void platformNotRegisterEventPublish(String platformGbId){ | |
| 50 | - PlatformNotRegisterEvent platformNotRegisterEvent = new PlatformNotRegisterEvent(this); | |
| 51 | - platformNotRegisterEvent.setPlatformGbID(platformGbId); | |
| 52 | - applicationEventPublisher.publishEvent(platformNotRegisterEvent); | |
| 53 | - } | |
| 54 | - | |
| 55 | - /** | |
| 56 | - * 平台周期注册事件 | |
| 57 | - * @param paltformGbId | |
| 58 | - */ | |
| 59 | - public void platformRegisterCycleEventPublish(String paltformGbId) { | |
| 60 | - PlatformCycleRegisterEvent platformCycleRegisterEvent = new PlatformCycleRegisterEvent(this); | |
| 61 | - platformCycleRegisterEvent.setPlatformGbID(paltformGbId); | |
| 62 | - applicationEventPublisher.publishEvent(platformCycleRegisterEvent); | |
| 63 | - } | |
| 64 | 31 | |
| 65 | 32 | /** |
| 66 | 33 | * 设备报警事件 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
| ... | ... | @@ -59,9 +59,25 @@ public class SipSubscribe { |
| 59 | 59 | void response(EventResult eventResult); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | + /** | |
| 63 | + * | |
| 64 | + */ | |
| 65 | + public enum EventResultType{ | |
| 66 | + // 超时 | |
| 67 | + timeout, | |
| 68 | + // 回复 | |
| 69 | + response, | |
| 70 | + // 事务已结束 | |
| 71 | + transactionTerminated, | |
| 72 | + // 会话已结束 | |
| 73 | + dialogTerminated, | |
| 74 | + // 设备未找到 | |
| 75 | + deviceNotFoundEvent | |
| 76 | + } | |
| 77 | + | |
| 62 | 78 | public static class EventResult<EventObject>{ |
| 63 | 79 | public int statusCode; |
| 64 | - public String type; | |
| 80 | + public EventResultType type; | |
| 65 | 81 | public String msg; |
| 66 | 82 | public String callId; |
| 67 | 83 | public Dialog dialog; |
| ... | ... | @@ -76,7 +92,7 @@ public class SipSubscribe { |
| 76 | 92 | ResponseEvent responseEvent = (ResponseEvent)event; |
| 77 | 93 | Response response = responseEvent.getResponse(); |
| 78 | 94 | this.dialog = responseEvent.getDialog(); |
| 79 | - this.type = "response"; | |
| 95 | + this.type = EventResultType.response; | |
| 80 | 96 | if (response != null) { |
| 81 | 97 | this.msg = response.getReasonPhrase(); |
| 82 | 98 | this.statusCode = response.getStatusCode(); |
| ... | ... | @@ -85,28 +101,28 @@ public class SipSubscribe { |
| 85 | 101 | |
| 86 | 102 | }else if (event instanceof TimeoutEvent) { |
| 87 | 103 | TimeoutEvent timeoutEvent = (TimeoutEvent)event; |
| 88 | - this.type = "timeout"; | |
| 104 | + this.type = EventResultType.timeout; | |
| 89 | 105 | this.msg = "消息超时未回复"; |
| 90 | 106 | this.statusCode = -1024; |
| 91 | 107 | this.dialog = timeoutEvent.getClientTransaction().getDialog(); |
| 92 | 108 | this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null; |
| 93 | 109 | }else if (event instanceof TransactionTerminatedEvent) { |
| 94 | 110 | TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event; |
| 95 | - this.type = "transactionTerminated"; | |
| 111 | + this.type = EventResultType.transactionTerminated; | |
| 96 | 112 | this.msg = "事务已结束"; |
| 97 | 113 | this.statusCode = -1024; |
| 98 | 114 | this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId(); |
| 99 | 115 | this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog(); |
| 100 | 116 | }else if (event instanceof DialogTerminatedEvent) { |
| 101 | 117 | DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event; |
| 102 | - this.type = "dialogTerminated"; | |
| 118 | + this.type = EventResultType.dialogTerminated; | |
| 103 | 119 | this.msg = "会话已结束"; |
| 104 | 120 | this.statusCode = -1024; |
| 105 | 121 | this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); |
| 106 | 122 | this.dialog = dialogTerminatedEvent.getDialog(); |
| 107 | 123 | }else if (event instanceof DeviceNotFoundEvent) { |
| 108 | 124 | DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event; |
| 109 | - this.type = "deviceNotFoundEvent"; | |
| 125 | + this.type = EventResultType.deviceNotFoundEvent; | |
| 110 | 126 | this.msg = "设备未找到"; |
| 111 | 127 | this.statusCode = -1024; |
| 112 | 128 | this.dialog = deviceNotFoundEvent.getDialog(); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.offline; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.conf.UserSetting; | |
| 4 | -import com.genersoft.iot.vmp.conf.redis.RedisKeyExpirationEventMessageListener; | |
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 7 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 8 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 9 | -import org.slf4j.Logger; | |
| 10 | -import org.slf4j.LoggerFactory; | |
| 11 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 12 | -import org.springframework.data.redis.connection.Message; | |
| 13 | -import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 14 | -import org.springframework.stereotype.Component; | |
| 15 | - | |
| 16 | -import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 17 | -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 18 | - | |
| 19 | -/** | |
| 20 | - * 设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 | |
| 21 | - * @author swwheihei | |
| 22 | - */ | |
| 23 | -@Component | |
| 24 | -public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener { | |
| 25 | - | |
| 26 | - private Logger logger = LoggerFactory.getLogger(KeepaliveTimeoutListenerForPlatform.class); | |
| 27 | - | |
| 28 | - @Autowired | |
| 29 | - private EventPublisher publisher; | |
| 30 | - | |
| 31 | - @Autowired | |
| 32 | - private UserSetting userSetting; | |
| 33 | - | |
| 34 | - @Autowired | |
| 35 | - private SipSubscribe sipSubscribe; | |
| 36 | - | |
| 37 | - @Autowired | |
| 38 | - private IVideoManagerStorage storager; | |
| 39 | - | |
| 40 | - public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) { | |
| 41 | - super(listenerContainer, userSetting); | |
| 42 | - } | |
| 43 | - | |
| 44 | - | |
| 45 | - /** | |
| 46 | - * 监听失效的key | |
| 47 | - * @param message | |
| 48 | - * @param pattern | |
| 49 | - */ | |
| 50 | - @Override | |
| 51 | - public void onMessage(Message message, byte[] pattern) { | |
| 52 | - // 获取失效的key | |
| 53 | - String expiredKey = message.toString(); | |
| 54 | - // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线 | |
| 55 | - String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_"; | |
| 56 | - String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_"; | |
| 57 | - String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_"; | |
| 58 | - if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) { | |
| 59 | - String platformGbId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length()); | |
| 60 | - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId); | |
| 61 | - if (platform != null) { | |
| 62 | - publisher.platformKeepaliveExpireEventPublish(platformGbId); | |
| 63 | - } | |
| 64 | - }else if (expiredKey.startsWith(PLATFORM_REGISTER_PREFIX)) { | |
| 65 | - String platformGbId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length()); | |
| 66 | - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId); | |
| 67 | - if (platform != null) { | |
| 68 | - publisher.platformRegisterCycleEventPublish(platformGbId); | |
| 69 | - } | |
| 70 | - }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) { | |
| 71 | - String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length()); | |
| 72 | - if (sipSubscribe.getErrorSubscribe(callId) != null) { | |
| 73 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); | |
| 74 | - eventResult.callId = callId; | |
| 75 | - eventResult.msg = "注册超时"; | |
| 76 | - eventResult.type = "register timeout"; | |
| 77 | - sipSubscribe.getErrorSubscribe(callId).response(eventResult); | |
| 78 | - } | |
| 79 | - } | |
| 80 | - } | |
| 81 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEvent.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire; | |
| 2 | - | |
| 3 | -import org.springframework.context.ApplicationEvent; | |
| 4 | - | |
| 5 | -/** | |
| 6 | - * 平台心跳超时事件 | |
| 7 | - */ | |
| 8 | -public class PlatformKeepaliveExpireEvent extends ApplicationEvent { | |
| 9 | - | |
| 10 | - /** | |
| 11 | - * Add default serial version ID | |
| 12 | - */ | |
| 13 | - private static final long serialVersionUID = 1L; | |
| 14 | - | |
| 15 | - private String platformGbID; | |
| 16 | - | |
| 17 | - public PlatformKeepaliveExpireEvent(Object source) { | |
| 18 | - super(source); | |
| 19 | - } | |
| 20 | - | |
| 21 | - public String getPlatformGbID() { | |
| 22 | - return platformGbID; | |
| 23 | - } | |
| 24 | - | |
| 25 | - public void setPlatformGbID(String platformGbID) { | |
| 26 | - this.platformGbID = platformGbID; | |
| 27 | - } | |
| 28 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; | |
| 5 | -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 6 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 7 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 8 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 9 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 10 | -import org.jetbrains.annotations.NotNull; | |
| 11 | -import org.slf4j.Logger; | |
| 12 | -import org.slf4j.LoggerFactory; | |
| 13 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 14 | -import org.springframework.context.ApplicationListener; | |
| 15 | -import org.springframework.stereotype.Component; | |
| 16 | - | |
| 17 | -import javax.sip.message.Response; | |
| 18 | - | |
| 19 | -/** | |
| 20 | - * @description: 平台心跳超时事件 | |
| 21 | - * @author: panll | |
| 22 | - * @date: 2020年11月5日 10:00 | |
| 23 | - */ | |
| 24 | -@Component | |
| 25 | -public class PlatformKeepaliveExpireEventLister implements ApplicationListener<PlatformKeepaliveExpireEvent> { | |
| 26 | - | |
| 27 | - | |
| 28 | - private final static Logger logger = LoggerFactory.getLogger(PlatformKeepaliveExpireEventLister.class); | |
| 29 | - | |
| 30 | - @Autowired | |
| 31 | - private IVideoManagerStorage storager; | |
| 32 | - | |
| 33 | - @Autowired | |
| 34 | - private IRedisCatchStorage redisCatchStorage; | |
| 35 | - | |
| 36 | - @Autowired | |
| 37 | - private ISIPCommanderForPlatform sipCommanderForPlatform; | |
| 38 | - | |
| 39 | - @Autowired | |
| 40 | - private SipSubscribe sipSubscribe; | |
| 41 | - | |
| 42 | - @Autowired | |
| 43 | - private EventPublisher publisher; | |
| 44 | - | |
| 45 | - @Override | |
| 46 | - public void onApplicationEvent(@NotNull PlatformKeepaliveExpireEvent event) { | |
| 47 | - | |
| 48 | - if (logger.isDebugEnabled()) { | |
| 49 | - logger.debug("平台心跳到期事件事件触发,平台国标ID:" + event.getPlatformGbID()); | |
| 50 | - } | |
| 51 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID()); | |
| 52 | - ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(event.getPlatformGbID()); | |
| 53 | - if (parentPlatformCatch == null) { | |
| 54 | - return; | |
| 55 | - } | |
| 56 | - if (parentPlatform == null) { | |
| 57 | - logger.debug("平台心跳到期事件事件触发,但平台已经删除!!! 平台国标ID:" + event.getPlatformGbID()); | |
| 58 | - return; | |
| 59 | - } | |
| 60 | - parentPlatformCatch.setParentPlatform(parentPlatform); | |
| 61 | - // 发送心跳 | |
| 62 | - if (parentPlatformCatch.getKeepAliveReply() >= 3) { | |
| 63 | - // 有3次未收到心跳回复, 设置平台状态为离线, 开始重新注册 | |
| 64 | - logger.warn("有3次未收到心跳回复,标记设置平台状态为离线, 并重新注册 平台国标ID:" + event.getPlatformGbID()); | |
| 65 | - storager.updateParentPlatformStatus(event.getPlatformGbID(), false); | |
| 66 | - publisher.platformNotRegisterEventPublish(event.getPlatformGbID()); | |
| 67 | - parentPlatformCatch.setKeepAliveReply(0); | |
| 68 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 69 | - }else { | |
| 70 | - // 再次发送心跳 | |
| 71 | - String callId = sipCommanderForPlatform.keepalive(parentPlatform); | |
| 72 | - | |
| 73 | - parentPlatformCatch.setKeepAliveReply( parentPlatformCatch.getKeepAliveReply() + 1); | |
| 74 | - // 存储心跳信息, 并设置状态为未回复, 如果多次过期仍未收到回复,则认为上级平台已经离线 | |
| 75 | - redisCatchStorage.updatePlatformKeepalive(parentPlatform); | |
| 76 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 77 | - | |
| 78 | - sipSubscribe.addOkSubscribe(callId, (SipSubscribe.EventResult eventResult) ->{ | |
| 79 | - if (eventResult.statusCode == Response.OK) { | |
| 80 | - // 收到心跳响应信息, | |
| 81 | - parentPlatformCatch.setKeepAliveReply(0); | |
| 82 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 83 | - } | |
| 84 | - } ); | |
| 85 | - } | |
| 86 | - } | |
| 87 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformCycleRegisterEvent.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.platformNotRegister; | |
| 2 | - | |
| 3 | -import org.springframework.context.ApplicationEvent; | |
| 4 | - | |
| 5 | -public class PlatformCycleRegisterEvent extends ApplicationEvent { | |
| 6 | - /** | |
| 7 | - * Add default serial version ID | |
| 8 | - */ | |
| 9 | - private static final long serialVersionUID = 1L; | |
| 10 | - | |
| 11 | - private String platformGbID; | |
| 12 | - | |
| 13 | - public String getPlatformGbID() { | |
| 14 | - return platformGbID; | |
| 15 | - } | |
| 16 | - | |
| 17 | - public void setPlatformGbID(String platformGbID) { | |
| 18 | - this.platformGbID = platformGbID; | |
| 19 | - } | |
| 20 | - | |
| 21 | - public PlatformCycleRegisterEvent(Object source) { | |
| 22 | - super(source); | |
| 23 | - } | |
| 24 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformCycleRegisterEventLister.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.platformNotRegister; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 5 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 6 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 7 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 8 | -import org.slf4j.Logger; | |
| 9 | -import org.slf4j.LoggerFactory; | |
| 10 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 11 | -import org.springframework.context.ApplicationListener; | |
| 12 | -import org.springframework.stereotype.Component; | |
| 13 | - | |
| 14 | -import java.util.Timer; | |
| 15 | -import java.util.TimerTask; | |
| 16 | - | |
| 17 | -@Component | |
| 18 | -public class PlatformCycleRegisterEventLister implements ApplicationListener<PlatformCycleRegisterEvent> { | |
| 19 | - | |
| 20 | - private final static Logger logger = LoggerFactory.getLogger(PlatformCycleRegisterEventLister.class); | |
| 21 | - | |
| 22 | - @Autowired | |
| 23 | - private IVideoManagerStorage storager; | |
| 24 | - @Autowired | |
| 25 | - private ISIPCommanderForPlatform sipCommanderFroPlatform; | |
| 26 | - @Autowired | |
| 27 | - private DynamicTask dynamicTask; | |
| 28 | - | |
| 29 | - @Override | |
| 30 | - public void onApplicationEvent(PlatformCycleRegisterEvent event) { | |
| 31 | - logger.info("上级平台周期注册事件"); | |
| 32 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID()); | |
| 33 | - if (parentPlatform == null) { | |
| 34 | - logger.info("[ 平台未注册事件 ] 平台已经删除!!! 平台国标ID:" + event.getPlatformGbID()); | |
| 35 | - return; | |
| 36 | - } | |
| 37 | - String taskKey = "platform-cycle-register" + parentPlatform.getServerGBId();; | |
| 38 | - SipSubscribe.Event okEvent = (responseEvent)->{ | |
| 39 | - dynamicTask.stop(taskKey); | |
| 40 | - }; | |
| 41 | - dynamicTask.startCron(taskKey, ()->{ | |
| 42 | - logger.info("[平台注册]再次向平台注册,平台国标ID:" + event.getPlatformGbID()); | |
| 43 | - sipCommanderFroPlatform.register(parentPlatform, null, okEvent); | |
| 44 | - }, Integer.parseInt(parentPlatform.getExpires())* 1000); | |
| 45 | - } | |
| 46 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEvent.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.platformNotRegister; | |
| 2 | - | |
| 3 | -import org.springframework.context.ApplicationEvent; | |
| 4 | - | |
| 5 | -public class PlatformNotRegisterEvent extends ApplicationEvent { | |
| 6 | - | |
| 7 | - /** | |
| 8 | - * Add default serial version ID | |
| 9 | - */ | |
| 10 | - private static final long serialVersionUID = 1L; | |
| 11 | - | |
| 12 | - private String platformGbID; | |
| 13 | - | |
| 14 | - public PlatformNotRegisterEvent(Object source) { | |
| 15 | - super(source); | |
| 16 | - } | |
| 17 | - | |
| 18 | - public String getPlatformGbID() { | |
| 19 | - return platformGbID; | |
| 20 | - } | |
| 21 | - | |
| 22 | - public void setPlatformGbID(String platformGbID) { | |
| 23 | - this.platformGbID = platformGbID; | |
| 24 | - } | |
| 25 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.event.platformNotRegister; | |
| 2 | - | |
| 3 | -import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 4 | -import com.genersoft.iot.vmp.conf.SipConfig; | |
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | |
| 7 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 8 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | |
| 9 | -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | |
| 10 | -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 11 | -import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 12 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 13 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 14 | -import org.slf4j.Logger; | |
| 15 | -import org.slf4j.LoggerFactory; | |
| 16 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 17 | -import org.springframework.context.ApplicationListener; | |
| 18 | -import org.springframework.stereotype.Component; | |
| 19 | - | |
| 20 | -import java.util.*; | |
| 21 | - | |
| 22 | -/** | |
| 23 | - * @description: 平台未注册事件,来源有二: | |
| 24 | - * 1、平台新添加 | |
| 25 | - * 2、平台心跳超时 | |
| 26 | - * @author: panll | |
| 27 | - * @date: 2020年11月24日 10:00 | |
| 28 | - */ | |
| 29 | -@Component | |
| 30 | -public class PlatformNotRegisterEventLister implements ApplicationListener<PlatformNotRegisterEvent> { | |
| 31 | - | |
| 32 | - private final static Logger logger = LoggerFactory.getLogger(PlatformNotRegisterEventLister.class); | |
| 33 | - | |
| 34 | - @Autowired | |
| 35 | - private IVideoManagerStorage storager; | |
| 36 | - @Autowired | |
| 37 | - private IRedisCatchStorage redisCatchStorage; | |
| 38 | - @Autowired | |
| 39 | - private IMediaServerService mediaServerService; | |
| 40 | - | |
| 41 | - @Autowired | |
| 42 | - private SIPCommanderFroPlatform sipCommanderFroPlatform; | |
| 43 | - | |
| 44 | - @Autowired | |
| 45 | - private ZLMRTPServerFactory zlmrtpServerFactory; | |
| 46 | - | |
| 47 | - @Autowired | |
| 48 | - private SipConfig config; | |
| 49 | - | |
| 50 | - @Autowired | |
| 51 | - private DynamicTask dynamicTask; | |
| 52 | - | |
| 53 | - // @Autowired | |
| 54 | - // private RedisUtil redis; | |
| 55 | - | |
| 56 | - @Override | |
| 57 | - public void onApplicationEvent(PlatformNotRegisterEvent event) { | |
| 58 | - | |
| 59 | - logger.info("[ 平台未注册事件 ]平台国标ID:" + event.getPlatformGbID()); | |
| 60 | - | |
| 61 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID()); | |
| 62 | - if (parentPlatform == null) { | |
| 63 | - logger.info("[ 平台未注册事件 ] 平台已经删除!!! 平台国标ID:" + event.getPlatformGbID()); | |
| 64 | - return; | |
| 65 | - } | |
| 66 | - // 查询是否有推流, 如果有则都停止 | |
| 67 | - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID()); | |
| 68 | - if (sendRtpItems != null && sendRtpItems.size() > 0) { | |
| 69 | - logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流", event.getPlatformGbID()); | |
| 70 | - for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 71 | - redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId(), null, null); | |
| 72 | - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 73 | - Map<String, Object> param = new HashMap<>(); | |
| 74 | - param.put("vhost", "__defaultVhost__"); | |
| 75 | - param.put("app", sendRtpItem.getApp()); | |
| 76 | - param.put("stream", sendRtpItem.getStreamId()); | |
| 77 | - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | |
| 78 | - } | |
| 79 | - | |
| 80 | - } | |
| 81 | - String taskKey = "platform-not-register-" + parentPlatform.getServerGBId(); | |
| 82 | - SipSubscribe.Event okEvent = (responseEvent)->{ | |
| 83 | - dynamicTask.stop(taskKey); | |
| 84 | - }; | |
| 85 | - dynamicTask.startCron(taskKey, ()->{ | |
| 86 | - logger.info("[平台注册]再次向平台注册,平台国标ID:" + event.getPlatformGbID()); | |
| 87 | - sipCommanderFroPlatform.register(parentPlatform, null, okEvent); | |
| 88 | - }, config.getRegisterTimeInterval()* 1000); | |
| 89 | - } | |
| 90 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
| ... | ... | @@ -30,24 +30,11 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { |
| 30 | 30 | |
| 31 | 31 | @Autowired |
| 32 | 32 | private IVideoManagerStorage storager; |
| 33 | - @Autowired | |
| 34 | - private IRedisCatchStorage redisCatchStorage; | |
| 35 | - @Autowired | |
| 36 | - private IMediaServerService mediaServerService; | |
| 37 | 33 | |
| 38 | 34 | @Autowired |
| 39 | 35 | private SIPCommanderFroPlatform sipCommanderFroPlatform; |
| 40 | 36 | |
| 41 | 37 | @Autowired |
| 42 | - private ZLMRTPServerFactory zlmrtpServerFactory; | |
| 43 | - | |
| 44 | - @Autowired | |
| 45 | - private SipConfig config; | |
| 46 | - | |
| 47 | - @Autowired | |
| 48 | - private UserSetting userSetting; | |
| 49 | - | |
| 50 | - @Autowired | |
| 51 | 38 | private IGbStreamService gbStreamService; |
| 52 | 39 | |
| 53 | 40 | @Autowired | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
| ... | ... | @@ -60,7 +60,6 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { |
| 60 | 60 | // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 |
| 61 | 61 | List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId()); |
| 62 | 62 | if (gbStreams.size() == 0) { |
| 63 | - logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId()); | |
| 64 | 63 | return; |
| 65 | 64 | } |
| 66 | 65 | for (DeviceChannel deviceChannel : gbStreams) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
| ... | ... | @@ -15,7 +15,7 @@ public interface ISIPCommanderForPlatform { |
| 15 | 15 | * @return |
| 16 | 16 | */ |
| 17 | 17 | boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); |
| 18 | - boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain); | |
| 18 | + boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister); | |
| 19 | 19 | |
| 20 | 20 | /** |
| 21 | 21 | * 向上级平台注销 |
| ... | ... | @@ -30,7 +30,7 @@ public interface ISIPCommanderForPlatform { |
| 30 | 30 | * @param parentPlatform |
| 31 | 31 | * @return callId(作为接受回复的判定) |
| 32 | 32 | */ |
| 33 | - String keepalive(ParentPlatform parentPlatform); | |
| 33 | + String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); | |
| 34 | 34 | |
| 35 | 35 | |
| 36 | 36 | /** | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
| ... | ... | @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; |
| 3 | 3 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; |
| 6 | +import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils; | |
| 6 | 7 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 7 | 8 | import gov.nist.javax.sip.message.MessageFactoryImpl; |
| 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; |
| ... | ... | @@ -75,7 +76,7 @@ public class SIPRequestHeaderPlarformProvider { |
| 75 | 76 | } |
| 76 | 77 | |
| 77 | 78 | |
| 78 | - public Request createRegisterRequest(@NotNull ParentPlatform platform, long CSeq, String fromTag, String viaTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 79 | + public Request createRegisterRequest(@NotNull ParentPlatform platform, long CSeq, String fromTag, String viaTag, CallIdHeader callIdHeader, boolean isRegister) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 79 | 80 | Request request = null; |
| 80 | 81 | String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort(); |
| 81 | 82 | //请求行 |
| ... | ... | @@ -109,18 +110,20 @@ public class SIPRequestHeaderPlarformProvider { |
| 109 | 110 | .createSipURI(platform.getDeviceGBId(), sipAddress)); |
| 110 | 111 | request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); |
| 111 | 112 | |
| 112 | - ExpiresHeader expires = sipFactory.createHeaderFactory().createExpiresHeader(Integer.parseInt(platform.getExpires())); | |
| 113 | + ExpiresHeader expires = sipFactory.createHeaderFactory().createExpiresHeader(isRegister ? platform.getExpires() : 0); | |
| 113 | 114 | request.addHeader(expires); |
| 114 | 115 | |
| 116 | + UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory); | |
| 117 | + request.addHeader(userAgentHeader); | |
| 115 | 118 | |
| 116 | 119 | return request; |
| 117 | 120 | } |
| 118 | 121 | |
| 119 | 122 | public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String viaTag, |
| 120 | - String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader) throws ParseException, PeerUnavailableException, InvalidArgumentException { | |
| 123 | + String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader, boolean isRegister) throws ParseException, PeerUnavailableException, InvalidArgumentException { | |
| 121 | 124 | |
| 122 | 125 | |
| 123 | - Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader); | |
| 126 | + Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader, isRegister); | |
| 124 | 127 | SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| 125 | 128 | if (www == null) { |
| 126 | 129 | AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest"); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| ... | ... | @@ -12,6 +12,7 @@ import javax.sip.message.Request; |
| 12 | 12 | |
| 13 | 13 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 14 | 14 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 15 | +import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils; | |
| 15 | 16 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 16 | 17 | import gov.nist.javax.sip.SipProviderImpl; |
| 17 | 18 | import gov.nist.javax.sip.SipStackImpl; |
| ... | ... | @@ -266,15 +267,7 @@ public class SIPRequestHeaderProvider { |
| 266 | 267 | Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() |
| 267 | 268 | .createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort())); |
| 268 | 269 | infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); |
| 269 | - List<String> agentParam = new ArrayList<>(); | |
| 270 | - agentParam.add("wvp-pro"); | |
| 271 | - // TODO 添加版本信息以及日期 | |
| 272 | - UserAgentHeader userAgentHeader = null; | |
| 273 | - try { | |
| 274 | - userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); | |
| 275 | - } catch (ParseException e) { | |
| 276 | - throw new RuntimeException(e); | |
| 277 | - } | |
| 270 | + UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory); | |
| 278 | 271 | infoRequest.addHeader(userAgentHeader); |
| 279 | 272 | |
| 280 | 273 | ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| ... | ... | @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 10 | 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 11 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 12 | 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; |
| 13 | +import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils; | |
| 13 | 14 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| 14 | 15 | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| 15 | 16 | import com.genersoft.iot.vmp.media.zlm.dto.HookType; |
| ... | ... | @@ -740,15 +741,7 @@ public class SIPCommander implements ISIPCommander { |
| 740 | 741 | // 增加Contact header |
| 741 | 742 | Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort())); |
| 742 | 743 | byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); |
| 743 | - List<String> agentParam = new ArrayList<>(); | |
| 744 | - agentParam.add("wvp-pro"); | |
| 745 | - // TODO 添加版本信息以及日期 | |
| 746 | - UserAgentHeader userAgentHeader = null; | |
| 747 | - try { | |
| 748 | - userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); | |
| 749 | - } catch (ParseException e) { | |
| 750 | - throw new RuntimeException(e); | |
| 751 | - } | |
| 744 | + UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory); | |
| 752 | 745 | byeRequest.addHeader(userAgentHeader); |
| 753 | 746 | ClientTransaction clientTransaction = null; |
| 754 | 747 | if("TCP".equals(protocol)) { |
| ... | ... | @@ -1677,14 +1670,11 @@ public class SIPCommander implements ISIPCommander { |
| 1677 | 1670 | clientTransaction = udpSipProvider.getNewClientTransaction(request); |
| 1678 | 1671 | } |
| 1679 | 1672 | if (request.getHeader(UserAgentHeader.NAME) == null) { |
| 1680 | - List<String> agentParam = new ArrayList<>(); | |
| 1681 | - agentParam.add("wvp-pro"); | |
| 1682 | - // TODO 添加版本信息以及日期 | |
| 1683 | 1673 | UserAgentHeader userAgentHeader = null; |
| 1684 | 1674 | try { |
| 1685 | - userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); | |
| 1675 | + userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory); | |
| 1686 | 1676 | } catch (ParseException e) { |
| 1687 | - throw new RuntimeException(e); | |
| 1677 | + logger.error("添加UserAgentHeader失败", e); | |
| 1688 | 1678 | } |
| 1689 | 1679 | request.addHeader(userAgentHeader); |
| 1690 | 1680 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| ... | ... | @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; |
| 7 | +import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | |
| 7 | 8 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 8 | 9 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 9 | 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| ... | ... | @@ -75,28 +76,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 75 | 76 | |
| 76 | 77 | @Override |
| 77 | 78 | public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { |
| 78 | - return register(parentPlatform, null, null, errorEvent, okEvent, false); | |
| 79 | + return register(parentPlatform, null, null, errorEvent, okEvent, false, true); | |
| 79 | 80 | } |
| 80 | 81 | |
| 81 | 82 | @Override |
| 82 | 83 | public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { |
| 83 | - ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | |
| 84 | - parentPlatform.setExpires("0"); | |
| 85 | - if (parentPlatformCatch != null) { | |
| 86 | - parentPlatformCatch.setParentPlatform(parentPlatform); | |
| 87 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 88 | - } | |
| 89 | - return register(parentPlatform, null, null, errorEvent, okEvent, false); | |
| 84 | + return register(parentPlatform, null, null, errorEvent, okEvent, false, false); | |
| 90 | 85 | } |
| 91 | 86 | |
| 92 | 87 | @Override |
| 93 | 88 | public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, |
| 94 | - SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) { | |
| 89 | + SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) { | |
| 95 | 90 | try { |
| 96 | 91 | Request request; |
| 97 | 92 | String tm = Long.toString(System.currentTimeMillis()); |
| 98 | 93 | if (!registerAgain ) { |
| 99 | - // //callid | |
| 100 | 94 | CallIdHeader callIdHeader = null; |
| 101 | 95 | if(parentPlatform.getTransport().equals("TCP")) { |
| 102 | 96 | callIdHeader = tcpSipProvider.getNewCallId(); |
| ... | ... | @@ -107,10 +101,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 107 | 101 | |
| 108 | 102 | request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, |
| 109 | 103 | redisCatchStorage.getCSEQ(), "FromRegister" + tm, |
| 110 | - "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), callIdHeader); | |
| 104 | + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), callIdHeader, isRegister); | |
| 111 | 105 | // 将 callid 写入缓存, 等注册成功可以更新状态 |
| 112 | 106 | String callIdFromHeader = callIdHeader.getCallId(); |
| 113 | - redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, parentPlatform.getServerGBId()); | |
| 107 | + redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister)); | |
| 114 | 108 | |
| 115 | 109 | sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{ |
| 116 | 110 | if (event != null) { |
| ... | ... | @@ -127,7 +121,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 127 | 121 | }else { |
| 128 | 122 | CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() |
| 129 | 123 | : udpSipProvider.getNewCallId(); |
| 130 | - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, "FromRegister" + tm, null, callId, www, callIdHeader); | |
| 124 | + request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, "FromRegister" + tm, null, callId, www, callIdHeader, isRegister); | |
| 131 | 125 | } |
| 132 | 126 | |
| 133 | 127 | transmitRequest(parentPlatform, request, null, okEvent); |
| ... | ... | @@ -145,7 +139,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 145 | 139 | } |
| 146 | 140 | |
| 147 | 141 | @Override |
| 148 | - public String keepalive(ParentPlatform parentPlatform) { | |
| 142 | + public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { | |
| 149 | 143 | String callId = null; |
| 150 | 144 | try { |
| 151 | 145 | String characterSet = parentPlatform.getCharacterSet(); |
| ... | ... | @@ -168,7 +162,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 168 | 162 | UUID.randomUUID().toString().replace("-", ""), |
| 169 | 163 | null, |
| 170 | 164 | callIdHeader); |
| 171 | - transmitRequest(parentPlatform, request); | |
| 165 | + transmitRequest(parentPlatform, request, errorEvent, okEvent); | |
| 172 | 166 | callId = callIdHeader.getCallId(); |
| 173 | 167 | } catch (ParseException | InvalidArgumentException | SipException e) { |
| 174 | 168 | e.printStackTrace(); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
| ... | ... | @@ -59,6 +59,9 @@ public abstract class SIPRequestProcessorParent { |
| 59 | 59 | public ServerTransaction getServerTransaction(RequestEvent evt) { |
| 60 | 60 | Request request = evt.getRequest(); |
| 61 | 61 | ServerTransaction serverTransaction = evt.getServerTransaction(); |
| 62 | + if (serverTransaction != null) { | |
| 63 | + System.out.println(serverTransaction.getState().toString()); | |
| 64 | + } | |
| 62 | 65 | // 判断TCP还是UDP |
| 63 | 66 | boolean isTcp = false; |
| 64 | 67 | ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
| ... | ... | @@ -86,6 +89,8 @@ public abstract class SIPRequestProcessorParent { |
| 86 | 89 | logger.error(e.getMessage()); |
| 87 | 90 | } catch (TransactionUnavailableException e) { |
| 88 | 91 | logger.error(e.getMessage()); |
| 92 | + }finally { | |
| 93 | + | |
| 89 | 94 | } |
| 90 | 95 | } |
| 91 | 96 | return serverTransaction; |
| ... | ... | @@ -182,6 +187,10 @@ public abstract class SIPRequestProcessorParent { |
| 182 | 187 | sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() |
| 183 | 188 | )); |
| 184 | 189 | response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); |
| 190 | + ServerTransaction serverTransaction = getServerTransaction(evt); | |
| 191 | + if (serverTransaction == null) { | |
| 192 | + | |
| 193 | + } | |
| 185 | 194 | getServerTransaction(evt).sendResponse(response); |
| 186 | 195 | } |
| 187 | 196 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
| ... | ... | @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 7 | 7 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 8 | 8 | import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; |
| 9 | +import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils; | |
| 9 | 10 | import gov.nist.javax.sip.ResponseEventExt; |
| 10 | 11 | import gov.nist.javax.sip.message.SIPResponse; |
| 11 | 12 | import gov.nist.javax.sip.stack.SIPDialog; |
| ... | ... | @@ -103,15 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { |
| 103 | 104 | } |
| 104 | 105 | requestURI.setPort(event.getRemotePort()); |
| 105 | 106 | reqAck.setRequestURI(requestURI); |
| 106 | - List<String> agentParam = new ArrayList<>(); | |
| 107 | - agentParam.add("wvp-pro"); | |
| 108 | - // TODO 添加版本信息以及日期 | |
| 109 | - UserAgentHeader userAgentHeader = null; | |
| 110 | - try { | |
| 111 | - userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); | |
| 112 | - } catch (ParseException e) { | |
| 113 | - throw new RuntimeException(e); | |
| 114 | - } | |
| 107 | + UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory); | |
| 115 | 108 | reqAck.addHeader(userAgentHeader); |
| 116 | 109 | Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort())); |
| 117 | 110 | reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
| ... | ... | @@ -6,8 +6,10 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 7 | 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 8 | 8 | import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; |
| 9 | +import com.genersoft.iot.vmp.service.IPlatformService; | |
| 9 | 10 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 10 | 11 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 12 | +import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | |
| 11 | 13 | import org.slf4j.Logger; |
| 12 | 14 | import org.slf4j.LoggerFactory; |
| 13 | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| ... | ... | @@ -44,6 +46,9 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { |
| 44 | 46 | @Autowired |
| 45 | 47 | private SubscribeHolder subscribeHolder; |
| 46 | 48 | |
| 49 | + @Autowired | |
| 50 | + private IPlatformService platformService; | |
| 51 | + | |
| 47 | 52 | @Override |
| 48 | 53 | public void afterPropertiesSet() throws Exception { |
| 49 | 54 | // 添加消息处理的订阅 |
| ... | ... | @@ -60,48 +65,39 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { |
| 60 | 65 | Response response = evt.getResponse(); |
| 61 | 66 | CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME); |
| 62 | 67 | String callId = callIdHeader.getCallId(); |
| 63 | - | |
| 64 | - String platformGBId = redisCatchStorage.queryPlatformRegisterInfo(callId); | |
| 65 | - if (platformGBId == null) { | |
| 66 | - logger.info(String.format("未找到callId: %s 的注册/注销平台id", callId )); | |
| 68 | + PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId); | |
| 69 | + if (platformRegisterInfo == null) { | |
| 70 | + logger.info(String.format("[国标级联]未找到callId: %s 的注册/注销平台id", callId )); | |
| 67 | 71 | return; |
| 68 | 72 | } |
| 69 | 73 | |
| 70 | - ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId); | |
| 74 | + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformRegisterInfo.getPlatformId()); | |
| 71 | 75 | if (parentPlatformCatch == null) { |
| 72 | - logger.warn(String.format("[收到注册/注销%S请求]平台:%s,但是平台缓存信息未查询到!!!", response.getStatusCode(),platformGBId)); | |
| 76 | + logger.warn(String.format("[国标级联]收到注册/注销%S请求,平台:%s,但是平台缓存信息未查询到!!!", response.getStatusCode(),platformRegisterInfo.getPlatformId())); | |
| 73 | 77 | return; |
| 74 | 78 | } |
| 75 | - String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "注销" : "注册"; | |
| 76 | - logger.info(String.format("[%s %S响应]%s ", action, response.getStatusCode(), platformGBId )); | |
| 79 | + | |
| 80 | + String action = platformRegisterInfo.isRegister() ? "注册" : "注销"; | |
| 81 | + logger.info(String.format("[国标级联]%s %S响应,%s ", action, response.getStatusCode(), platformRegisterInfo.getPlatformId() )); | |
| 77 | 82 | ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform(); |
| 78 | 83 | if (parentPlatform == null) { |
| 79 | - logger.warn(String.format("收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformGBId, action, response.getStatusCode())); | |
| 84 | + logger.warn(String.format("[国标级联]收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformRegisterInfo.getPlatformId(), action, response.getStatusCode())); | |
| 80 | 85 | return; |
| 81 | 86 | } |
| 82 | 87 | |
| 83 | - if (response.getStatusCode() == 401) { | |
| 88 | + if (response.getStatusCode() == Response.UNAUTHORIZED) { | |
| 84 | 89 | WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); |
| 85 | - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true); | |
| 86 | - }else if (response.getStatusCode() == 200){ | |
| 87 | - // 注册/注销成功 | |
| 88 | - logger.info(String.format("%s %s成功", platformGBId, action)); | |
| 89 | - redisCatchStorage.delPlatformRegisterInfo(callId); | |
| 90 | - redisCatchStorage.delPlatformCatchInfo(platformGBId); | |
| 91 | - // 取回Expires设置,避免注销过程中被置为0 | |
| 92 | - ParentPlatform parentPlatformTmp = storager.queryParentPlatByServerGBId(platformGBId); | |
| 93 | - if (parentPlatformTmp != null) { | |
| 94 | - parentPlatformTmp.setStatus("注册".equals(action)); | |
| 95 | - redisCatchStorage.updatePlatformRegister(parentPlatformTmp); | |
| 96 | - redisCatchStorage.updatePlatformKeepalive(parentPlatformTmp); | |
| 97 | - parentPlatformCatch.setParentPlatform(parentPlatformTmp); | |
| 98 | - } | |
| 99 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 100 | - storager.updateParentPlatformStatus(platformGBId, "注册".equals(action)); | |
| 101 | - if ("注销".equals(action)) { | |
| 102 | - subscribeHolder.removeCatalogSubscribe(platformGBId); | |
| 103 | - subscribeHolder.removeMobilePositionSubscribe(platformGBId); | |
| 90 | + sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister()); | |
| 91 | + }else if (response.getStatusCode() == Response.OK){ | |
| 92 | + | |
| 93 | + if (platformRegisterInfo.isRegister()) { | |
| 94 | + platformService.online(parentPlatform); | |
| 95 | + }else { | |
| 96 | + platformService.offline(parentPlatform); | |
| 104 | 97 | } |
| 98 | + | |
| 99 | + // 注册/注销成功移除缓存的信息 | |
| 100 | + redisCatchStorage.delPlatformRegisterInfo(callId); | |
| 105 | 101 | } |
| 106 | 102 | } |
| 107 | 103 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/utils/HeaderUtils.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.utils; | |
| 2 | + | |
| 3 | +import javax.sip.PeerUnavailableException; | |
| 4 | +import javax.sip.SipFactory; | |
| 5 | +import javax.sip.header.UserAgentHeader; | |
| 6 | +import java.text.ParseException; | |
| 7 | +import java.util.ArrayList; | |
| 8 | +import java.util.List; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 生成header的工具类 | |
| 12 | + * @author lin | |
| 13 | + */ | |
| 14 | +public class HeaderUtils { | |
| 15 | + | |
| 16 | + public static UserAgentHeader createUserAgentHeader(SipFactory sipFactory) throws PeerUnavailableException, ParseException { | |
| 17 | + List<String> agentParam = new ArrayList<>(); | |
| 18 | + agentParam.add("WVP PRO"); | |
| 19 | + // TODO 添加版本信息以及日期 | |
| 20 | + return sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); | |
| 21 | + } | |
| 22 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
| ... | ... | @@ -50,7 +50,7 @@ public class AssistRESTfulUtils { |
| 50 | 50 | if (mediaServerItem == null) { |
| 51 | 51 | return null; |
| 52 | 52 | } |
| 53 | - if (ObjectUtils.isEmpty(mediaServerItem.getRecordAssistPort())) { | |
| 53 | + if (mediaServerItem.getRecordAssistPort() > 0) { | |
| 54 | 54 | logger.warn("未启用Assist服务"); |
| 55 | 55 | return null; |
| 56 | 56 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| ... | ... | @@ -18,8 +18,11 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 18 | 18 | import org.slf4j.Logger; |
| 19 | 19 | import org.slf4j.LoggerFactory; |
| 20 | 20 | import org.springframework.beans.factory.annotation.Autowired; |
| 21 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 21 | 22 | import org.springframework.http.HttpStatus; |
| 22 | 23 | import org.springframework.http.ResponseEntity; |
| 24 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 25 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | |
| 23 | 26 | import org.springframework.util.ObjectUtils; |
| 24 | 27 | import org.springframework.util.StringUtils; |
| 25 | 28 | import org.springframework.web.bind.annotation.PostMapping; |
| ... | ... | @@ -92,6 +95,10 @@ public class ZLMHttpHookListener { |
| 92 | 95 | @Autowired |
| 93 | 96 | private AssistRESTfulUtils assistRESTfulUtils; |
| 94 | 97 | |
| 98 | + @Qualifier("taskExecutor") | |
| 99 | + @Autowired | |
| 100 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 101 | + | |
| 95 | 102 | /** |
| 96 | 103 | * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 |
| 97 | 104 | * |
| ... | ... | @@ -238,9 +245,12 @@ public class ZLMHttpHookListener { |
| 238 | 245 | // 鉴权通过 |
| 239 | 246 | redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); |
| 240 | 247 | // 通知assist新的callId |
| 241 | - if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) { | |
| 242 | - assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null); | |
| 243 | - } | |
| 248 | + taskExecutor.execute(()->{ | |
| 249 | + if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) { | |
| 250 | + assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null); | |
| 251 | + } | |
| 252 | + }); | |
| 253 | + | |
| 244 | 254 | }else { |
| 245 | 255 | zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId()); |
| 246 | 256 | } |
| ... | ... | @@ -416,18 +426,23 @@ public class ZLMHttpHookListener { |
| 416 | 426 | String schema = item.getSchema(); |
| 417 | 427 | List<MediaItem.MediaTrack> tracks = item.getTracks(); |
| 418 | 428 | boolean regist = item.isRegist(); |
| 419 | - if (regist) { | |
| 420 | - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); | |
| 421 | - if (streamAuthorityInfo == null) { | |
| 422 | - streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item); | |
| 429 | + if (item.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 430 | + || item.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 431 | + || item.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | |
| 432 | + if (regist) { | |
| 433 | + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); | |
| 434 | + if (streamAuthorityInfo == null) { | |
| 435 | + streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item); | |
| 436 | + }else { | |
| 437 | + streamAuthorityInfo.setOriginType(item.getOriginType()); | |
| 438 | + streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr()); | |
| 439 | + } | |
| 440 | + redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo); | |
| 423 | 441 | }else { |
| 424 | - streamAuthorityInfo.setOriginType(item.getOriginType()); | |
| 425 | - streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr()); | |
| 442 | + redisCatchStorage.removeStreamAuthorityInfo(app, stream); | |
| 426 | 443 | } |
| 427 | - redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo); | |
| 428 | - }else { | |
| 429 | - redisCatchStorage.removeStreamAuthorityInfo(app, stream); | |
| 430 | 444 | } |
| 445 | + | |
| 431 | 446 | if ("rtsp".equals(schema)){ |
| 432 | 447 | logger.info("on_stream_changed:注册->{}, app->{}, stream->{}", regist, app, stream); |
| 433 | 448 | if (regist) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.service; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 4 | +import com.github.pagehelper.PageInfo; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 国标平台的业务类 | |
| 8 | + * @author lin | |
| 9 | + */ | |
| 10 | +public interface IPlatformService { | |
| 11 | + | |
| 12 | + ParentPlatform queryPlatformByServerGBId(String platformGbId); | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 分页获取上级平台 | |
| 16 | + * @param page | |
| 17 | + * @param count | |
| 18 | + * @return | |
| 19 | + */ | |
| 20 | + PageInfo<ParentPlatform> queryParentPlatformList(int page, int count); | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 添加级联平台 | |
| 24 | + * @param parentPlatform 级联平台 | |
| 25 | + */ | |
| 26 | + boolean add(ParentPlatform parentPlatform); | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 平台上线 | |
| 30 | + * @param parentPlatform 平台信息 | |
| 31 | + */ | |
| 32 | + void online(ParentPlatform parentPlatform); | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 平台离线 | |
| 36 | + * @param parentPlatform 平台信息 | |
| 37 | + */ | |
| 38 | + void offline(ParentPlatform parentPlatform); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 向上级平台发起注册 | |
| 42 | + * @param parentPlatform | |
| 43 | + */ | |
| 44 | + void login(ParentPlatform parentPlatform); | |
| 45 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| ... | ... | @@ -513,10 +513,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 513 | 513 | mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); |
| 514 | 514 | String protocol = sslEnabled ? "https" : "http"; |
| 515 | 515 | String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); |
| 516 | - String recordHookPrex = null; | |
| 517 | - if (mediaServerItem.getRecordAssistPort() != 0) { | |
| 518 | - recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaServerItem.getRecordAssistPort()); | |
| 519 | - } | |
| 516 | + | |
| 520 | 517 | Map<String, Object> param = new HashMap<>(); |
| 521 | 518 | param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline |
| 522 | 519 | param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"); |
| ... | ... | @@ -525,7 +522,6 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 525 | 522 | param.put("hook.on_play",String.format("%s/on_play", hookPrex)); |
| 526 | 523 | param.put("hook.on_http_access",String.format("%s/on_http_access", hookPrex)); |
| 527 | 524 | param.put("hook.on_publish", String.format("%s/on_publish", hookPrex)); |
| 528 | - param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): ""); | |
| 529 | 525 | param.put("hook.on_record_ts",String.format("%s/on_record_ts", hookPrex)); |
| 530 | 526 | param.put("hook.on_rtsp_auth",String.format("%s/on_rtsp_auth", hookPrex)); |
| 531 | 527 | param.put("hook.on_rtsp_realm",String.format("%s/on_rtsp_realm", hookPrex)); |
| ... | ... | @@ -535,6 +531,11 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 535 | 531 | param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex)); |
| 536 | 532 | param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex)); |
| 537 | 533 | param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex)); |
| 534 | + if (mediaServerItem.getRecordAssistPort() > 0) { | |
| 535 | + param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort())); | |
| 536 | + }else { | |
| 537 | + param.put("hook.on_record_mp4",""); | |
| 538 | + } | |
| 538 | 539 | param.put("hook.timeoutSec","20"); |
| 539 | 540 | param.put("general.streamNoneReaderDelayMS",mediaServerItem.getStreamNoneReaderDelayMS()==-1?"3600000":mediaServerItem.getStreamNoneReaderDelayMS() ); |
| 540 | 541 | // 推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。 |
| ... | ... | @@ -544,7 +545,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 544 | 545 | param.put("general.continue_push_ms", "3000" ); |
| 545 | 546 | // 最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track, 设置此选项优化那些音频错误的不规范流, |
| 546 | 547 | // 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项 |
| 547 | - param.put("general.wait_track_ready_ms", "3000" ); | |
| 548 | +// param.put("general.wait_track_ready_ms", "3000" ); | |
| 548 | 549 | if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) { |
| 549 | 550 | param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); |
| 550 | 551 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.service.impl; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 4 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | |
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | |
| 10 | +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | |
| 11 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 12 | +import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 13 | +import com.genersoft.iot.vmp.service.IPlatformService; | |
| 14 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 15 | +import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; | |
| 16 | +import com.github.pagehelper.PageHelper; | |
| 17 | +import com.github.pagehelper.PageInfo; | |
| 18 | +import org.slf4j.Logger; | |
| 19 | +import org.slf4j.LoggerFactory; | |
| 20 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 21 | +import org.springframework.stereotype.Service; | |
| 22 | + | |
| 23 | +import javax.sip.TimeoutEvent; | |
| 24 | +import java.util.HashMap; | |
| 25 | +import java.util.List; | |
| 26 | +import java.util.Map; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * @author lin | |
| 30 | + */ | |
| 31 | +@Service | |
| 32 | +public class PlatformServiceImpl implements IPlatformService { | |
| 33 | + | |
| 34 | + private final static String REGISTER_KEY_PREFIX = "platform_register_"; | |
| 35 | + private final static String KEEPALIVE_KEY_PREFIX = "platform_keepalive_"; | |
| 36 | + | |
| 37 | + private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class); | |
| 38 | + | |
| 39 | + @Autowired | |
| 40 | + private ParentPlatformMapper platformMapper; | |
| 41 | + | |
| 42 | + @Autowired | |
| 43 | + private IRedisCatchStorage redisCatchStorage; | |
| 44 | + | |
| 45 | + @Autowired | |
| 46 | + private IMediaServerService mediaServerService; | |
| 47 | + | |
| 48 | + @Autowired | |
| 49 | + private SIPCommanderFroPlatform commanderForPlatform; | |
| 50 | + | |
| 51 | + @Autowired | |
| 52 | + private DynamicTask dynamicTask; | |
| 53 | + | |
| 54 | + @Autowired | |
| 55 | + private ZLMRTPServerFactory zlmrtpServerFactory; | |
| 56 | + | |
| 57 | + @Autowired | |
| 58 | + private SubscribeHolder subscribeHolder; | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + @Override | |
| 63 | + public ParentPlatform queryPlatformByServerGBId(String platformGbId) { | |
| 64 | + return platformMapper.getParentPlatByServerGBId(platformGbId); | |
| 65 | + } | |
| 66 | + | |
| 67 | + @Override | |
| 68 | + public PageInfo<ParentPlatform> queryParentPlatformList(int page, int count) { | |
| 69 | + PageHelper.startPage(page, count); | |
| 70 | + List<ParentPlatform> all = platformMapper.getParentPlatformList(); | |
| 71 | + return new PageInfo<>(all); | |
| 72 | + } | |
| 73 | + | |
| 74 | + @Override | |
| 75 | + public boolean add(ParentPlatform parentPlatform) { | |
| 76 | + | |
| 77 | + if (parentPlatform.getCatalogGroup() == 0) { | |
| 78 | + // 每次发送目录的数量默认为1 | |
| 79 | + parentPlatform.setCatalogGroup(1); | |
| 80 | + } | |
| 81 | + if (parentPlatform.getAdministrativeDivision() == null) { | |
| 82 | + // 行政区划默认去编号的前6位 | |
| 83 | + parentPlatform.setAdministrativeDivision(parentPlatform.getServerGBId().substring(0,6)); | |
| 84 | + } | |
| 85 | + parentPlatform.setCatalogId(parentPlatform.getDeviceGBId()); | |
| 86 | + int result = platformMapper.addParentPlatform(parentPlatform); | |
| 87 | + // 添加缓存 | |
| 88 | + ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); | |
| 89 | + parentPlatformCatch.setParentPlatform(parentPlatform); | |
| 90 | + parentPlatformCatch.setId(parentPlatform.getServerGBId()); | |
| 91 | + parentPlatformCatch.setParentPlatform(parentPlatform); | |
| 92 | + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 93 | + if (parentPlatform.isEnable()) { | |
| 94 | + // 保存时启用就发送注册 | |
| 95 | + // 注册成功时由程序直接调用了online方法 | |
| 96 | + commanderForPlatform.register(parentPlatform, eventResult -> { | |
| 97 | + logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId()); | |
| 98 | + }, null); | |
| 99 | + } | |
| 100 | + return result > 0; | |
| 101 | + } | |
| 102 | + | |
| 103 | + @Override | |
| 104 | + public void online(ParentPlatform parentPlatform) { | |
| 105 | + logger.info("[国标级联]:{}, 平台上线", parentPlatform.getServerGBId()); | |
| 106 | + platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true); | |
| 107 | + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | |
| 108 | + if (parentPlatformCatch != null) { | |
| 109 | + parentPlatformCatch.getParentPlatform().setStatus(true); | |
| 110 | + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 111 | + }else { | |
| 112 | + parentPlatformCatch = new ParentPlatformCatch(); | |
| 113 | + parentPlatformCatch.setParentPlatform(parentPlatform); | |
| 114 | + parentPlatformCatch.setId(parentPlatform.getServerGBId()); | |
| 115 | + parentPlatform.setStatus(true); | |
| 116 | + parentPlatformCatch.setParentPlatform(parentPlatform); | |
| 117 | + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 118 | + } | |
| 119 | + | |
| 120 | + final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); | |
| 121 | + if (dynamicTask.contains(registerTaskKey)) { | |
| 122 | + dynamicTask.stop(registerTaskKey); | |
| 123 | + } | |
| 124 | + // 添加注册任务 | |
| 125 | + dynamicTask.startDelay(registerTaskKey, | |
| 126 | + // 注册失败(注册成功时由程序直接调用了online方法) | |
| 127 | + ()->commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null), | |
| 128 | + parentPlatform.getExpires()*1000); | |
| 129 | + | |
| 130 | + final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); | |
| 131 | + if (!dynamicTask.contains(keepaliveTaskKey)) { | |
| 132 | + // 添加心跳任务 | |
| 133 | + dynamicTask.startCron(keepaliveTaskKey, | |
| 134 | + ()-> commanderForPlatform.keepalive(parentPlatform, eventResult -> { | |
| 135 | + // 心跳失败 | |
| 136 | + if (eventResult.type == SipSubscribe.EventResultType.timeout) { | |
| 137 | + // 心跳超时 | |
| 138 | + ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | |
| 139 | + // 此时是第三次心跳超时, 平台离线 | |
| 140 | + if (platformCatch.getKeepAliveReply() == 2) { | |
| 141 | + // 设置平台离线,并重新注册 | |
| 142 | + offline(parentPlatform); | |
| 143 | + logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId()); | |
| 144 | + commanderForPlatform.register(parentPlatform, eventResult1 -> { | |
| 145 | + logger.info("[国标级联] {},三次心跳超时后再次发起注册仍然失败,开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId()); | |
| 146 | + // 添加注册任务 | |
| 147 | + dynamicTask.startCron(registerTaskKey, | |
| 148 | + // 注册失败(注册成功时由程序直接调用了online方法) | |
| 149 | + ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()), | |
| 150 | + 60*1000); | |
| 151 | + }, null); | |
| 152 | + } | |
| 153 | + | |
| 154 | + }else { | |
| 155 | + logger.warn("[国标级联]发送心跳收到错误,code: {}, msg: {}", eventResult.statusCode, eventResult.msg); | |
| 156 | + } | |
| 157 | + | |
| 158 | + }, eventResult -> { | |
| 159 | + // 心跳成功 | |
| 160 | + // 清空之前的心跳超时计数 | |
| 161 | + ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | |
| 162 | + if (platformCatch.getKeepAliveReply() > 0) { | |
| 163 | + platformCatch.setKeepAliveReply(0); | |
| 164 | + redisCatchStorage.updatePlatformCatchInfo(platformCatch); | |
| 165 | + } | |
| 166 | + }), | |
| 167 | + parentPlatform.getExpires()*1000); | |
| 168 | + } | |
| 169 | + } | |
| 170 | + | |
| 171 | + @Override | |
| 172 | + public void offline(ParentPlatform parentPlatform) { | |
| 173 | + logger.info("[平台离线]:{}", parentPlatform.getServerGBId()); | |
| 174 | + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | |
| 175 | + parentPlatformCatch.setKeepAliveReply(0); | |
| 176 | + parentPlatformCatch.setRegisterAliveReply(0); | |
| 177 | + ParentPlatform parentPlatformInCatch = parentPlatformCatch.getParentPlatform(); | |
| 178 | + parentPlatformInCatch.setStatus(false); | |
| 179 | + parentPlatformCatch.setParentPlatform(parentPlatformInCatch); | |
| 180 | + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | |
| 181 | + platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), false); | |
| 182 | + | |
| 183 | + // 停止所有推流 | |
| 184 | + logger.info("[平台离线] {}, 停止所有推流", parentPlatform.getServerGBId()); | |
| 185 | + stopAllPush(parentPlatform.getServerGBId()); | |
| 186 | + // 清除注册定时 | |
| 187 | + logger.info("[平台离线] {}, 停止定时注册任务", parentPlatform.getServerGBId()); | |
| 188 | + final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); | |
| 189 | + if (dynamicTask.contains(registerTaskKey)) { | |
| 190 | + dynamicTask.stop(registerTaskKey); | |
| 191 | + } | |
| 192 | + // 清除心跳定时 | |
| 193 | + logger.info("[平台离线] {}, 停止定时发送心跳任务", parentPlatform.getServerGBId()); | |
| 194 | + final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); | |
| 195 | + if (dynamicTask.contains(keepaliveTaskKey)) { | |
| 196 | + // 添加心跳任务 | |
| 197 | + dynamicTask.stop(keepaliveTaskKey); | |
| 198 | + } | |
| 199 | + // 停止目录订阅回复 | |
| 200 | + logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId()); | |
| 201 | + subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); | |
| 202 | + } | |
| 203 | + | |
| 204 | + private void stopAllPush(String platformId) { | |
| 205 | + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(platformId); | |
| 206 | + if (sendRtpItems != null && sendRtpItems.size() > 0) { | |
| 207 | + for (SendRtpItem sendRtpItem : sendRtpItems) { | |
| 208 | + redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null); | |
| 209 | + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | |
| 210 | + Map<String, Object> param = new HashMap<>(3); | |
| 211 | + param.put("vhost", "__defaultVhost__"); | |
| 212 | + param.put("app", sendRtpItem.getApp()); | |
| 213 | + param.put("stream", sendRtpItem.getStreamId()); | |
| 214 | + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | |
| 215 | + } | |
| 216 | + | |
| 217 | + } | |
| 218 | + } | |
| 219 | + | |
| 220 | + @Override | |
| 221 | + public void login(ParentPlatform parentPlatform) { | |
| 222 | + final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); | |
| 223 | + commanderForPlatform.register(parentPlatform, eventResult1 -> { | |
| 224 | + logger.info("[国标级联] {},开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId()); | |
| 225 | + // 添加注册任务 | |
| 226 | + dynamicTask.startCron(registerTaskKey, | |
| 227 | + // 注册失败(注册成功时由程序直接调用了online方法) | |
| 228 | + ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()), | |
| 229 | + 60*1000); | |
| 230 | + }, null); | |
| 231 | + } | |
| 232 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| ... | ... | @@ -575,7 +575,7 @@ public class PlayServiceImpl implements IPlayService { |
| 575 | 575 | logger.warn("查询录像信息时发现节点已离线"); |
| 576 | 576 | return null; |
| 577 | 577 | } |
| 578 | - if (mediaServerItem.getRecordAssistPort() != 0) { | |
| 578 | + if (mediaServerItem.getRecordAssistPort() > 0) { | |
| 579 | 579 | JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); |
| 580 | 580 | if (jsonObject != null && jsonObject.getInteger("code") == 0) { |
| 581 | 581 | long duration = jsonObject.getLong("data"); |
| ... | ... | @@ -691,7 +691,7 @@ public class PlayServiceImpl implements IPlayService { |
| 691 | 691 | // for (SendRtpItem sendRtpItem : sendRtpItems) { |
| 692 | 692 | // if (sendRtpItem.getMediaServerId().equals(mediaServerId)) { |
| 693 | 693 | // if (mediaListMap.get(sendRtpItem.getStreamId()) == null) { |
| 694 | -// ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | |
| 694 | +// ParentPlatform platform = storager.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); | |
| 695 | 695 | // sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId()); |
| 696 | 696 | // } |
| 697 | 697 | // } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
| ... | ... | @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 8 | 8 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 9 | 9 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 10 | 10 | import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; |
| 11 | +import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | |
| 11 | 12 | |
| 12 | 13 | import java.util.List; |
| 13 | 14 | import java.util.Map; |
| ... | ... | @@ -61,17 +62,13 @@ public interface IRedisCatchStorage { |
| 61 | 62 | |
| 62 | 63 | void delPlatformCatchInfo(String platformGbId); |
| 63 | 64 | |
| 64 | - void updatePlatformKeepalive(ParentPlatform parentPlatform); | |
| 65 | - | |
| 66 | 65 | void delPlatformKeepalive(String platformGbId); |
| 67 | 66 | |
| 68 | - void updatePlatformRegister(ParentPlatform parentPlatform); | |
| 69 | - | |
| 70 | 67 | void delPlatformRegister(String platformGbId); |
| 71 | 68 | |
| 72 | - void updatePlatformRegisterInfo(String callId, String platformGbId); | |
| 69 | + void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo); | |
| 73 | 70 | |
| 74 | - String queryPlatformRegisterInfo(String callId); | |
| 71 | + PlatformRegisterInfo queryPlatformRegisterInfo(String callId); | |
| 75 | 72 | |
| 76 | 73 | void delPlatformRegisterInfo(String callId); |
| 77 | 74 | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
| ... | ... | @@ -170,15 +170,6 @@ public interface IVideoManagerStorage { |
| 170 | 170 | */ |
| 171 | 171 | boolean deleteParentPlatform(ParentPlatform parentPlatform); |
| 172 | 172 | |
| 173 | - | |
| 174 | - /** | |
| 175 | - * 分页获取上级平台 | |
| 176 | - * @param page | |
| 177 | - * @param count | |
| 178 | - * @return | |
| 179 | - */ | |
| 180 | - PageInfo<ParentPlatform> queryParentPlatformList(int page, int count); | |
| 181 | - | |
| 182 | 173 | /** |
| 183 | 174 | * 获取所有已启用的平台 |
| 184 | 175 | * @return | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/dto/PlatformRegisterInfo.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.storager.dao.dto; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 平台发送注册/注销消息时缓存此消息 | |
| 5 | + * @author lin | |
| 6 | + */ | |
| 7 | +public class PlatformRegisterInfo { | |
| 8 | + | |
| 9 | + /** | |
| 10 | + * 平台Id | |
| 11 | + */ | |
| 12 | + private String platformId; | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 是否时注册,false为注销 | |
| 16 | + */ | |
| 17 | + private boolean register; | |
| 18 | + | |
| 19 | + public static PlatformRegisterInfo getInstance(String platformId, boolean register) { | |
| 20 | + PlatformRegisterInfo platformRegisterInfo = new PlatformRegisterInfo(); | |
| 21 | + platformRegisterInfo.setPlatformId(platformId); | |
| 22 | + platformRegisterInfo.setRegister(register); | |
| 23 | + return platformRegisterInfo; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public String getPlatformId() { | |
| 27 | + return platformId; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public void setPlatformId(String platformId) { | |
| 31 | + this.platformId = platformId; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public boolean isRegister() { | |
| 35 | + return register; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public void setRegister(boolean register) { | |
| 39 | + this.register = register; | |
| 40 | + } | |
| 41 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| ... | ... | @@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 16 | 16 | import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; |
| 17 | 17 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 18 | 18 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| 19 | +import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | |
| 19 | 20 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 20 | 21 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| 21 | 22 | import org.slf4j.Logger; |
| ... | ... | @@ -291,18 +292,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 291 | 292 | } |
| 292 | 293 | |
| 293 | 294 | @Override |
| 294 | - public void updatePlatformKeepalive(ParentPlatform parentPlatform) { | |
| 295 | - String key = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + parentPlatform.getServerGBId(); | |
| 296 | - RedisUtil.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout())); | |
| 297 | - } | |
| 298 | - | |
| 299 | - @Override | |
| 300 | - public void updatePlatformRegister(ParentPlatform parentPlatform) { | |
| 301 | - String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_" + parentPlatform.getServerGBId(); | |
| 302 | - RedisUtil.set(key, "", Integer.parseInt(parentPlatform.getExpires())); | |
| 303 | - } | |
| 304 | - | |
| 305 | - @Override | |
| 306 | 295 | public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) { |
| 307 | 296 | return (ParentPlatformCatch)RedisUtil.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId); |
| 308 | 297 | } |
| ... | ... | @@ -324,15 +313,15 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 324 | 313 | |
| 325 | 314 | |
| 326 | 315 | @Override |
| 327 | - public void updatePlatformRegisterInfo(String callId, String platformGbId) { | |
| 316 | + public void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo) { | |
| 328 | 317 | String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId; |
| 329 | - RedisUtil.set(key, platformGbId, 30); | |
| 318 | + RedisUtil.set(key, platformRegisterInfo, 30); | |
| 330 | 319 | } |
| 331 | 320 | |
| 332 | 321 | |
| 333 | 322 | @Override |
| 334 | - public String queryPlatformRegisterInfo(String callId) { | |
| 335 | - return (String)RedisUtil.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId); | |
| 323 | + public PlatformRegisterInfo queryPlatformRegisterInfo(String callId) { | |
| 324 | + return (PlatformRegisterInfo)RedisUtil.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId); | |
| 336 | 325 | } |
| 337 | 326 | |
| 338 | 327 | @Override | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| ... | ... | @@ -458,13 +458,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | 460 | @Override |
| 461 | - public PageInfo<ParentPlatform> queryParentPlatformList(int page, int count) { | |
| 462 | - PageHelper.startPage(page, count); | |
| 463 | - List<ParentPlatform> all = platformMapper.getParentPlatformList(); | |
| 464 | - return new PageInfo<>(all); | |
| 465 | - } | |
| 466 | - | |
| 467 | - @Override | |
| 468 | 461 | public ParentPlatform queryParentPlatByServerGBId(String platformGbId) { |
| 469 | 462 | return platformMapper.getParentPlatByServerGBId(platformGbId); |
| 470 | 463 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
| ... | ... | @@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit; |
| 5 | 5 | |
| 6 | 6 | import com.alibaba.fastjson.JSONObject; |
| 7 | 7 | import com.genersoft.iot.vmp.utils.SpringBeanFactory; |
| 8 | +import gov.nist.javax.sip.stack.UDPMessageChannel; | |
| 8 | 9 | import org.springframework.data.redis.core.*; |
| 9 | 10 | import org.springframework.util.CollectionUtils; |
| 10 | 11 | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
| ... | ... | @@ -9,14 +9,13 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 9 | 9 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 10 | 10 | import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; |
| 11 | 11 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; |
| 12 | -import com.genersoft.iot.vmp.gb28181.bean.TreeType; | |
| 13 | 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 14 | 13 | import com.genersoft.iot.vmp.service.IPlatformChannelService; |
| 14 | +import com.genersoft.iot.vmp.service.IPlatformService; | |
| 15 | 15 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 16 | 16 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 17 | 17 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 18 | 18 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 19 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | |
| 20 | 19 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 21 | 20 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam; |
| 22 | 21 | import com.github.pagehelper.PageInfo; |
| ... | ... | @@ -26,10 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; |
| 26 | 25 | import org.slf4j.Logger; |
| 27 | 26 | import org.slf4j.LoggerFactory; |
| 28 | 27 | import org.springframework.beans.factory.annotation.Autowired; |
| 29 | -import org.springframework.http.HttpStatus; | |
| 30 | -import org.springframework.http.ResponseEntity; | |
| 31 | 28 | import org.springframework.util.ObjectUtils; |
| 32 | -import org.springframework.util.StringUtils; | |
| 33 | 29 | import org.springframework.web.bind.annotation.*; |
| 34 | 30 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 35 | 31 | |
| ... | ... | @@ -70,6 +66,9 @@ public class PlatformController { |
| 70 | 66 | @Autowired |
| 71 | 67 | private DynamicTask dynamicTask; |
| 72 | 68 | |
| 69 | + @Autowired | |
| 70 | + private IPlatformService platformService; | |
| 71 | + | |
| 73 | 72 | /** |
| 74 | 73 | * 获取国标服务的配置 |
| 75 | 74 | * |
| ... | ... | @@ -95,8 +94,7 @@ public class PlatformController { |
| 95 | 94 | @Parameter(name = "id", description = "平台国标编号", required = true) |
| 96 | 95 | @GetMapping("/info/{id}") |
| 97 | 96 | public ParentPlatform getPlatform(@PathVariable String id) { |
| 98 | - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(id); | |
| 99 | - WVPResult<ParentPlatform> wvpResult = new WVPResult<>(); | |
| 97 | + ParentPlatform parentPlatform = platformService.queryPlatformByServerGBId(id); | |
| 100 | 98 | if (parentPlatform != null) { |
| 101 | 99 | return parentPlatform; |
| 102 | 100 | } else { |
| ... | ... | @@ -117,7 +115,7 @@ public class PlatformController { |
| 117 | 115 | @Parameter(name = "count", description = "每页条数", required = true) |
| 118 | 116 | public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count) { |
| 119 | 117 | |
| 120 | - PageInfo<ParentPlatform> parentPlatformPageInfo = storager.queryParentPlatformList(page, count); | |
| 118 | + PageInfo<ParentPlatform> parentPlatformPageInfo = platformService.queryParentPlatformList(page, count); | |
| 121 | 119 | if (parentPlatformPageInfo.getList().size() > 0) { |
| 122 | 120 | for (ParentPlatform platform : parentPlatformPageInfo.getList()) { |
| 123 | 121 | platform.setMobilePositionSubscribe(subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()) != null); |
| ... | ... | @@ -136,7 +134,7 @@ public class PlatformController { |
| 136 | 134 | @Operation(summary = "添加上级平台信息") |
| 137 | 135 | @PostMapping("/add") |
| 138 | 136 | @ResponseBody |
| 139 | - public String addPlatform(@RequestBody ParentPlatform parentPlatform) { | |
| 137 | + public void addPlatform(@RequestBody ParentPlatform parentPlatform) { | |
| 140 | 138 | |
| 141 | 139 | if (logger.isDebugEnabled()) { |
| 142 | 140 | logger.debug("保存上级平台信息API调用"); |
| ... | ... | @@ -158,33 +156,16 @@ public class PlatformController { |
| 158 | 156 | throw new ControllerException(ErrorCode.ERROR400.getCode(), "error severPort"); |
| 159 | 157 | } |
| 160 | 158 | |
| 159 | + | |
| 161 | 160 | ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId()); |
| 162 | 161 | if (parentPlatformOld != null) { |
| 163 | 162 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台 " + parentPlatform.getServerGBId() + " 已存在"); |
| 164 | 163 | } |
| 165 | 164 | parentPlatform.setCreateTime(DateUtil.getNow()); |
| 166 | 165 | parentPlatform.setUpdateTime(DateUtil.getNow()); |
| 167 | - boolean updateResult = storager.updateParentPlatform(parentPlatform); | |
| 168 | - | |
| 169 | - if (updateResult) { | |
| 170 | - // 保存时启用就发送注册 | |
| 171 | - if (parentPlatform.isEnable()) { | |
| 172 | - if (parentPlatformOld != null && parentPlatformOld.isStatus()) { | |
| 173 | - commanderForPlatform.unregister(parentPlatformOld, null, eventResult -> { | |
| 174 | - // 只要保存就发送注册 | |
| 175 | - commanderForPlatform.register(parentPlatform, null, null); | |
| 176 | - }); | |
| 177 | - } else { | |
| 178 | - // 只要保存就发送注册 | |
| 179 | - commanderForPlatform.register(parentPlatform, null, null); | |
| 180 | - } | |
| 166 | + boolean updateResult = platformService.add(parentPlatform); | |
| 181 | 167 | |
| 182 | - } else if (parentPlatformOld != null && parentPlatformOld.isEnable()) { | |
| 183 | - // 关闭启用时注销 | |
| 184 | - commanderForPlatform.unregister(parentPlatform, null, null); | |
| 185 | - } | |
| 186 | - return null; | |
| 187 | - } else { | |
| 168 | + if (!updateResult) { | |
| 188 | 169 | throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败"); |
| 189 | 170 | } |
| 190 | 171 | } | ... | ... |
src/main/resources/all-application.yml
| ... | ... | @@ -179,8 +179,6 @@ user-settings: |
| 179 | 179 | platform-play-timeout: 60000 |
| 180 | 180 | # 是否开启接口鉴权 |
| 181 | 181 | interface-authentication: true |
| 182 | - # 自动配置redis 可以过期事件 | |
| 183 | - redis-config: true | |
| 184 | 182 | # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录 |
| 185 | 183 | interface-authentication-excludes: |
| 186 | 184 | - /api/v1/** | ... | ... |
web_src/src/components/dialog/MediaServerEdit.vue
web_src/src/components/dialog/StreamProxyEdit.vue
web_src/src/components/dialog/platformEdit.vue
web_src/src/components/dialog/pushStreamEdit.vue