648540858
2022-11-17 d340a37a00c8d5ea2605ca0f40a920efbeb9546f
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -1,19 +1,19 @@
package com.genersoft.iot.vmp.media.zlm;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.*;
import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -24,18 +24,15 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**    
 * @description:针对 ZLMediaServer的hook事件监听
@@ -183,42 +180,45 @@
      JSONObject ret = new JSONObject();
      String mediaServerId = json.getString("mediaServerId");
      MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
      if (!"rtp".equals(param.getApp())) {
         // 推流鉴权
         if (param.getParams() == null) {
            logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
            ret.put("code", 401);
            ret.put("msg", "Unauthorized");
            return ret;
         }
         Map<String, String> paramMap = urlParamToMap(param.getParams());
         String sign = paramMap.get("sign");
         if (sign == null) {
            logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
            ret.put("code", 401);
            ret.put("msg", "Unauthorized");
            return ret;
         }
         // 推流自定义播放鉴权码
         String callId = paramMap.get("callId");
         // 鉴权配置
         boolean hasAuthority = userService.checkPushAuthority(callId, sign);
         if (!hasAuthority) {
            logger.info("推流鉴权失败: sign 无权限: callId={}. sign={}", callId, sign);
            ret.put("code", 401);
            ret.put("msg", "Unauthorized");
            return ret;
         }
         StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
         streamAuthorityInfo.setCallId(callId);
         streamAuthorityInfo.setSign(sign);
         // 鉴权通过
         redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
         // 通知assist新的callId
         if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {
            taskExecutor.execute(()->{
               assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
            });
         if (userSetting.getPushAuthority()) {
            // 推流鉴权
            if (param.getParams() == null) {
               logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
               ret.put("code", 401);
               ret.put("msg", "Unauthorized");
               return ret;
            }
            Map<String, String> paramMap = urlParamToMap(param.getParams());
            String sign = paramMap.get("sign");
            if (sign == null) {
               logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
               ret.put("code", 401);
               ret.put("msg", "Unauthorized");
               return ret;
            }
            // 推流自定义播放鉴权码
            String callId = paramMap.get("callId");
            // 鉴权配置
            boolean hasAuthority = userService.checkPushAuthority(callId, sign);
            if (!hasAuthority) {
               logger.info("推流鉴权失败: sign 无权限: callId={}. sign={}", callId, sign);
               ret.put("code", 401);
               ret.put("msg", "Unauthorized");
               return ret;
            }
            StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
            streamAuthorityInfo.setCallId(callId);
            streamAuthorityInfo.setSign(sign);
            // 鉴权通过
            redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
            // 通知assist新的callId
            if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {
               taskExecutor.execute(()->{
                  assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
               });
            }
         }
      }else {
         zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId());
@@ -226,7 +226,6 @@
      ret.put("code", 0);
      ret.put("msg", "success");
      ret.put("enable_hls", false);
      if (!"rtp".equals(param.getApp())) {
         ret.put("enable_audio", true);
@@ -569,6 +568,8 @@
   public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
      jsonObject.put("ip", request.getRemoteAddr());
      System.out.println(jsonObject.toJSONString()
      );
      ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject);
      zlmServerConfig.setIp(request.getRemoteAddr());
      logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId());
@@ -625,6 +626,32 @@
      return ret;
   }
   /**
    * rtpServer收流超时
    */
   @ResponseBody
   @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8")
   public JSONObject onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam param){
      System.out.println(param);
      logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc());
      JSONObject ret = new JSONObject();
      ret.put("code", 0);
      ret.put("msg", "success");
      taskExecutor.execute(()->{
         JSONObject json = (JSONObject) JSON.toJSON(param);
         List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);
         if (subscribes != null  && subscribes.size() > 0) {
            for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
               subscribe.response(null, json);
            }
         }
      });
      return ret;
   }
   private Map<String, String> urlParamToMap(String params) {
      HashMap<String, String> map = new HashMap<>();
      if (ObjectUtils.isEmpty(params)) {