From 82adc0cb23f3ee47322e78889cdaba57e9309000 Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期二, 21 三月 2023 15:55:24 +0800
Subject: [PATCH] 完善语音对讲级联

---
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java |  833 ++++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 596 insertions(+), 237 deletions(-)

diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
index 19908e4..c89279a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -1,35 +1,39 @@
 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
 
-import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson2.JSONObject;
+import com.genersoft.iot.vmp.common.VideoManagerConstants;
 import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
+import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
+import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
-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.gb28181.transmit.cmd.ISIPCommanderForPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
-import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
+import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
-import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
-import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.service.IPlayService;
-import com.genersoft.iot.vmp.service.IStreamPushService;
+import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
+import com.genersoft.iot.vmp.media.zlm.dto.*;
+import com.genersoft.iot.vmp.service.*;
 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
-import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener;
+import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
+import com.genersoft.iot.vmp.service.redisMsg.RedisPushStreamResponseListener;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
-import com.genersoft.iot.vmp.utils.SerializeUtils;
 import gov.nist.javax.sdp.TimeDescriptionImpl;
 import gov.nist.javax.sdp.fields.TimeField;
+import gov.nist.javax.sip.message.SIPRequest;
+import gov.nist.javax.sip.message.SIPResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
@@ -37,13 +41,14 @@
 import org.springframework.stereotype.Component;
 
 import javax.sdp.*;
-import javax.sip.*;
-import javax.sip.address.SipURI;
+import javax.sip.InvalidArgumentException;
+import javax.sip.RequestEvent;
+import javax.sip.SipException;
 import javax.sip.header.CallIdHeader;
-import javax.sip.message.Request;
 import javax.sip.message.Response;
 import java.text.ParseException;
 import java.time.Instant;
