Compare commits

...

4 Commits

Author SHA1 Message Date
阿斌
07ef9fa7f2
Pre Merge pull request !36 from 阿斌/N/A 2025-11-29 16:11:21 +00:00
lin
8674cc6213 去除媒体节点接入时过多的端口配置,端口使用媒体服务返回的端口,不再支持docker内网不一致的情况 2025-11-30 00:11:08 +08:00
lin
f4ca65882f 调整国标设备密码逻辑,未设置公共密码则需要提前添加设备后才允许注册 2025-11-29 22:19:21 +08:00
阿斌
da98101aac
update src/main/resources/civilCode.csv.
行政规划错误。江苏南通海门市,修改为海门区,浙江杭州删除下城区、江干区,新增钱塘区,临平区

Signed-off-by: 阿斌 <38912748@qq.com>
2024-12-15 08:58:42 +00:00
15 changed files with 205 additions and 277 deletions

View File

@ -14,7 +14,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletException;
import jakarta.servlet.SessionCookieConfig;
import jakarta.servlet.SessionTrackingMode;
import java.util.Collections;

View File

@ -44,42 +44,6 @@ public class MediaConfig{
@Value("${media.http-port:0}")
private Integer httpPort;
@Value("${media.flv-port:0}")
private Integer flvPort = 0;
@Value("${media.mp4-port:0}")
private Integer mp4Port = 0;
@Value("${media.ws-flv-port:0}")
private Integer wsFlvPort = 0;
@Value("${media.http-ssl-port:0}")
private Integer httpSSlPort = 0;
@Value("${media.flv-ssl-port:0}")
private Integer flvSSlPort = 0;
@Value("${media.ws-flv-ssl-port:0}")
private Integer wsFlvSSlPort = 0;
@Value("${media.rtmp-port:0}")
private Integer rtmpPort = 0;
@Value("${media.rtmp-ssl-port:0}")
private Integer rtmpSSlPort = 0;
@Value("${media.rtp-proxy-port:0}")
private Integer rtpProxyPort = 0;
@Value("${media.jtt-proxy-port:0}")
private Integer jttProxyPort = 0;
@Value("${media.rtsp-port:0}")
private Integer rtspPort = 0;
@Value("${media.rtsp-ssl-port:0}")
private Integer rtspSSLPort = 0;
@Value("${media.auto-config:true}")
private boolean autoConfig = true;
@ -108,24 +72,6 @@ public class MediaConfig{
private String type;
public int getRtpProxyPort() {
if (rtpProxyPort == null) {
return 0;
}else {
return rtpProxyPort;
}
}
public Integer getJttProxyPort() {
if (jttProxyPort == null) {
return 0;
}else {
return jttProxyPort;
}
}
public String getSdpIp() {
if (ObjectUtils.isEmpty(sdpIp)){
return ip;
@ -153,7 +99,7 @@ public class MediaConfig{
}
}
public MediaServer getMediaSerItem(){
public MediaServer buildMediaSer(){
MediaServer mediaServer = new MediaServer();
mediaServer.setId(id);
mediaServer.setIp(ip);
@ -162,19 +108,6 @@ public class MediaConfig{
mediaServer.setSdpIp(getSdpIp());
mediaServer.setStreamIp(getStreamIp());
mediaServer.setHttpPort(httpPort);
mediaServer.setFlvPort(flvPort);
mediaServer.setMp4Port(mp4Port);
mediaServer.setWsFlvPort(wsFlvPort);
mediaServer.setFlvSSLPort(flvSSlPort);
mediaServer.setWsFlvSSLPort(wsFlvSSlPort);
mediaServer.setHttpSSlPort(httpSSlPort);
mediaServer.setRtmpPort(rtmpPort);
mediaServer.setRtmpSSlPort(rtmpSSlPort);
mediaServer.setRtpProxyPort(getRtpProxyPort());
mediaServer.setJttProxyPort(getJttProxyPort());
mediaServer.setRtspPort(rtspPort);
mediaServer.setRtspSSLPort(rtspSSLPort);
mediaServer.setAutoConfig(autoConfig);
mediaServer.setSecret(secret);
mediaServer.setRtpEnable(rtpEnable);

View File

@ -88,39 +88,55 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
String deviceId = uri.getUser();
// 调整逻辑如果为设置公共密码那么就必须要预设用户信息否则无法注册
Device device = deviceService.getDeviceByDeviceId(deviceId);
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
userSetting.getSipUseSourceIpAsRemoteAddress());
String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort();
String title = registerFlag ? "[注册请求]" : "[注销请求]";
log.info(title + "设备:{}, 开始处理: {}", deviceId, requestAddress);
if (device != null &&
device.getSipTransactionInfo() != null &&
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
log.info(title + "设备:{}, 注册续订: {}", device.getDeviceId(), device.getDeviceId());
if (registerFlag) {
device.setExpires(request.getExpires().getExpires());
device.setIp(remoteAddressInfo.getIp());
device.setPort(remoteAddressInfo.getPort());
device.setHostAddress(IpPortUtil.concatenateIpAndPort(remoteAddressInfo.getIp(), String.valueOf(remoteAddressInfo.getPort())));
log.info("{} 设备:{}, 开始处理: {}", title, deviceId, requestAddress);
String password = null;
if (device != null) {
if (device.getSipTransactionInfo() != null &&
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
log.info("{} 设备:{}, 注册续订: {}", title, device.getDeviceId(), device.getDeviceId());
if (registerFlag) {
device.setExpires(request.getExpires().getExpires());
device.setIp(remoteAddressInfo.getIp());
device.setPort(remoteAddressInfo.getPort());
device.setHostAddress(IpPortUtil.concatenateIpAndPort(remoteAddressInfo.getIp(), String.valueOf(remoteAddressInfo.getPort())));
device.setLocalIp(request.getLocalAddress().getHostAddress());
Response registerOkResponse = getRegisterOkResponse(request);
// 判断TCP还是UDP
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
String transport = reqViaHeader.getTransport();
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse);
device.setRegisterTime(DateUtil.getNow());
deviceService.online(device, null);
} else {
deviceService.offline(deviceId, "主动注销");
device.setLocalIp(request.getLocalAddress().getHostAddress());
Response registerOkResponse = getRegisterOkResponse(request);
// 判断TCP还是UDP
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
String transport = reqViaHeader.getTransport();
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse);
device.setRegisterTime(DateUtil.getNow());
deviceService.online(device, null);
} else {
deviceService.offline(deviceId, "主动注销");
}
return;
}else {
// 正常注册, 用户信息未设置密码并且公共密码也未设置则关闭鉴权
if (!ObjectUtils.isEmpty(device.getPassword()) || !ObjectUtils.isEmpty(sipConfig.getPassword())) {
password = (!ObjectUtils.isEmpty(device.getPassword())) ? device.getPassword() : sipConfig.getPassword();
}
}
}else {
if (ObjectUtils.isEmpty(sipConfig.getPassword())) {
log.info("{} 设备:{}, 地址: {}, 公共密码已经禁用,请添加用户信息后注册", title, deviceId, requestAddress);
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
return;
}else {
password = sipConfig.getPassword();
}
return;
}
String password = (device != null && !ObjectUtils.isEmpty(device.getPassword())) ? device.getPassword() : sipConfig.getPassword();
AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
if (authHead == null && !ObjectUtils.isEmpty(password)) {
log.info(title + " 设备:{}, 回复401: {}", deviceId, requestAddress);

View File

@ -39,26 +39,14 @@ public class MediaServerConfig implements CommandLineRunner {
public void run(String... strings) throws Exception {
// 清理所有在线节点的缓存信息
mediaServerService.clearMediaServerForOnline();
MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer();
MediaServer mediaSerItemInConfig = mediaConfig.getMediaSerItem();
MediaServer mediaSerItemInConfig = mediaConfig.buildMediaSer();
mediaSerItemInConfig.setServerId(userSetting.getServerId());
if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) {
mediaServerService.update(mediaSerItemInConfig);
}else {
if (defaultMediaServer != null) {
mediaServerService.delete(defaultMediaServer);
}
MediaServer mediaServerItem = mediaServerService.getOneFromDatabase(mediaSerItemInConfig.getId());
if (mediaServerItem == null) {
mediaServerService.add(mediaSerItemInConfig);
}else {
mediaServerService.update(mediaSerItemInConfig);
}
}
mediaServerService.deleteDefault();
// 发送媒体节点变化事件
mediaServerService.syncCatchFromDatabase();
// 获取所有的zlm 并开启主动连接
List<MediaServer> all = mediaServerService.getAllFromDatabase();
List<MediaServer> all = mediaServerService.getAllFromDatabaseWithOutDefault();
all.add(mediaSerItemInConfig);
log.info("[媒体节点] 加载节点列表, 共{}个节点", all.size());
MediaServerChangeEvent event = new MediaServerChangeEvent(this);
event.setMediaServerItemList(all);

View File

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.media.abl;
import com.alibaba.fastjson2.JSONArray;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.media.abl.bean.ABLResult;
import com.genersoft.iot.vmp.media.abl.bean.AblServerConfig;
import com.genersoft.iot.vmp.media.abl.bean.ConfigKeyId;
@ -12,8 +13,7 @@ import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerDeleteEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.event.EventListener;
@ -29,10 +29,9 @@ import java.util.concurrent.ConcurrentHashMap;
* 管理zlm流媒体节点的状态
*/
@Component
@Slf4j
public class ABLMediaServerStatusManger {
private final static Logger logger = LoggerFactory.getLogger(ABLMediaServerStatusManger.class);
private final Map<Object, MediaServer> offlineABLPrimaryMap = new ConcurrentHashMap<>();
private final Map<Object, MediaServer> offlineAblsecondaryMap = new ConcurrentHashMap<>();
private final Map<Object, Long> offlineAblTimeMap = new ConcurrentHashMap<>();
@ -55,6 +54,9 @@ public class ABLMediaServerStatusManger {
@Autowired
private UserSetting userSetting;
@Autowired
private EventPublisher eventPublisher;
private final String type = "abl";
@Async("taskExecutor")
@ -68,7 +70,7 @@ public class ABLMediaServerStatusManger {
if (!type.equals(mediaServer.getType())) {
continue;
}
logger.info("[ABL-添加待上线节点] ID" + mediaServer.getId());
log.info("[ABL-添加待上线节点] ID" + mediaServer.getId());
offlineABLPrimaryMap.put(mediaServer.getId(), mediaServer);
offlineAblTimeMap.put(mediaServer.getId(), System.currentTimeMillis());
}
@ -87,7 +89,7 @@ public class ABLMediaServerStatusManger {
if (serverItem == null) {
return;
}
logger.info("[ABL-HOOK事件-服务启动] ID" + event.getMediaServerItem().getId());
log.info("[ABL-HOOK事件-服务启动] ID" + event.getMediaServerItem().getId());
online(serverItem, null);
}
@ -101,7 +103,7 @@ public class ABLMediaServerStatusManger {
if (serverItem == null) {
return;
}
logger.info("[ABL-HOOK事件-心跳] ID" + event.getMediaServerItem().getId());
log.info("[ABL-HOOK事件-心跳] ID" + event.getMediaServerItem().getId());
online(serverItem, null);
}
@ -111,7 +113,7 @@ public class ABLMediaServerStatusManger {
if (event.getMediaServer() == null) {
return;
}
logger.info("[ABL-节点被移除] ID" + event.getMediaServer().getServerId());
log.info("[ABL-节点被移除] ID" + event.getMediaServer().getServerId());
offlineABLPrimaryMap.remove(event.getMediaServer().getServerId());
offlineAblsecondaryMap.remove(event.getMediaServer().getServerId());
offlineAblTimeMap.remove(event.getMediaServer().getServerId());
@ -130,17 +132,17 @@ public class ABLMediaServerStatusManger {
offlineABLPrimaryMap.remove(mediaServerItem.getId());
continue;
}
logger.info("[ABL-尝试连接] ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
log.info("[ABL-尝试连接] ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
ABLResult ablResult = ablResTfulUtils.getServerConfig(mediaServerItem);
AblServerConfig ablServerConfig = null;
if (ablResult.getCode() != 0) {
logger.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
log.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
continue;
}
JSONArray params = ablResult.getParams();
if (params == null || params.isEmpty()) {
logger.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
log.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
}else {
ablServerConfig = AblServerConfig.getInstance(params);
initPort(mediaServerItem, ablServerConfig);
@ -153,17 +155,17 @@ public class ABLMediaServerStatusManger {
if (offlineAblTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) {
continue;
}
logger.info("[ABL-尝试连接] ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
log.info("[ABL-尝试连接] ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
ABLResult ablResult = ablResTfulUtils.getServerConfig(mediaServerItem);
AblServerConfig ablServerConfig = null;
if (ablResult.getCode() != 0) {
logger.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
log.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
offlineAblTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
continue;
}
JSONArray params = ablResult.getParams();
if (params == null || params.isEmpty()) {
logger.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
log.info("[ABL-尝试连接]失败, ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
offlineAblTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
}else {
ablServerConfig = AblServerConfig.getInstance(params);
@ -175,33 +177,30 @@ public class ABLMediaServerStatusManger {
}
private void online(MediaServer mediaServer, AblServerConfig config) {
if (config == null) {
ABLResult ablResult = ablResTfulUtils.getServerConfig(mediaServer);
JSONArray data = ablResult.getParams();
if (data != null && !data.isEmpty()) {
config = AblServerConfig.getInstance(data);
}else {
log.info("[ABL-连接成功] 读取流媒体配置失败 ID{}, 地址: {}:{}", mediaServer.getId(), mediaServer.getIp(), mediaServer.getHttpPort());
return;
}
}
offlineABLPrimaryMap.remove(mediaServer.getId());
offlineAblsecondaryMap.remove(mediaServer.getId());
offlineAblTimeMap.remove(mediaServer.getId());
if (!mediaServer.isStatus()) {
logger.info("[ABL-连接成功] ID{}, 地址: {}:{}", mediaServer.getId(), mediaServer.getIp(), mediaServer.getHttpPort());
mediaServer.setStatus(true);
mediaServer.setHookAliveInterval(10F);
mediaServerService.update(mediaServer);
if(mediaServer.isAutoConfig()) {
if (config == null) {
ABLResult ablResult = ablResTfulUtils.getServerConfig(mediaServer);
JSONArray data = ablResult.getParams();
if (data != null && !data.isEmpty()) {
config = AblServerConfig.getInstance(data);
}
}
if (config != null) {
initPort(mediaServer, config);
setAblConfig(mediaServer, false, config);
}
}
mediaServerService.update(mediaServer);
}
log.info("[ABL-连接成功] ID{}, 地址: {}:{}", mediaServer.getId(), mediaServer.getIp(), mediaServer.getHttpPort());
mediaServer.setStatus(true);
mediaServer.setHookAliveInterval(10F);
initPort(mediaServer, config);
// 发送上线通知
eventPublisher.mediaServerOnlineEventPublish(mediaServer);
mediaServerService.update(mediaServer);
// 设置两次心跳未收到则认为zlm离线
String key = "ABL-keepalive-" + mediaServer.getId();
dynamicTask.startDelay(key, ()->{
logger.warn("[ABL-心跳超时] ID{}", mediaServer.getId());
log.warn("[ABL-心跳超时] ID{}", mediaServer.getId());
mediaServer.setStatus(false);
offlineABLPrimaryMap.put(mediaServer.getId(), mediaServer);
offlineAblTimeMap.put(mediaServer.getId(), System.currentTimeMillis());
@ -238,16 +237,16 @@ public class ABLMediaServerStatusManger {
public void setAblConfig(MediaServer mediaServerItem, boolean restart, AblServerConfig config) {
try {
if (config.getHookEnable() == 0) {
logger.info("[媒体服务节点-ABL] 开启HOOK功能 {}", mediaServerItem.getId());
log.info("[媒体服务节点-ABL] 开启HOOK功能 {}", mediaServerItem.getId());
ABLResult ablResult = ablResTfulUtils.setConfigParamValue(mediaServerItem, "hook_enable", "1");
if (ablResult.getCode() == 0) {
logger.info("[媒体服务节点-ABL] 开启HOOK功能成功 {}", mediaServerItem.getId());
log.info("[媒体服务节点-ABL] 开启HOOK功能成功 {}", mediaServerItem.getId());
}else {
logger.info("[媒体服务节点-ABL] 开启HOOK功能失败 {}->{}", mediaServerItem.getId(), ablResult.getMemo());
log.info("[媒体服务节点-ABL] 开启HOOK功能失败 {}->{}", mediaServerItem.getId(), ablResult.getMemo());
}
}
}catch (Exception e) {
logger.info("[媒体服务节点-ABL] 开启HOOK功能失败 {}", mediaServerItem.getId(), e);
log.info("[媒体服务节点-ABL] 开启HOOK功能失败 {}", mediaServerItem.getId(), e);
}
// 设置相关的HOOK
String[] hookUrlArray = {
@ -280,16 +279,16 @@ public class ABLMediaServerStatusManger {
if (!hookUrl.equals(field.get(config))) {
ABLResult ablResult = ablResTfulUtils.setConfigParamValue(mediaServerItem, hook, hookUrl);
if (ablResult.getCode() == 0) {
logger.info("[媒体服务节点-ABL] 设置HOOK {} 成功 {}", hook, mediaServerItem.getId());
log.info("[媒体服务节点-ABL] 设置HOOK {} 成功 {}", hook, mediaServerItem.getId());
}else {
logger.info("[媒体服务节点-ABL] 设置HOOK {} 失败 {}->{}", hook, mediaServerItem.getId(), ablResult.getMemo());
log.info("[媒体服务节点-ABL] 设置HOOK {} 失败 {}->{}", hook, mediaServerItem.getId(), ablResult.getMemo());
}
}
}
}
}
}catch (Exception e) {
logger.info("[媒体服务节点-ABL] 设置HOOK 失败 {}", mediaServerItem.getId(), e);
log.info("[媒体服务节点-ABL] 设置HOOK 失败 {}", mediaServerItem.getId(), e);
}
}
@ -342,15 +341,15 @@ public class ABLMediaServerStatusManger {
//
// if (responseJSON != null && responseJSON.getInteger("code") == 0) {
// if (restart) {
// logger.info("[媒体服务节点] 设置成功,开始重启以保证配置生效 {} -> {}:{}",
// log.info("[媒体服务节点] 设置成功,开始重启以保证配置生效 {} -> {}:{}",
// mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
// ablResTfulUtils.restartServer(mediaServerItem);
// }else {
// logger.info("[媒体服务节点] 设置成功 {} -> {}:{}",
// log.info("[媒体服务节点] 设置成功 {} -> {}:{}",
// mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
// }
// }else {
// logger.info("[媒体服务节点] 设置媒体服务节点失败 {} -> {}:{}",
// log.info("[媒体服务节点] 设置媒体服务节点失败 {} -> {}:{}",
// mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
// }
}

View File

@ -22,7 +22,7 @@ public interface IMediaServerService {
List<MediaServer> getAll();
List<MediaServer> getAllFromDatabase();
List<MediaServer> getAllFromDatabaseWithOutDefault();
List<MediaServer> getAllOnline();
@ -175,4 +175,7 @@ public interface IMediaServerService {
DownloadFileInfo getDownloadFilePath(MediaServer mediaServer, RecordInfo recordInfo);
void loadMP4File(MediaServer mediaServer, String app, String stream, String filePath, String fileName, ErrorCallback<StreamInfo> callback);
void deleteDefault();
}

View File

@ -340,7 +340,12 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override
public void update(MediaServer mediaSerItem) {
mediaServerMapper.update(mediaSerItem);
if (mediaServerMapper.queryOne(mediaSerItem.getId(), userSetting.getServerId()) != null) {
mediaServerMapper.update(mediaSerItem);
}else {
mediaServerMapper.add(mediaSerItem);
}
MediaServer mediaServerInRedis = getOne(mediaSerItem.getId());
// 获取完整数据
MediaServer mediaServerInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId(), userSetting.getServerId());
@ -409,8 +414,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override
public List<MediaServer> getAllFromDatabase() {
return mediaServerMapper.queryAll(userSetting.getServerId());
public List<MediaServer> getAllFromDatabaseWithOutDefault() {
return mediaServerMapper.queryAllWithOutDefault(userSetting.getServerId());
}
@Override
@ -441,7 +446,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
return null;
}
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId();
return (MediaServer) redisTemplate.opsForHash().get(key, mediaServerId);
MediaServer mediaServer = (MediaServer) redisTemplate.opsForHash().get(key, mediaServerId);
if (mediaServer == null) {
// 尝试从数据库获取
mediaServer = mediaServerMapper.queryOne(mediaServerId, userSetting.getServerId());
if (mediaServer != null) {
redisTemplate.opsForHash().put(key, mediaServer.getId(), mediaServer);
}
}
return mediaServer;
}
/**
@ -992,6 +1005,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
mediaNodeServerService.loadMP4File(mediaServer, app, stream, filePath, fileName, callback);
}
@Override
public void deleteDefault() {
mediaServerMapper.deleteDefault(userSetting.getServerId());
}
@Override
public void seekRecordStamp(MediaServer mediaServer, String app, String stream, Double stamp, String schema) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.media.zlm;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.bean.ResultForOnPublish;
@ -26,6 +27,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @description:针对 ZLMediaServer的hook事件监听
@ -44,6 +46,9 @@ public class ZLMHttpHookListener {
@Autowired
private IMediaService mediaService;
@Autowired
private MediaConfig mediaConfig;
@Autowired
private UserSetting userSetting;
@ -226,13 +231,19 @@ public class ZLMHttpHookListener {
jsonObject.put("ip", request.getRemoteAddr());
ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject);
zlmServerConfig.setIp(request.getRemoteAddr());
log.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId());
log.info("[ZLM HOOK] zlm 启动 {}", zlmServerConfig.getGeneralMediaServerId());
try {
HookZlmServerStartEvent event = new HookZlmServerStartEvent(this);
MediaServer mediaServerItem = mediaServerService.getOne(zlmServerConfig.getMediaServerId());
if (mediaServerItem != null) {
event.setMediaServerItem(mediaServerItem);
MediaServer mediaServer = mediaServerService.getOne(zlmServerConfig.getMediaServerId());
if (mediaServer == null && Objects.equals(mediaConfig.getId(), zlmServerConfig.getGeneralMediaServerId())) {
mediaServer = mediaConfig.buildMediaSer();
}
if (mediaServer != null) {
event.setMediaServer(mediaServer);
event.setConfig(zlmServerConfig);
applicationEventPublisher.publishEvent(event);
}else {
log.info("[ZLM HOOK] 此zlm未接入 {}", zlmServerConfig.getGeneralMediaServerId());
}
}catch (Exception e) {
log.info("[ZLM-HOOK-ZLM启动] 发送通知失败 ", e);

View File

@ -73,7 +73,7 @@ public class ZLMMediaServerStatusManager {
if (!type.equals(mediaServerItem.getType())) {
continue;
}
log.info("[ZLM-添加待上线节点] ID" + mediaServerItem.getId());
log.info("[ZLM-添加待上线节点] ID{}", mediaServerItem.getId());
offlineZlmPrimaryMap.put(mediaServerItem.getId(), mediaServerItem);
offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
execute();
@ -83,17 +83,13 @@ public class ZLMMediaServerStatusManager {
@Async("taskExecutor")
@EventListener
public void onApplicationEvent(HookZlmServerStartEvent event) {
if (event.getMediaServerItem() == null
|| !type.equals(event.getMediaServerItem().getType())
|| event.getMediaServerItem().isStatus()) {
if (event.getMediaServer() == null
|| !type.equals(event.getMediaServer().getType())
|| event.getMediaServer().isStatus()) {
return;
}
MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
if (serverItem == null) {
return;
}
log.info("[ZLM-HOOK事件-服务启动] ID" + event.getMediaServerItem().getId());
online(serverItem, null);
log.info("[ZLM-HOOK事件-服务启动] ID{}", event.getMediaServer().getId());
online(event.getMediaServer(), event.getConfig());
}
@Async("taskExecutor")
@ -102,12 +98,12 @@ public class ZLMMediaServerStatusManager {
if (event.getMediaServerItem() == null) {
return;
}
MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
if (serverItem == null) {
MediaServer mediaServer = mediaServerService.getOne(event.getMediaServerItem().getId());
if (mediaServer == null) {
return;
}
log.debug("[ZLM-HOOK事件-心跳] ID" + event.getMediaServerItem().getId());
online(serverItem, null);
log.debug("[ZLM-HOOK事件-心跳] ID{}", event.getMediaServerItem().getId());
online(mediaServer, null);
}
@Async("taskExecutor")
@ -179,70 +175,49 @@ public class ZLMMediaServerStatusManager {
}
}
private void online(MediaServer mediaServerItem, ZLMServerConfig config) {
offlineZlmPrimaryMap.remove(mediaServerItem.getId());
offlineZlmsecondaryMap.remove(mediaServerItem.getId());
offlineZlmTimeMap.remove(mediaServerItem.getId());
if (!mediaServerItem.isStatus()) {
log.info("[ZLM-连接成功] ID{}, 地址: {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
mediaServerItem.setStatus(true);
mediaServerItem.setHookAliveInterval(10F);
// 发送上线通知
eventPublisher.mediaServerOnlineEventPublish(mediaServerItem);
if(mediaServerItem.isAutoConfig()) {
if (config == null) {
ZLMResult<List<JSONObject>> mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
List<JSONObject> data = mediaServerConfig.getData();
if (data != null && !data.isEmpty()) {
config = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
}
}
if (config != null) {
initPort(mediaServerItem, config);
setZLMConfig(mediaServerItem, "0".equals(config.getHookEnable())
|| !Objects.equals(mediaServerItem.getHookAliveInterval(), config.getHookAliveInterval()));
}
private void online(MediaServer mediaServer, ZLMServerConfig config) {
if (config == null) {
ZLMResult<List<JSONObject>> mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(mediaServer);
List<JSONObject> data = mediaServerConfig.getData();
if (data != null && !data.isEmpty()) {
config = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
}else {
log.info("[ZLM-连接成功] 读取流媒体配置失败 ID{}, 地址: {}:{}", mediaServer.getId(), mediaServer.getIp(), mediaServer.getHttpPort());
return;
}
mediaServerService.update(mediaServerItem);
}
offlineZlmPrimaryMap.remove(mediaServer.getId());
offlineZlmsecondaryMap.remove(mediaServer.getId());
offlineZlmTimeMap.remove(mediaServer.getId());
mediaServer.setStatus(true);
mediaServer.setHookAliveInterval(config.getHookAliveInterval());
initPort(mediaServer, config);
log.info("[ZLM-连接成功] ID{}, 地址: {}:{}", mediaServer.getId(), mediaServer.getIp(), mediaServer.getHttpPort());
// 发送上线通知
eventPublisher.mediaServerOnlineEventPublish(mediaServer);
mediaServerService.update(mediaServer);
// 设置两次心跳未收到则认为zlm离线
String key = "zlm-keepalive-" + mediaServerItem.getId();
String key = "zlm-keepalive-" + mediaServer.getId();
dynamicTask.startDelay(key, ()->{
log.warn("[ZLM-心跳超时] ID{}", mediaServerItem.getId());
mediaServerItem.setStatus(false);
offlineZlmPrimaryMap.put(mediaServerItem.getId(), mediaServerItem);
offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
log.warn("[ZLM-心跳超时] ID{}", mediaServer.getId());
mediaServer.setStatus(false);
offlineZlmPrimaryMap.put(mediaServer.getId(), mediaServer);
offlineZlmTimeMap.put(mediaServer.getId(), System.currentTimeMillis());
// 发送离线通知
eventPublisher.mediaServerOfflineEventPublish(mediaServerItem);
mediaServerService.update(mediaServerItem);
}, (int)(mediaServerItem.getHookAliveInterval() * 2 * 1000));
eventPublisher.mediaServerOfflineEventPublish(mediaServer);
mediaServerService.update(mediaServer);
}, (int)(mediaServer.getHookAliveInterval() * 2 * 1000));
}
private void initPort(MediaServer mediaServerItem, ZLMServerConfig zlmServerConfig) {
// 端口只会从配置中读取一次一旦自己配置或者读取过了将不在配置
if (mediaServerItem.getHttpSSlPort() == 0) {
mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
}
if (mediaServerItem.getRtmpPort() == 0) {
mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort());
}
if (mediaServerItem.getRtmpSSlPort() == 0) {
mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
}
if (mediaServerItem.getRtspPort() == 0) {
mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort());
}
if (mediaServerItem.getRtspSSLPort() == 0) {
mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
}
if (mediaServerItem.getRtpProxyPort() == 0) {
mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
}
if (mediaServerItem.getFlvSSLPort() == 0) {
mediaServerItem.setFlvSSLPort(zlmServerConfig.getHttpSSLport());
}
if (mediaServerItem.getWsFlvSSLPort() == 0) {
mediaServerItem.setWsFlvSSLPort(zlmServerConfig.getHttpSSLport());
}
mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort());
mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort());
mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
mediaServerItem.setFlvSSLPort(zlmServerConfig.getHttpSSLport());
mediaServerItem.setWsFlvSSLPort(zlmServerConfig.getHttpSSLport());
if (Objects.isNull(zlmServerConfig.getTranscodeSuffix())) {
mediaServerItem.setTranscodeSuffix(null);
}else {

View File

@ -1,24 +1,23 @@
package com.genersoft.iot.vmp.media.zlm.event;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
/**
* zlm server_start事件
*/
@Setter
@Getter
public class HookZlmServerStartEvent extends ApplicationEvent {
public HookZlmServerStartEvent(Object source) {
super(source);
}
private MediaServer mediaServerItem;
private MediaServer mediaServer;
private ZLMServerConfig config;
public MediaServer getMediaServerItem() {
return mediaServerItem;
}
public void setMediaServerItem(MediaServer mediaServerItem) {
this.mediaServerItem = mediaServerItem;
}
}

View File

@ -86,34 +86,15 @@ public interface MediaServerMapper {
@Update(value = {" <script>" +
"UPDATE wvp_media_server " +
"SET update_time=#{updateTime}, transcode_suffix=#{transcodeSuffix} " +
"<if test=\"ip != null\">, ip=#{ip}</if>" +
"<if test=\"hookIp != null\">, hook_ip=#{hookIp}</if>" +
"<if test=\"sdpIp != null\">, sdp_ip=#{sdpIp}</if>" +
"<if test=\"streamIp != null\">, stream_ip=#{streamIp}</if>" +
"<if test=\"httpPort != null\">, http_port=#{httpPort}</if>" +
"<if test=\"httpSSlPort != null\">, http_ssl_port=#{httpSSlPort}</if>" +
"<if test=\"rtmpPort != null\">, rtmp_port=#{rtmpPort}</if>" +
"<if test=\"rtmpSSlPort != null\">, rtmp_ssl_port=#{rtmpSSlPort}</if>" +
"<if test=\"rtpProxyPort != null\">, rtp_proxy_port=#{rtpProxyPort}</if>" +
"<if test=\"jttProxyPort != null\">, jtt_proxy_port=#{jttProxyPort}</if>" +
"<if test=\"rtspPort != null\">, rtsp_port=#{rtspPort}</if>" +
"<if test=\"rtspSSLPort != null\">, rtsp_ssl_port=#{rtspSSLPort}</if>" +
"<if test=\"flvPort != null\">, flv_port=#{flvPort}</if>" +
"<if test=\"mp4Port != null\">, mp4_port=#{mp4Port}</if>" +
"<if test=\"flvSSLPort != null\">, flv_ssl_port=#{flvSSLPort}</if>" +
"<if test=\"wsFlvPort != null\">, ws_flv_port=#{wsFlvPort}</if>" +
"<if test=\"wsFlvSSLPort != null\">, ws_flv_ssl_port=#{wsFlvSSLPort}</if>" +
"<if test=\"autoConfig != null\">, auto_config=#{autoConfig}</if>" +
"<if test=\"rtpEnable != null\">, rtp_enable=#{rtpEnable}</if>" +
"<if test=\"rtpPortRange != null\">, rtp_port_range=#{rtpPortRange}</if>" +
"<if test=\"sendRtpPortRange != null\">, send_rtp_port_range=#{sendRtpPortRange}</if>" +
"<if test=\"secret != null\">, secret=#{secret}</if>" +
"<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" +
"<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
"<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
"<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
"<if test=\"serverId != null\">, server_id=#{serverId}</if>" +
"<if test=\"type != null\">, type=#{type}</if>" +
", ip=#{ip}, hook_ip=#{hookIp}, sdp_ip=#{sdpIp}, stream_ip=#{streamIp}, http_port=#{httpPort}" +
", http_ssl_port=#{httpSSlPort}, rtmp_port=#{rtmpPort}, rtmp_ssl_port=#{rtmpSSlPort}" +
", rtp_proxy_port=#{rtpProxyPort}, jtt_proxy_port=#{jttProxyPort}, rtsp_port=#{rtspPort}" +
", rtsp_ssl_port=#{rtspSSLPort}, flv_port=#{flvPort}, mp4_port=#{mp4Port}" +
", flv_ssl_port=#{flvSSLPort}, ws_flv_port=#{wsFlvPort}, ws_flv_ssl_port=#{wsFlvSSLPort}" +
", auto_config=#{autoConfig}, rtp_enable=#{rtpEnable}, rtp_port_range=#{rtpPortRange}" +
", send_rtp_port_range=#{sendRtpPortRange}, secret=#{secret}, record_assist_port=#{recordAssistPort}" +
", hook_alive_interval=#{hookAliveInterval}, record_day=#{recordDay}, record_path=#{recordPath}" +
", server_id=#{serverId}, type=#{type}" +
"WHERE id=#{id}"+
" </script>"})
int update(MediaServer mediaServerItem);
@ -159,6 +140,9 @@ public interface MediaServerMapper {
@Select("SELECT * FROM wvp_media_server where server_id = #{serverId}")
List<MediaServer> queryAll(@Param("serverId") String serverId);
@Select("SELECT * FROM wvp_media_server where default_server=false AND server_id = #{serverId}")
List<MediaServer> queryAllWithOutDefault(@Param("serverId") String serverId);
@Delete("DELETE FROM wvp_media_server WHERE id=#{id} and server_id = #{serverId}")
void delOne(String id, @Param("serverId") String serverId);
@ -171,4 +155,6 @@ public interface MediaServerMapper {
@Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0 and server_id = #{serverId}")
List<MediaServer> queryAllWithAssistPort(@Param("serverId") String serverId);
@Delete("DELETE FROM wvp_media_server WHERE default_server=true and server_id = #{serverId}")
void deleteDefault(@Param("serverId") String serverId);
}

View File

@ -73,7 +73,7 @@ sip:
domain: 4101050000
# [可选]
id: 41010500002000000001
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
# [可选] 公共认证密码 移除密码将必须提前添加设备才能通过认证
password: 12345678
# 是否存储alarm信息
alarm: false

View File

@ -46,7 +46,7 @@ sip:
domain: ${WVP_DOMAIN:4401020049}
# [可选]
id: ${WVP_ID:44010200492000000001}
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
# [可选] 公共认证密码 移除密码将必须提前添加设备才能通过认证
password: ${WVP_PWD:admin123}
#zlm 默认服务器配置

View File

@ -861,7 +861,7 @@
320623,如东县,3206
320681,启东市,3206
320682,如皋市,3206
320684,海门,3206
320684,海门,3206
320685,海安市,3206
3207,连云港市,32
320703,连云区,3207
@ -918,8 +918,6 @@
33,浙江省,
3301,杭州市,33
330102,上城区,3301
330103,下城区,3301
330104,江干区,3301
330105,拱墅区,3301
330106,西湖区,3301
330108,滨江区,3301
@ -927,6 +925,8 @@
330110,余杭区,3301
330111,富阳区,3301
330112,临安区,3301
330113,临平区,3301
330114,钱塘区,3301
330122,桐庐县,3301
330127,淳安县,3301
330182,建德市,3301

1 编号 名称 上级
861 320623 如东县 3206
862 320681 启东市 3206
863 320682 如皋市 3206
864 320684 海门市 海门区 3206
865 320685 海安市 3206
866 3207 连云港市 32
867 320703 连云区 3207
918 33 浙江省
919 3301 杭州市 33
920 330102 上城区 3301
330103 下城区 3301
330104 江干区 3301
921 330105 拱墅区 3301
922 330106 西湖区 3301
923 330108 滨江区 3301
925 330110 余杭区 3301
926 330111 富阳区 3301
927 330112 临安区 3301
928 330113 临平区 3301
929 330114 钱塘区 3301
930 330122 桐庐县 3301
931 330127 淳安县 3301
932 330182 建德市 3301

View File

@ -95,7 +95,7 @@ server:
# 作为28181服务器的配置
sip:
# [必须修改] 本机的IP对应你的网卡监听什么ip就是使用什么网卡
# [可选] 监听网卡监听什么ip就是使用什么网卡不配置则自动获取本机所有网卡推荐不配置系统自动获取
# 如果要监听多张网卡可以使用逗号分隔多个IP 例如: 192.168.1.4,10.0.0.4
# 如果不明白就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1任何包括localhost在内的域名都是不可以的。
@ -111,7 +111,7 @@ sip:
domain: 4401020049
# [可选]
id: 44010200492000000001
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
# [可选] 公共认证密码 移除密码将必须提前添加设备才能通过认证
password: admin123
# [可选] 国标级联注册失败,再次发起注册的时间间隔。 默认60秒
register-time-interval: 60