diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index 85f46849..c24e0cad 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -6,6 +6,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.regex.Pattern; + @Configuration("mediaConfig") public class MediaConfig{ @@ -161,7 +165,18 @@ public class MediaConfig{ if (StringUtils.isEmpty(sdpIp)){ return ip; }else { - return sdpIp; + if (isValidIPAddress(sdpIp)) { + return sdpIp; + }else { + // 按照域名解析 + String hostAddress = null; + try { + hostAddress = InetAddress.getByName(sdpIp).getHostAddress(); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + return hostAddress; + } } } @@ -211,4 +226,11 @@ public class MediaConfig{ return mediaServerItem; } + private boolean isValidIPAddress(String ipAddress) { + if ((ipAddress != null) && (!ipAddress.isEmpty())) { + return Pattern.matches("^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", ipAddress); + } + return false; + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index 1c054401..47a4e008 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -94,7 +94,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen String deviceId = uri.getUser(); AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); - if (authHead == null) { + if (authHead == null && !StringUtils.isEmpty(sipConfig.getPassword())) { logger.info("[注册请求] 未携带授权头 回复401: {}", requestAddress); response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java index d5d4c1d0..cf07250d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java @@ -49,28 +49,28 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp return; } try { + // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 + // 获取到通信地址等信息 + ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME); + String received = viaHeader.getReceived(); + int rPort = viaHeader.getRPort(); + // 解析本地地址替代 + if (StringUtils.isEmpty(received) || rPort == -1) { + received = viaHeader.getHost(); + rPort = viaHeader.getPort(); + } + if (device.getPort() != rPort) { + device.setPort(rPort); + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); + } + device.setKeepaliveTime(DateUtil.getNow()); if (device.getOnline() == 1) { // 回复200 OK responseAck(evt, Response.OK); + deviceService.updateDevice(device); }else { // 对于已经离线的设备判断他的注册是否已经过期 if (!deviceService.expire(device)){ - device.setKeepaliveTime(DateUtil.getNow()); - // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 - // 获取到通信地址等信息 - ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME); - String received = viaHeader.getReceived(); - int rPort = viaHeader.getRPort(); - // 解析本地地址替代 - if (StringUtils.isEmpty(received) || rPort == -1) { - received = viaHeader.getHost(); - rPort = viaHeader.getPort(); - } - if (device.getPort() != rPort) { - device.setPort(rPort); - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); - } - device.setKeepaliveTime(DateUtil.getNow()); deviceService.online(device); // 回复200 OK responseAck(evt, Response.OK); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java index 4509e424..1f701715 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java @@ -70,15 +70,20 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent rootElement = getRootElement(evt, device.getCharset()); String sn = getText(rootElement, "SN"); - + RecordInfo recordInfo = new RecordInfo(); + recordInfo.setDeviceId(device.getDeviceId()); + recordInfo.setSn(sn); + recordInfo.setName(getText(rootElement, "Name")); String sumNumStr = getText(rootElement, "SumNum"); int sumNum = 0; if (!StringUtils.isEmpty(sumNumStr)) { sumNum = Integer.parseInt(sumNumStr); } + recordInfo.setSumNum(sumNum); Element recordListElement = rootElement.element("RecordList"); if (recordListElement == null || sumNum == 0) { logger.info("无录像数据"); + eventPublisher.recordEndEventPush(recordInfo); recordDataCatch.put(device.getDeviceId(), sn, sumNum, new ArrayList<>()); releaseRequest(device.getDeviceId(), sn); } else { @@ -112,6 +117,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent record.setRecorderId(getText(itemRecord, "RecorderID")); recordList.add(record); } + recordInfo.setRecordList(recordList); + // 发送消息,如果是上级查询此录像,则会通过这里通知给上级 + eventPublisher.recordEndEventPush(recordInfo); int count = recordDataCatch.put(device.getDeviceId(), sn, sumNum, recordList); logger.info("[国标录像], {}->{}: {}/{}", device.getDeviceId(), sn, count, sumNum); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index b43c81f6..2521a069 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -87,6 +87,9 @@ public class PlayServiceImpl implements IPlayService { @Autowired private DynamicTask dynamicTask; + @Autowired + private ZLMHttpHookSubscribe subscribe; + @@ -256,6 +259,7 @@ public class PlayServiceImpl implements IPlayService { } }, userSetting.getPlayTimeout()*1000); final String ssrc = ssrcInfo.getSsrc(); + final String stream = ssrcInfo.getStream(); cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { logger.info("收到订阅消息: " + response.toJSONString()); dynamicTask.stop(timeOutTaskKey); @@ -271,9 +275,13 @@ public class PlayServiceImpl implements IPlayService { if (ssrcIndex >= 0) { //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); - if (!ssrc.equals(ssrcInResponse) && device.isSsrcCheck()) { // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 - // 查询 ssrcInResponse 是否可用 - if (mediaServerItem.isRtpEnable() && !mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 + if (ssrc.equals(ssrcInResponse)) { + return; + } + logger.info("[SIP 消息] 收到invite 200, 发现下级自定义了ssrc 开启修正"); + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { // ssrc 不可用 // 释放ssrc mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); @@ -283,10 +291,32 @@ public class PlayServiceImpl implements IPlayService { errorEvent.response(event); return; } + + // 单端口模式streamId也有变化,需要重新设置监听 + if (!mediaServerItem.isRtpEnable()) { + // 添加订阅 + JSONObject subscribeKey = new JSONObject(); + subscribeKey.put("app", "rtp"); + subscribeKey.put("stream", stream); + subscribeKey.put("regist", true); + subscribeKey.put("schema", "rtmp"); + subscribeKey.put("mediaServerId", mediaServerItem.getId()); + subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed,subscribeKey); + subscribeKey.put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, + (MediaServerItem mediaServerItemInUse, JSONObject response)->{ + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); + dynamicTask.stop(timeOutTaskKey); + // hook响应 + onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid); + hookEvent.response(mediaServerItemInUse, response); + }); + } // 关闭rtp server mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); // 重新开启ssrc server mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false); + } } }, (event) -> { diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 21223ce1..2d62e29d 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -220,6 +220,7 @@ export default { method: 'get', url: '/api/play/start/' + deviceId + '/' + channelId }).then(function (res) { + console.log(res) that.isLoging = false; if (res.data.code === 0) { @@ -241,8 +242,9 @@ export default { that.$message.error(res.data.msg); } }).catch(function (e) { + console.error(e) that.isLoging = false; - that.$message.error("请求超时"); + // that.$message.error("请求超时"); }); }, queryRecords: function (itemData) { diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 43a929c5..aba35ddb 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -4,10 +4,22 @@
- + + + + + + + + h265web敬请期待 + wsPlayer 敬请期待 + + + +
- +
@@ -273,16 +285,16 @@