+import java.util.Random;
 import java.util.Vector;
 
 /**
@@ -58,7 +63,7 @@
     private final String method = "INVITE";
 
     @Autowired
-    private SIPCommanderFroPlatform cmderFroPlatform;
+    private ISIPCommanderForPlatform cmderFroPlatform;
 
     @Autowired
     private IVideoManagerStorage storager;
@@ -67,25 +72,40 @@
     private IStreamPushService streamPushService;
 
     @Autowired
+    private IStreamProxyService streamProxyService;
+
+    @Autowired
     private IRedisCatchStorage redisCatchStorage;
 
     @Autowired
     private DynamicTask dynamicTask;
 
     @Autowired
-    private SIPCommander cmder;
+    private RedisPushStreamResponseListener redisPushStreamResponseListener;
 
     @Autowired
     private IPlayService playService;
 
     @Autowired
-    private ISIPCommander commander;
+    private SIPSender sipSender;
+
+	@Autowired
+	private AudioBroadcastManager audioBroadcastManager;
 
     @Autowired
     private ZLMRTPServerFactory zlmrtpServerFactory;
 
     @Autowired
     private IMediaServerService mediaServerService;
+
+    @Autowired
+    private ISIPCommander commander;
+
+	@Autowired
+	private ZLMRESTfulUtils zlmresTfulUtils;
+
+    @Autowired
+    private ZlmHttpHookSubscribe zlmHttpHookSubscribe;
 
     @Autowired
     private SIPProcessorObserver sipProcessorObserver;
@@ -98,6 +118,19 @@
 
     @Autowired
     private ZLMMediaListManager mediaListManager;
+
+	@Autowired
+	private DeferredResultHolder resultHolder;
+
+	@Autowired
+	private ZlmHttpHookSubscribe subscribe;
+
+	@Autowired
+	private SipConfig config;
+
+    @Autowired
+    private VideoStreamSessionManager streamSession;
+
 
 
     @Autowired
@@ -119,24 +152,48 @@
     public void process(RequestEvent evt) {
         //  Invite Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傝棰戞寚浠�
         try {
-            Request request = evt.getRequest();
-            SipURI sipUri = (SipURI) request.getRequestURI();
-            //浠巗ubject璇诲彇channelId,涓嶅啀浠巖equest-line璇诲彇銆� 鏈変簺骞冲彴request-line鏄钩鍙板浗鏍囩紪鐮侊紝涓嶆槸璁惧鍥芥爣缂栫爜銆�
-            //String channelId = sipURI.getUser();
-            String channelId = SipUtils.getChannelIdFromHeader(request);
+            SIPRequest request = (SIPRequest)evt.getRequest();
+            String channelId = SipUtils.getChannelIdFromRequest(request);
             String requesterId = SipUtils.getUserIdFromFromHeader(request);
             CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
             if (requesterId == null || channelId == null) {
                 logger.info("鏃犳硶浠嶧romHeader鐨凙ddress涓幏鍙栧埌骞冲彴id锛岃繑鍥�400");
                 // 鍙傛暟涓嶅叏锛� 鍙�400锛岃姹傞敊璇�
-                responseAck(evt, Response.BAD_REQUEST);
+                try {
+                    responseAck(request, Response.BAD_REQUEST);
+                } catch (SipException | InvalidArgumentException | ParseException e) {
+                    logger.error("[鍛戒护鍙戦�佸け璐 invite BAD_REQUEST: {}", e.getMessage());
+                }
                 return;
             }
+            String ssrc = null;
+            SessionDescription sdp = null;
+            String ssrcDefault = "0000000000";
+            if (channelId == null) {
+                // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡
+                String contentString = new String(request.getRawContent());
+
+                // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎浠ヨВ鏋愩��
+                int ssrcIndex = contentString.indexOf("y=");
+
+                if (ssrcIndex >= 0) {
+                    //ssrc瑙勫畾闀垮害涓�10涓瓧鑺傦紝涓嶅彇浣欎笅闀垮害浠ラ伩鍏嶅悗缁繕鏈夆�渇=鈥濆瓧娈�
+                    ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
+                    String substring = contentString.substring(0, contentString.indexOf("y="));
+                    sdp = SdpFactory.getInstance().createSessionDescription(substring);
+                } else {
+                    ssrc = ssrcDefault;
+                    sdp = SdpFactory.getInstance().createSessionDescription(contentString);
+                }
+                channelId = sdp.getOrigin().getUsername();
+            }
+
 
             // 鏌ヨ璇锋眰鏄惁鏉ヨ嚜涓婄骇骞冲彴\璁惧
             ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
             if (platform == null) {
-                inviteFromDeviceHandle(evt, requesterId);
+                inviteFromDeviceHandle(request, requesterId, channelId);
+
             } else {
                 // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾
                 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
@@ -145,14 +202,15 @@
 
                 MediaServerItem mediaServerItem = null;
                 StreamPushItem streamPushItem = null;
+                StreamProxyItem proxyByAppAndStream = null;
                 // 涓嶆槸閫氶亾鍙兘鏄洿鎾祦
                 if (channel != null && gbStream == null) {
-                    if (channel.getStatus() == 0) {
-                        logger.info("閫氶亾绂荤嚎锛岃繑鍥�400");
-                        responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
-                        return;
+                    // 閫氶亾瀛樺湪锛屽彂100锛孴RYING
+                    try {
+                        responseAck(request, Response.TRYING);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite TRYING: {}", e.getMessage());
                     }
-                    responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑
                 } else if (channel == null && gbStream != null) {
 
                     String mediaServerId = gbStream.getMediaServerId();
@@ -160,13 +218,21 @@
                     if (mediaServerItem == null) {
                         if ("proxy".equals(gbStream.getStreamType())) {
                             logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
-                            responseAck(evt, Response.GONE);
+                            try {
+                                responseAck(request, Response.GONE);
+                            } catch (SipException | InvalidArgumentException | ParseException e) {
+                                logger.error("[鍛戒护鍙戦�佸け璐 invite GONE: {}", e.getMessage());
+                            }
                             return;
                         } else {
                             streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
                             if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) {
                                 logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
-                                responseAck(evt, Response.GONE);
+                                try {
+                                    responseAck(request, Response.GONE);
+                                } catch (SipException | InvalidArgumentException | ParseException e) {
+                                    logger.error("[鍛戒护鍙戦�佸け璐 invite GONE: {}", e.getMessage());
+                                }
                                 return;
                             }
                         }
@@ -175,38 +241,66 @@
                             streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
                             if (streamPushItem == null) {
                                 logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
-                                responseAck(evt, Response.GONE);
+                                try {
+                                    responseAck(request, Response.GONE);
+                                } catch (SipException | InvalidArgumentException | ParseException e) {
+                                    logger.error("[鍛戒护鍙戦�佸け璐 invite GONE: {}", e.getMessage());
+                                }
+                                return;
+                            }
+                        }else if("proxy".equals(gbStream.getStreamType())){
+                            proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
+                            if (proxyByAppAndStream == null) {
+                                logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
+                                try {
+                                    responseAck(request, Response.GONE);
+                                } catch (SipException | InvalidArgumentException | ParseException e) {
+                                    logger.error("[鍛戒护鍙戦�佸け璐 invite GONE: {}", e.getMessage());
+                                }
                                 return;
                             }
                         }
                     }
-                    responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑
+                    try {
+                        responseAck(request, Response.CALL_IS_BEING_FORWARDED);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite CALL_IS_BEING_FORWARDED: {}", e.getMessage());
+                    }
                 } else if (catalog != null) {
-                    responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 鐩綍涓嶆敮鎸佺偣鎾�
+                    try {
+                        // 鐩綍涓嶆敮鎸佺偣鎾�
+                        responseAck(request, Response.BAD_REQUEST, "catalog channel can not play");
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 鐩綍涓嶆敮鎸佺偣鎾�: {}", e.getMessage());
+                    }
                     return;
                 } else {
-                    logger.info("閫氶亾涓嶅瓨鍦紝杩斿洖404");
-                    responseAck(evt, Response.NOT_FOUND); // 閫氶亾涓嶅瓨鍦紝鍙�404锛岃祫婧愪笉瀛樺湪
+                    logger.info("閫氶亾涓嶅瓨鍦紝杩斿洖404: {}", channelId);
+                    try {
+                        // 閫氶亾涓嶅瓨鍦紝鍙�404锛岃祫婧愪笉瀛樺湪
+                        responseAck(request, Response.NOT_FOUND);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 閫氶亾涓嶅瓨鍦�: {}", e.getMessage());
+                    }
                     return;
                 }
-                // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡
-                String contentString = new String(request.getRawContent());
+                if (sdp == null || ssrc == null) {
+                    // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡
+                    String contentString = new String(request.getRawContent());
 
-                // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎浠ヨВ鏋愩��
-                int ssrcIndex = contentString.indexOf("y=");
-                // 妫�鏌ユ槸鍚︽湁y瀛楁
-                String ssrcDefault = "0000000000";
-                String ssrc;
-                SessionDescription sdp;
-                if (ssrcIndex >= 0) {
-                    //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈�
-                    ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
-                    String substring = contentString.substring(0, contentString.indexOf("y="));
-                    sdp = SdpFactory.getInstance().createSessionDescription(substring);
-                } else {
-                    ssrc = ssrcDefault;
-                    sdp = SdpFactory.getInstance().createSessionDescription(contentString);
+                    // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎浠ヨВ鏋愩��
+                    int ssrcIndex = contentString.indexOf("y=");
+                    if (ssrcIndex >= 0) {
+                        //ssrc瑙勫畾闀垮害涓�10涓瓧鑺傦紝涓嶅彇浣欎笅闀垮害浠ラ伩鍏嶅悗缁繕鏈夆�渇=鈥濆瓧娈�
+                        ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
+                        String substring = contentString.substring(0, contentString.indexOf("y="));
+                        sdp = SdpFactory.getInstance().createSessionDescription(substring);
+                    } else {
+                        ssrc = ssrcDefault;
+                        sdp = SdpFactory.getInstance().createSessionDescription(contentString);
+                    }
                 }
+
                 String sessionName = sdp.getSessionName().getValue();
 
                 Long startTime = null;
@@ -240,16 +334,13 @@
                         String protocol = media.getProtocol();
 
                         // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp
-                        if ("TCP/RTP/AVP".equals(protocol)) {
+                        if ("TCP/RTP/AVP".equalsIgnoreCase(protocol)) {
                             String setup = mediaDescription.getAttribute("setup");
                             if (setup != null) {
                                 mediaTransmissionTCP = true;
-                                if ("active".equals(setup)) {
+                                if ("active".equalsIgnoreCase(setup)) {
                                     tcpActive = true;
-                                    // 涓嶆敮鎸乼cp涓诲姩
-                                    responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 鐩綍涓嶆敮鎸佺偣鎾�
-                                    return;
-                                } else if ("passive".equals(setup)) {
+                                } else if ("passive".equalsIgnoreCase(setup)) {
                                     tcpActive = false;
                                 }
                             }
@@ -260,11 +351,16 @@
                 if (port == -1) {
                     logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415");
                     // 鍥炲涓嶆敮鎸佺殑鏍煎紡
-                    responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415
+                    try {
+                        // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415
+                        responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 涓嶆敮鎸佺殑鏍煎紡: {}", e.getMessage());
+                    }
                     return;
                 }
                 String username = sdp.getOrigin().getUsername();
-                String addressStr = sdp.getOrigin().getAddress();
+                String addressStr = sdp.getConnection().getAddress();
 
                 logger.info("[涓婄骇鐐规挱]鐢ㄦ埛锛歿}锛� 閫氶亾锛歿}, 鍦板潃锛歿}:{}锛� ssrc锛歿}", username, channelId, addressStr, port, ssrc);
                 Device device = null;
@@ -273,32 +369,45 @@
                     device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
                     if (device == null) {
                         logger.warn("鐐规挱骞冲彴{}鐨勯�氶亾{}鏃舵湭鎵惧埌璁惧淇℃伅", requesterId, channel);
-                        responseAck(evt, Response.SERVER_INTERNAL_ERROR);
+                        try {
+                            responseAck(request, Response.SERVER_INTERNAL_ERROR);
+                        } catch (SipException | InvalidArgumentException | ParseException e) {
+                            logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈壘鍒拌澶囦俊鎭�: {}", e.getMessage());
+                        }
                         return;
                     }
                     mediaServerItem = playService.getNewMediaServerItem(device);
                     if (mediaServerItem == null) {
                         logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm");
-                        responseAck(evt, Response.BUSY_HERE);
+                        try {
+                            responseAck(request, Response.BUSY_HERE);
+                        } catch (SipException | InvalidArgumentException | ParseException e) {
+                            logger.error("[鍛戒护鍙戦�佸け璐 invite BUSY_HERE: {}", e.getMessage());
+                        }
                         return;
                     }
                     SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
-                            device.getDeviceId(), channelId,
-                            mediaTransmissionTCP);
+                            device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp());
+
                     if (tcpActive != null) {
                         sendRtpItem.setTcpActive(tcpActive);
                     }
                     if (sendRtpItem == null) {
                         logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
-                        responseAck(evt, Response.BUSY_HERE);
+                        try {
+                            responseAck(request, Response.BUSY_HERE);
+                        } catch (SipException | InvalidArgumentException | ParseException e) {
+                            logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage());
+                        }
                         return;
                     }
                     sendRtpItem.setCallId(callIdHeader.getCallId());
-                    sendRtpItem.setPlayType("Play".equals(sessionName) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK);
+                    sendRtpItem.setPlayType("Play".equalsIgnoreCase(sessionName) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK);
 
                     Long finalStartTime = startTime;
                     Long finalStopTime = stopTime;
-                    ZLMHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> {
+                    String finalChannelId = channelId;
+                    ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> {
                         String app = responseJSON.getString("app");
                         String stream = responseJSON.getString("stream");
                         logger.info("[涓婄骇鐐规挱]涓嬬骇宸茬粡寮�濮嬫帹娴併�� 鍥炲200OK(SDP)锛� {}/{}", app, stream);
@@ -310,30 +419,44 @@
 
                         StringBuffer content = new StringBuffer(200);
                         content.append("v=0\r\n");
-                        content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
+                        content.append("o=" + finalChannelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
                         content.append("s=" + sessionName + "\r\n");
                         content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
-                        if ("Playback".equals(sessionName)) {
+                        if ("Playback".equalsIgnoreCase(sessionName)) {
                             content.append("t=" + finalStartTime + " " + finalStopTime + "\r\n");
                         } else {
                             content.append("t=0 0\r\n");
                         }
-                        content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n");
+                        int localPort = sendRtpItem.getLocalPort();
+                        if (localPort == 0) {
+                            // 闈炰弗鏍兼ā寮忕鍙d笉缁熶竴, 澧炲姞鍏煎鎬э紝淇敼涓轰竴涓笉涓�0鐨勭鍙�
+                            localPort = new Random().nextInt(65535) + 1;
+                        }
+                        content.append("m=video " + localPort + " RTP/AVP 96\r\n");
                         content.append("a=sendonly\r\n");
                         content.append("a=rtpmap:96 PS/90000\r\n");
-                        content.append("y=" + ssrc + "\r\n");
+                        content.append("y=" + sendRtpItem.getSsrc() + "\r\n");
                         content.append("f=\r\n");
 
                         try {
                             // 瓒呮椂鏈敹鍒癆ck搴旇鍥炲bye,褰撳墠绛夊緟鏃堕棿涓�10绉�
-                            dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
-                                logger.info("Ack 绛夊緟瓒呮椂");
-                                mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc);
-                                // 鍥炲bye
-                                cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
-                            }, 60 * 1000);
-                            responseSdpAck(evt, content.toString(), platform);
+                            if (userSetting.getPushStreamAfterAck()) {
+                                dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
+                                    logger.info("Ack 绛夊緟瓒呮椂");
+                                    mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
+                                    // 鍥炲bye
+                                    try {
+                                        cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
+                                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                                        logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage());
+                                    }
+                                }, 60 * 1000);
+                            }
 
+                            SIPResponse sipResponse = responseSdpAck(request, content.toString(), platform);
+                            if (!userSetting.getPushStreamAfterAck()) {
+                                playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader());
+                            }
                         } catch (SipException e) {
                             e.printStackTrace();
                         } catch (InvalidArgumentException e) {
@@ -344,23 +467,18 @@
                     };
                     SipSubscribe.Event errorEvent = ((event) -> {
                         // 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒
-                        Response response = null;
                         try {
-                            response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
-                            ServerTransaction serverTransaction = getServerTransaction(evt);
-                            serverTransaction.sendResponse(response);
-                            if (serverTransaction.getDialog() != null) {
-                                serverTransaction.getDialog().delete();
-                            }
-                        } catch (ParseException | SipException | InvalidArgumentException e) {
+                            Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
+                            sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
+                        } catch (ParseException | SipException  e) {
                             e.printStackTrace();
                         }
                     });
                     sendRtpItem.setApp("rtp");
-                    if ("Playback".equals(sessionName)) {
+                    if ("Playback".equalsIgnoreCase(sessionName)) {
                         sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
-                        SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true, true);
-                        sendRtpItem.setStreamId(ssrcInfo.getStream());
+                        SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, device.isSsrcCheck(), true);
+                        sendRtpItem.setStream(ssrcInfo.getStream());
                         // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
                         redisCatchStorage.updateSendRTPSever(sendRtpItem);
                         playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
@@ -370,15 +488,11 @@
                                         if (result.getEvent() != null) {
                                             errorEvent.response(result.getEvent());
                                         }
-                                        redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
+                                        redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null);
                                         try {
-                                            responseAck(evt, Response.REQUEST_TIMEOUT);
-                                        } catch (SipException e) {
-                                            e.printStackTrace();
-                                        } catch (InvalidArgumentException e) {
-                                            e.printStackTrace();
-                                        } catch (ParseException e) {
-                                            e.printStackTrace();
+                                            responseAck(request, Response.REQUEST_TIMEOUT);
+                                        } catch (SipException | InvalidArgumentException | ParseException e) {
+                                            logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 褰曞儚鍥炴斁 鍙戦�丷EQUEST_TIMEOUT: {}", e.getMessage());
                                         }
                                     } else {
                                         if (result.getMediaServerItem() != null) {
@@ -392,7 +506,14 @@
                         if (playTransaction != null) {
                             Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream());
                             if (!streamReady) {
-                                playTransaction = null;
+                                boolean hasRtpServer = mediaServerService.checkRtpServer(mediaServerItem, "rtp", playTransaction.getStream());
+                                if (hasRtpServer) {
+                                    logger.info("[涓婄骇鐐规挱]宸茬粡寮�鍚痳tpServer浣嗘槸灏氭湭鏀跺埌娴侊紝寮�鍚洃鍚祦鐨勫埌鏉�");
+                                    HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", playTransaction.getStream(), true, "rtsp", mediaServerItem.getId());
+                                    zlmHttpHookSubscribe.addSubscribe(hookSubscribe, hookEvent);
+                                }else {
+                                    playTransaction = null;
+                                }
                             }
                         }
                         if (playTransaction == null) {
@@ -401,44 +522,55 @@
                                 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
                             }
                             SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
-                            sendRtpItem.setStreamId(ssrcInfo.getStream());
+                            logger.info(JSONObject.toJSONString(ssrcInfo));
+                            sendRtpItem.setStream(ssrcInfo.getStream());
+                            sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc);
+
                             // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
                             redisCatchStorage.updateSendRTPSever(sendRtpItem);
                             playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> {
-                                logger.info("[涓婄骇鐐规挱]瓒呮椂, 鐢ㄦ埛锛歿}锛� 閫氶亾锛歿}", username, channelId);
-                                redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
-                            }, null);
+                                logger.info("[涓婄骇鐐规挱]瓒呮椂, 鐢ㄦ埛锛歿}锛� 閫氶亾锛歿}", username, finalChannelId);
+                                redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null);
+                            });
                         } else {
-                            sendRtpItem.setStreamId(playTransaction.getStream());
+                            sendRtpItem.setStream(playTransaction.getStream());
                             // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
                             redisCatchStorage.updateSendRTPSever(sendRtpItem);
                             JSONObject jsonObject = new JSONObject();
                             jsonObject.put("app", sendRtpItem.getApp());
-                            jsonObject.put("stream", sendRtpItem.getStreamId());
+                            jsonObject.put("stream", sendRtpItem.getStream());
                             hookEvent.response(mediaServerItem, jsonObject);
                         }
                     }
                 } else if (gbStream != null) {
-                    if (streamPushItem.isStatus()) {
-                        // 鍦ㄧ嚎鐘舵��
-                        pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
-                                mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
-                    } else {
-                        // 涓嶅湪绾� 鎷夎捣
-                        notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
-                                mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                    if("push".equals(gbStream.getStreamType())) {
+                        if (streamPushItem != null && streamPushItem.isPushIng()) {
+                            // 鎺ㄦ祦鐘舵��
+                            pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                        } else {
+                            // 鏈帹娴� 鎷夎捣
+                            notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                        }
+                    }else if ("proxy".equals(gbStream.getStreamType())){
+                        if (null != proxyByAppAndStream) {
+                            if(proxyByAppAndStream.isStatus()){
+                                pushProxyStream(evt, request, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                            }else{
+                                //寮�鍚唬鐞嗘媺娴�
+                                notifyStreamOnline(evt, request,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                            }
+                        }
+
+
                     }
-
                 }
-
             }
-
-        } catch (SipException | InvalidArgumentException | ParseException e) {
-            e.printStackTrace();
-            logger.warn("sdp瑙f瀽閿欒");
-            e.printStackTrace();
         } catch (SdpParseException e) {
-            e.printStackTrace();
+            logger.error("sdp瑙f瀽閿欒", e);
         } catch (SdpException e) {
             e.printStackTrace();
         }
@@ -447,23 +579,23 @@
     /**
      * 瀹夋帓鎺ㄦ祦
      */
-
-    private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
+    private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform,
                             CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                             int port, Boolean tcpActive, boolean mediaTransmissionTCP,
-                            String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
-        // 鎺ㄦ祦
-        if (streamPushItem.getServerId().equals(userSetting.getServerId())) {
+                            String channelId, String addressStr, String ssrc, String requesterId) {
             Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
             if (streamReady) {
                 // 鑷钩鍙板唴瀹�
                 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
-                        gbStream.getApp(), gbStream.getStream(), channelId,
-                        mediaTransmissionTCP);
+                        gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
 
                 if (sendRtpItem == null) {
                     logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
-                    responseAck(evt, Response.BUSY_HERE);
+                    try {
+                        responseAck(request, Response.BUSY_HERE);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage());
+                    }
                     return;
                 }
                 if (tcpActive != null) {
@@ -473,44 +605,116 @@
                 // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
                 sendRtpItem.setStatus(1);
                 sendRtpItem.setCallId(callIdHeader.getCallId());
-                byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
-                sendRtpItem.setDialog(dialogByteArray);
-                byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
-                sendRtpItem.setTransaction(transactionByteArray);
+                sendRtpItem.setFromTag(request.getFromTag());
+
+                SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
+                if (response != null) {
+                    sendRtpItem.setToTag(response.getToTag());
+                }
                 redisCatchStorage.updateSendRTPSever(sendRtpItem);
-                sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
+
+        }
+
+    }
+    private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
+                            CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
+                            int port, Boolean tcpActive, boolean mediaTransmissionTCP,
+                            String channelId, String addressStr, String ssrc, String requesterId) {
+        // 鎺ㄦ祦
+        if (streamPushItem.isSelf()) {
+            Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
+            if (streamReady) {
+                // 鑷钩鍙板唴瀹�
+                SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
+                        gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
+
+                if (sendRtpItem == null) {
+                    logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
+                    try {
+                        responseAck(request, Response.BUSY_HERE);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage());
+                    }
+                    return;
+                }
+                if (tcpActive != null) {
+                    sendRtpItem.setTcpActive(tcpActive);
+                }
+                sendRtpItem.setPlayType(InviteStreamType.PUSH);
+                // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
+                sendRtpItem.setStatus(1);
+                sendRtpItem.setCallId(callIdHeader.getCallId());
+
+                sendRtpItem.setFromTag(request.getFromTag());
+                SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
+                if (response != null) {
+                    sendRtpItem.setToTag(response.getToTag());
+                }
+
+                redisCatchStorage.updateSendRTPSever(sendRtpItem);
+
             } else {
                 // 涓嶅湪绾� 鎷夎捣
-                notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                         mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
             }
 
         } else {
             // 鍏朵粬骞冲彴鍐呭
-            otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+            otherWvpPushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                     mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
         }
-
     }
-
     /**
      * 閫氱煡娴佷笂绾�
      */
-    private void notifyStreamOnline(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
+    private void notifyStreamOnline(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
                                     CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                                     int port, Boolean tcpActive, boolean mediaTransmissionTCP,
-                                    String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
+                                    String channelId, String addressStr, String ssrc, String requesterId) {
         if ("proxy".equals(gbStream.getStreamType())) {
             // TODO 鎺у埗鍚敤浠ヤ娇璁惧涓婄嚎
-            logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽惎鐢ㄦ祦鍚庡紑濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
-            responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
+            logger.info("[ app={}, stream={} ]閫氶亾鏈帹娴侊紝鍚敤娴佸悗寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
+            // 鐩戝惉娴佷笂绾�
+            HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(gbStream.getApp(), gbStream.getStream(), true, "rtsp", mediaServerItem.getId());
+            zlmHttpHookSubscribe.addSubscribe(hookSubscribe, (mediaServerItemInUSe, responseJSON) -> {
+                String app = responseJSON.getString("app");
+                String stream = responseJSON.getString("stream");
+                logger.info("[涓婄骇鐐规挱]鎷夋祦浠g悊宸茬粡灏辩华锛� {}/{}", app, stream);
+                dynamicTask.stop(callIdHeader.getCallId());
+                pushProxyStream(evt, request, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
+                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+            });
+            dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
+                logger.info("[ app={}, stream={} ] 绛夊緟鎷夋祦浠g悊娴佽秴鏃�", gbStream.getApp(), gbStream.getStream());
+                zlmHttpHookSubscribe.removeSubscribe(hookSubscribe);
+            }, userSetting.getPlatformPlayTimeout());
+            boolean start = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
+            if (!start) {
+                try {
+                    responseAck(request, Response.BUSY_HERE, "channel [" + gbStream.getGbId() + "] offline");
+                } catch (SipException | InvalidArgumentException | ParseException e) {
+                    logger.error("[鍛戒护鍙戦�佸け璐 invite 閫氶亾鏈帹娴�: {}", e.getMessage());
+                }
+                zlmHttpHookSubscribe.removeSubscribe(hookSubscribe);
+                dynamicTask.stop(callIdHeader.getCallId());
+            }
+
+
+
         } else if ("push".equals(gbStream.getStreamType())) {
             if (!platform.isStartOfflinePush()) {
-                responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel unavailable");
+                // 骞冲彴璁剧疆涓叧闂簡鎷夎捣绂荤嚎鐨勬帹娴佸垯鐩存帴鍥炲
+                try {
+                    logger.info("[涓婄骇鐐规挱] 澶辫触锛屾帹娴佽澶囨湭鎺ㄦ祦锛宑hannel: {}, app: {}, stream: {}", gbStream.getGbId(), gbStream.getApp(), gbStream.getStream());
+                    responseAck(request, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
+                } catch (SipException | InvalidArgumentException | ParseException e) {
+                    logger.error("[鍛戒护鍙戦�佸け璐 invite 閫氶亾鏈帹娴�: {}", e.getMessage());
+                }
                 return;
             }
             // 鍙戦�乺edis娑堟伅浠ヤ娇璁惧涓婄嚎
-            logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽彂閫乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
+            logger.info("[ app={}, stream={} ]閫氶亾鏈帹娴侊紝鍙戦�乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
 
             MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(1,
                     gbStream.getApp(), gbStream.getStream(), gbStream.getGbId(), gbStream.getPlatformId(),
@@ -520,8 +724,8 @@
             dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
                 logger.info("[ app={}, stream={} ] 绛夊緟璁惧寮�濮嬫帹娴佽秴鏃�", gbStream.getApp(), gbStream.getStream());
                 try {
-                    mediaListManager.removedChannelOnlineEventLister(gbStream.getGbId());
-                    responseAck(evt, Response.REQUEST_TIMEOUT); // 瓒呮椂
+                    mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
+                    responseAck(request, Response.REQUEST_TIMEOUT); // 瓒呮椂
                 } catch (SipException e) {
                     e.printStackTrace();
                 } catch (InvalidArgumentException e) {
@@ -535,16 +739,16 @@
             Boolean finalTcpActive = tcpActive;
 
             // 娣诲姞鍦ㄦ湰鏈轰笂绾跨殑閫氱煡
-            mediaListManager.addChannelOnlineEventLister(gbStream.getGbId(), (app, stream, serverId) -> {
+            mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> {
                 dynamicTask.stop(callIdHeader.getCallId());
                 if (serverId.equals(userSetting.getServerId())) {
                     SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
-                            app, stream, channelId, mediaTransmissionTCP);
+                            app, stream, channelId, mediaTransmissionTCP, platform.isRtcp());
 
                     if (sendRtpItem == null) {
-                        logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
+                        logger.warn("涓婄骇鐐规椂鍒涘缓sendRTPItem澶辫触锛屽彲鑳芥槸鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
                         try {
-                            responseAck(evt, Response.BUSY_HERE);
+                            responseAck(request, Response.BUSY_HERE);
                         } catch (SipException e) {
                             e.printStackTrace();
                         } catch (InvalidArgumentException e) {
@@ -561,16 +765,30 @@
                     // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
                     sendRtpItem.setStatus(1);
                     sendRtpItem.setCallId(callIdHeader.getCallId());
-                    byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
-                    sendRtpItem.setDialog(dialogByteArray);
-                    byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
-                    sendRtpItem.setTransaction(transactionByteArray);
+
+                    sendRtpItem.setFromTag(request.getFromTag());
+                    SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
+                    if (response != null) {
+                        sendRtpItem.setToTag(response.getToTag());
+                    }
                     redisCatchStorage.updateSendRTPSever(sendRtpItem);
-                    sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
                 } else {
                     // 鍏朵粬骞冲彴鍐呭
-                    otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                    otherWvpPushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                             mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                }
+            });
+
+            // 娣诲姞鍥炲鐨勬嫆缁濇垨鑰呴敊璇殑閫氱煡
+            redisPushStreamResponseListener.addEvent(gbStream.getApp(), gbStream.getStream(), response -> {
+                if (response.getCode() != 0) {
+                    dynamicTask.stop(callIdHeader.getCallId());
+                    mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
+                    try {
+                        responseAck(request, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鐐规挱鍥炲: {}", e.getMessage());
+                    }
                 }
             });
         }
@@ -579,7 +797,7 @@
     /**
      * 鏉ヨ嚜鍏朵粬wvp鐨勬帹娴�
      */
-    private void otherWvpPushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
+    private void otherWvpPushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
                                     CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                                     int port, Boolean tcpActive, boolean mediaTransmissionTCP,
                                     String channelId, String addressStr, String ssrc, String requesterId) {
@@ -587,12 +805,12 @@
         // 鍙戦�乺edis娑堟伅
         redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(),
                 streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId,
-                channelId, mediaTransmissionTCP, null, responseSendItemMsg -> {
+                channelId, mediaTransmissionTCP, platform.isRtcp(),null, responseSendItemMsg -> {
                     SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem();
                     if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
                         logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
                         try {
-                            responseAck(evt, Response.BUSY_HERE);
+                            responseAck(request, Response.BUSY_HERE);
                         } catch (SipException e) {
                             e.printStackTrace();
                         } catch (InvalidArgumentException e) {
@@ -610,53 +828,40 @@
                     // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
                     sendRtpItem.setStatus(1);
                     sendRtpItem.setCallId(callIdHeader.getCallId());
-                    byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
-                    sendRtpItem.setDialog(dialogByteArray);
-                    byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
-                    sendRtpItem.setTransaction(transactionByteArray);
+
+                    sendRtpItem.setFromTag(request.getFromTag());
+                    SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request,sendRtpItem, platform, evt);
+                    if (response != null) {
+                        sendRtpItem.setToTag(response.getToTag());
+                    }
                     redisCatchStorage.updateSendRTPSever(sendRtpItem);
-                    sendStreamAck(responseSendItemMsg.getMediaServerItem(), sendRtpItem, platform, evt);
                 }, (wvpResult) -> {
-                    try {
-                        // 閿欒
-                        if (wvpResult.getCode() == RedisGbPlayMsgListener.ERROR_CODE_OFFLINE) {
-                            // 绂荤嚎
-                            // 鏌ヨ鏄惁鍦ㄦ湰鏈轰笂绾夸簡
-                            StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
-                            if (currentStreamPushItem.isStatus()) {
-                                // 鍦ㄧ嚎鐘舵��
-                                pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
-                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
 
-                            } else {
-                                // 涓嶅湪绾� 鎷夎捣
-                                notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
-                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
-                            }
+                    // 閿欒
+                    if (wvpResult.getCode() == RedisGbPlayMsgListener.ERROR_CODE_OFFLINE) {
+                        // 绂荤嚎
+                        // 鏌ヨ鏄惁鍦ㄦ湰鏈轰笂绾夸簡
+                        StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
+                        if (currentStreamPushItem.isPushIng()) {
+                            // 鍦ㄧ嚎鐘舵��
+                            pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+
+                        } else {
+                            // 涓嶅湪绾� 鎷夎捣
+                            notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                         }
-                    } catch (InvalidArgumentException e) {
-                        throw new RuntimeException(e);
-                    } catch (ParseException e) {
-                        throw new RuntimeException(e);
-                    } catch (SipException e) {
-                        throw new RuntimeException(e);
                     }
-
-
                     try {
-                        responseAck(evt, Response.BUSY_HERE);
-                    } catch (SipException e) {
-                        e.printStackTrace();
-                    } catch (InvalidArgumentException e) {
-                        e.printStackTrace();
-                    } catch (ParseException e) {
-                        e.printStackTrace();
+                        responseAck(request, Response.BUSY_HERE);
+                    } catch (InvalidArgumentException | ParseException | SipException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鐐规挱鍥炲 BUSY_HERE: {}", e.getMessage());
                     }
-                    return;
                 });
     }
 
-    public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
+    public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
 
         StringBuffer content = new StringBuffer(200);
         content.append("v=0\r\n");
@@ -679,7 +884,11 @@
         content.append("f=\r\n");
 
         try {
-            responseSdpAck(evt, content.toString(), platform);
+            SIPResponse sipResponse = responseSdpAck(request, content.toString(), platform);
+            if (!userSetting.getPushStreamAfterAck()) {
+                playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader());
+            }
+            return sipResponse;
         } catch (SipException e) {
             e.printStackTrace();
         } catch (InvalidArgumentException e) {
@@ -687,17 +896,34 @@
         } catch (ParseException e) {
             e.printStackTrace();
         }
+        return null;
     }
 
-    public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException {
+    public void inviteFromDeviceHandle(SIPRequest request, String requesterId, String channelId) {
 
         // 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛�
         Device device = redisCatchStorage.getDevice(requesterId);
-        Request request = evt.getRequest();
+        AudioBroadcastCatch broadcastCatch = audioBroadcastManager.get(requesterId, channelId);
+        if (broadcastCatch == null) {
+            logger.warn("鏉ヨ嚜璁惧鐨処nvite璇锋眰闈炶闊冲箍鎾紝宸插拷鐣ワ紝requesterId锛� {}/{}", requesterId, channelId);
+            try {
+                responseAck(request, Response.FORBIDDEN);
+            } catch (SipException | InvalidArgumentException | ParseException e) {
+                logger.error("[鍛戒护鍙戦�佸け璐 鏉ヨ嚜璁惧鐨処nvite璇锋眰闈炶闊冲箍鎾� FORBIDDEN: {}", e.getMessage());
+            }
+            return;
+        }
         if (device != null) {
             logger.info("鏀跺埌璁惧" + requesterId + "鐨勮闊冲箍鎾璉nvite璇锋眰");
-            responseAck(evt, Response.TRYING);
-
+            String key = VideoManagerConstants.BROADCAST_WAITE_INVITE +  device.getDeviceId() + broadcastCatch.getChannelId();
+            dynamicTask.stop(key);
+            try {
+                responseAck(request, Response.TRYING);
+            } catch (SipException | InvalidArgumentException | ParseException e) {
+                logger.error("[鍛戒护鍙戦�佸け璐 invite BAD_REQUEST: {}", e.getMessage());
+                playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId());
+                return;
+            }
             String contentString = new String(request.getRawContent());
             // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎绉婚櫎浠ヨВ鏋愩��
             String substring = contentString;
@@ -705,57 +931,190 @@
             int ssrcIndex = contentString.indexOf("y=");
             if (ssrcIndex > 0) {
                 substring = contentString.substring(0, ssrcIndex);
-                ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
+                ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim();
             }
             ssrcIndex = substring.indexOf("f=");
             if (ssrcIndex > 0) {
                 substring = contentString.substring(0, ssrcIndex);
             }
-            SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
+            try {
+                SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
 
-            //  鑾峰彇鏀寔鐨勬牸寮�
-            Vector mediaDescriptions = sdp.getMediaDescriptions(true);
-            // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96
-            int port = -1;
-            //boolean recvonly = false;
-            boolean mediaTransmissionTCP = false;
-            Boolean tcpActive = null;
-            for (int i = 0; i < mediaDescriptions.size(); i++) {
-                MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i);
-                Media media = mediaDescription.getMedia();
+                //  鑾峰彇鏀寔鐨勬牸寮�
+                Vector mediaDescriptions = sdp.getMediaDescriptions(true);
 
-                Vector mediaFormats = media.getMediaFormats(false);
-                if (mediaFormats.contains("8")) {
-                    port = media.getMediaPort();
-                    String protocol = media.getProtocol();
-                    // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp
-                    if ("TCP/RTP/AVP".equals(protocol)) {
-                        String setup = mediaDescription.getAttribute("setup");
-                        if (setup != null) {
-                            mediaTransmissionTCP = true;
-                            if ("active".equals(setup)) {
-                                tcpActive = true;
-                            } else if ("passive".equals(setup)) {
-                                tcpActive = false;
+                // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96
+                int port = -1;
+                boolean mediaTransmissionTCP = false;
+                Boolean tcpActive = null;
+                for (int i = 0; i < mediaDescriptions.size(); i++) {
+                    MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i);
+                    Media media = mediaDescription.getMedia();
+
+                    Vector mediaFormats = media.getMediaFormats(false);
+                    if (mediaFormats.contains("8")) {
+                        port = media.getMediaPort();
+                        String protocol = media.getProtocol();
+                        // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp
+                        if ("TCP/RTP/AVP".equals(protocol)) {
+                            String setup = mediaDescription.getAttribute("setup");
+                            if (setup != null) {
+                                mediaTransmissionTCP = true;
+                                if ("active".equals(setup)) {
+                                    tcpActive = true;
+                                } else if ("passive".equals(setup)) {
+                                    tcpActive = false;
+                                }
                             }
                         }
+                        break;
                     }
-                    break;
                 }
-            }
-            if (port == -1) {
-                logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415");
-                // 鍥炲涓嶆敮鎸佺殑鏍煎紡
-                responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415
-                return;
-            }
-            String username = sdp.getOrigin().getUsername();
-            String addressStr = sdp.getOrigin().getAddress();
-            logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", username, addressStr, port, ssrc);
+                if (port == -1) {
+                    logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415");
+                    // 鍥炲涓嶆敮鎸佺殑鏍煎紡
+                    try {
+                        responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 涓嶆敮鎸佺殑濯掍綋鏍煎紡: {}", e.getMessage());
+                        playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId());
+                        return;
+                    }
+                    return;
+                }
+                String addressStr = sdp.getOrigin().getAddress();
+                logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}, {}", requesterId, addressStr, port, ssrc,
+                        mediaTransmissionTCP ? (tcpActive? "TCP涓诲姩":"TCP琚姩") : "UDP");
 
+                MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem();
+                if (mediaServerItem == null) {
+                    logger.warn("鏈壘鍒拌闊冲枈璇濅娇鐢ㄧ殑zlm");
+                    try {
+                        responseAck(request, Response.BUSY_HERE);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈壘鍒板彲鐢ㄧ殑zlm: {}", e.getMessage());
+                        playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId());
+                    }
+                    return;
+                }
+                logger.info("璁惧{}璇锋眰璇煶娴侊紝 鏀舵祦鍦板潃锛歿}:{}锛宻src锛歿}, {}, 瀵硅鏂瑰紡锛歿}", requesterId, addressStr, port, ssrc,
+                        mediaTransmissionTCP ? (tcpActive? "TCP涓诲姩":"TCP琚姩") : "UDP", sdp.getSessionName().getValue());
+
+                SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
+                        device.getDeviceId(), broadcastCatch.getChannelId(),
+                        mediaTransmissionTCP, false);
+
+                if (sendRtpItem == null) {
+                    logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
+                    try {
+                        responseAck(request, Response.BUSY_HERE);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage());
+                        playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId());
+                        return;
+                    }
+                    return;
+                }
+
+
+                CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
+                sendRtpItem.setPlayType(InviteStreamType.BROADCAST);
+                sendRtpItem.setCallId(callIdHeader.getCallId());
+                sendRtpItem.setPlatformId(requesterId);
+                sendRtpItem.setStatus(1);
+                sendRtpItem.setApp(broadcastCatch.getApp());
+                sendRtpItem.setStream(broadcastCatch.getStream());
+                sendRtpItem.setPt(8);
+                sendRtpItem.setUsePs(false);
+                sendRtpItem.setRtcp(false);
+                sendRtpItem.setOnlyAudio(true);
+                sendRtpItem.setTcp(mediaTransmissionTCP);
+                if (tcpActive != null) {
+                    sendRtpItem.setTcpActive(tcpActive);
+                }
+
+                redisCatchStorage.updateSendRTPSever(sendRtpItem);
+
+                Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream());
+                if (streamReady) {
+                    sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, ssrc);
+                }else {
+                    logger.warn("[璇煶閫氳瘽]锛� 鏈彂鐜板緟鎺ㄩ�佺殑娴�,app={},stream={}", broadcastCatch.getApp(), broadcastCatch.getStream());
+                    try {
+                        responseAck(request, Response.GONE);
+                    } catch (SipException | InvalidArgumentException | ParseException e) {
+                        logger.error("[鍛戒护鍙戦�佸け璐 璇煶閫氳瘽 鍥炲410澶辫触锛� {}", e.getMessage());
+                        return;
+                    }
+                    playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId());
+                }
+            } catch (SdpException e) {
+                logger.error("[SDP瑙f瀽寮傚父]", e);
+                playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId());
+            }
         } else {
             logger.warn("鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹�");
-            responseAck(evt, Response.BAD_REQUEST);
+            try {
+                responseAck(request, Response.BAD_REQUEST);; // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415
+            } catch (SipException | InvalidArgumentException | ParseException e) {
+                logger.error("[鍛戒护鍙戦�佸け璐 invite 鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹傦紝 {}", e.getMessage());
+            }
         }
     }
+
+    SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request,  MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc){
+        SIPResponse sipResponse = null;
+        try {
+            sendRtpItem.setStatus(2);
+            redisCatchStorage.updateSendRTPSever(sendRtpItem);
+            StringBuffer content = new StringBuffer(200);
+            content.append("v=0\r\n");
+            content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion()  + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
+            content.append("s=Play\r\n");
+            content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
+            content.append("t=0 0\r\n");
+
+            if (mediaTransmissionTCP) {
+                content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n");
+            }else {
+                content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n");
+            }
+
+            content.append("a=rtpmap:8 PCMA/8000/1\r\n");
+
+            content.append("a=sendonly\r\n");
+            if (sendRtpItem.isTcp()) {
+                content.append("a=connection:new\r\n");
+                if (!sendRtpItem.isTcpActive()) {
+                    content.append("a=setup:active\r\n");
+                }else {
+                    content.append("a=setup:passive\r\n");
+                }
+            }
+            content.append("y="+ ssrc + "\r\n");
+            content.append("f=v/////a/1/8/1\r\n");
+
+            ParentPlatform parentPlatform = new ParentPlatform();
+            parentPlatform.setServerIP(device.getIp());
+            parentPlatform.setServerPort(device.getPort());
+            parentPlatform.setServerGBId(device.getDeviceId());
+
+            sipResponse = responseSdpAck(request, content.toString(), parentPlatform);
+
+            AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(device.getDeviceId(), sendRtpItem.getChannelId());
+
+            audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.Ok);
+            audioBroadcastCatch.setSipTransactionInfoByRequset(sipResponse);
+            audioBroadcastManager.update(audioBroadcastCatch);
+
+            // 寮�鍚彂娴侊紝澶у崕鍦ㄦ敹鍒�200OK鍚庡氨浼氬紑濮嬪缓绔嬭繛鎺�
+            if (!userSetting.getPushStreamAfterAck()) {
+                playService.startPushStream(sendRtpItem, sipResponse, parentPlatform, request.getCallIdHeader());
+            }
+
+        } catch (SipException | InvalidArgumentException | ParseException | SdpParseException e) {
+            logger.error("[鍛戒护鍙戦�佸け璐 璇煶鍠婅瘽 鍥炲200OK锛圫DP锛�: {}", e.getMessage());
+        }
+        return sipResponse;
+    }
 }

--
Gitblit v1.8.0