648540858
2022-10-18 74714711aa87dcd1259f5aebe55d362be732ffa2
优化sip消息构建,去除ServerTransaction的使用
33个文件已修改
1个文件已添加
939 ■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java 143 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java 123 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/GitUtil.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
@@ -3,15 +3,13 @@
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import javax.sip.ServerTransaction;
import javax.sip.header.*;
public class SubscribeInfo {
    public SubscribeInfo(ServerTransaction serverTransaction, String id) {
    public SubscribeInfo(SIPRequest request, String id) {
        this.id = id;
        SIPRequest request = (SIPRequest)serverTransaction.getRequest();
        this.request = request;
        this.expires = request.getExpires().getExpires();
        EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
New file
@@ -0,0 +1,106 @@
package com.genersoft.iot.vmp.gb28181.transmit;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.SipProviderImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.header.CallIdHeader;
import javax.sip.header.UserAgentHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Message;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
@Component
public class SIPSender {
    private final Logger logger = LoggerFactory.getLogger(SIPSender.class);
    @Autowired
    @Qualifier(value = "tcpSipProvider")
    private SipProviderImpl tcpSipProvider;
    @Autowired
    @Qualifier(value = "udpSipProvider")
    private SipProviderImpl udpSipProvider;
    @Autowired
    private SipFactory sipFactory;
    @Autowired
    private GitUtil gitUtil;
    @Autowired
    private SipSubscribe sipSubscribe;
    public void transmitRequest(Message message) throws SipException, ParseException {
        transmitRequest(message, null, null);
    }
    public void transmitRequest(Message message, SipSubscribe.Event errorEvent) throws SipException, ParseException {
        transmitRequest(message, errorEvent, null);
    }
    public void transmitRequest(Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
        ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);
        String transport = "UDP";
        if (viaHeader == null) {
            logger.warn("[消息头缺失]: ViaHeader");
        }else {
            transport = viaHeader.getTransport();
        }
        if (message.getHeader(UserAgentHeader.NAME) == null) {
            try {
                message.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
            } catch (ParseException e) {
                logger.error("添加UserAgentHeader失败", e);
            }
        }
        CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
        // 添加错误订阅
        if (errorEvent != null) {
            sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
                errorEvent.response(eventResult);
                sipSubscribe.removeErrorSubscribe(eventResult.callId);
                sipSubscribe.removeOkSubscribe(eventResult.callId);
            }));
        }
        // 添加订阅
        if (okEvent != null) {
            sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
                okEvent.response(eventResult);
                sipSubscribe.removeOkSubscribe(eventResult.callId);
                sipSubscribe.removeErrorSubscribe(eventResult.callId);
            });
        }
        if ("TCP".equals(transport)) {
            if (message instanceof Request) {
                tcpSipProvider.sendRequest((Request)message);
            }else if (message instanceof Response) {
                tcpSipProvider.sendResponse((Response)message);
            }
        } else if ("UDP".equals(transport)) {
            if (message instanceof Request) {
                udpSipProvider.sendRequest((Request)message);
            }else if (message instanceof Response) {
                udpSipProvider.sendResponse((Response)message);
            }
        }
    }
    public CallIdHeader getNewCallIdHeader(String transport){
        return  transport.equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -13,6 +13,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.PeerUnavailableException;
import javax.sip.SipException;
import javax.sip.message.Message;
import javax.sip.message.Request;
import java.text.ParseException;
@@ -362,9 +363,4 @@
     */
    void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
    void transmitRequest(String transport, Request request) throws SipException, ParseException ;
    void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException;
    void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, ParseException;
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -9,6 +9,7 @@
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
@@ -44,6 +45,7 @@
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Message;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.lang.reflect.Field;
@@ -68,16 +70,8 @@
    private SipFactory sipFactory;
    @Autowired
    private GitUtil gitUtil;
    @Autowired
    @Qualifier(value = "tcpSipProvider")
    private SipProviderImpl tcpSipProvider;
    @Autowired
    @Qualifier(value = "udpSipProvider")
    private SipProviderImpl udpSipProvider;
    private SIPSender sipSender;
    @Autowired
    private SIPRequestHeaderProvider headerProvider;
@@ -90,8 +84,7 @@
    @Autowired
    private ZlmHttpHookSubscribe subscribe;
    @Autowired
    private SipSubscribe sipSubscribe;
    @Autowired
    private IMediaServerService mediaServerService;
@@ -202,13 +195,10 @@
        ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
        ptzXml.append("</Info>\r\n");
        ptzXml.append("</Control>\r\n");
        Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sipSender.getNewCallIdHeader(device.getTransport()));
        CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request);
        sipSender.transmitRequest( request);
    }
    /**
@@ -239,11 +229,10 @@
        ptzXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request);
        SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest(request);
    }
@@ -269,13 +258,10 @@
        ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
        ptzXml.append("</Info>\r\n");
        ptzXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent, okEvent);
        Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest(request, errorEvent, okEvent);
    }
@@ -362,11 +348,10 @@
        // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
//            content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
        CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(), callIdHeader);
        transmitRequest(device.getTransport(), request, (e -> {
        Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, (e -> {
            streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
            mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
            errorEvent.response(e);
@@ -454,27 +439,25 @@
        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
        // 添加订阅
        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
            if (hookEvent != null) {
                InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());
                InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json,sipSender.getNewCallIdHeader(device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream());
                hookEvent.call(inviteStreamInfo);
            }
            subscribe.removeSubscribe(hookSubscribe);
        });
        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()), ssrcInfo.getSsrc());
        transmitRequest(device.getTransport(), request, errorEvent, event -> {
        sipSender.transmitRequest( request, errorEvent, event -> {
            ResponseEvent responseEvent = (ResponseEvent) event.event;
            SIPResponse response = (SIPResponse) responseEvent.getResponse();
            streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback);
            streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback);
            okEvent.response(event);
        });
        if (inviteStreamCallback != null) {
            inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
            inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()));
        }
    }
@@ -554,14 +537,11 @@
        content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
        // 添加订阅
        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
            hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
            hookEvent.call(new InviteStreamInfo(mediaServerItem, json,sipSender.getNewCallIdHeader(device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()));
            subscribe.removeSubscribe(hookSubscribe);
            hookSubscribe.getContent().put("regist", false);
            hookSubscribe.getContent().put("schema", "rtsp");
@@ -570,7 +550,7 @@
                    (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> {
                        logger.info("[录像]下载结束, 发送BYE");
                        try {
                            streamByeCmd(device, channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
                            streamByeCmd(device, channelId, ssrcInfo.getStream(),sipSender.getNewCallIdHeader(device.getTransport()).getCallId());
                        } catch (InvalidArgumentException | ParseException | SipException |
                                 SsrcTransactionNotFoundException e) {
                            logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage());
@@ -578,14 +558,14 @@
                    });
        });
        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()), ssrcInfo.getSsrc());
        if (inviteStreamCallback != null) {
            inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
            inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()));
        }
        transmitRequest(device.getTransport(), request, errorEvent, okEvent -> {
        sipSender.transmitRequest( request, errorEvent, okEvent -> {
            ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
            SIPResponse response = (SIPResponse) responseEvent.getResponse();
            streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
            streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
        });
    }
@@ -612,7 +592,7 @@
        streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
        Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo());
        transmitRequest(device.getTransport(), byteRequest, null, okEvent);
        sipSender.transmitRequest( byteRequest, null, okEvent);
    }
    /**
@@ -643,11 +623,10 @@
        broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
        broadcastXml.append("</Notify>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request);
        Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request);
    }
@@ -664,11 +643,10 @@
        broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
        broadcastXml.append("</Notify>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
@@ -696,11 +674,10 @@
        cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -721,11 +698,10 @@
        cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request);
    }
    /**
@@ -747,11 +723,10 @@
        cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -784,11 +759,10 @@
        }
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -814,11 +788,10 @@
        cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request);
    }
    /**
@@ -862,11 +835,10 @@
        cmdXml.append("</HomePosition>\r\n");
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -926,11 +898,10 @@
        cmdXml.append("</BasicParam>\r\n");
        cmdXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -950,12 +921,11 @@
        catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
        catalogXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        transmitRequest(device.getTransport(), request, errorEvent);
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -975,12 +945,11 @@
        catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
        catalogXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        transmitRequest(device.getTransport(), request);
        sipSender.transmitRequest( request);
    }
@@ -1001,12 +970,11 @@
        catalogXml.append("  <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
        catalogXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        transmitRequest(device.getTransport(), request, errorEvent);
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -1047,13 +1015,12 @@
        }
        recordInfoXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
                SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
                SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        transmitRequest(device.getTransport(), request, errorEvent, okEvent);
        sipSender.transmitRequest( request, errorEvent, okEvent);
    }
    /**
@@ -1099,11 +1066,10 @@
        }
        cmdXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -1130,11 +1096,10 @@
        cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
        cmdXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -1158,11 +1123,10 @@
        }
        cmdXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent);
        Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request, errorEvent);
    }
    /**
@@ -1183,12 +1147,11 @@
        mobilePostitionXml.append("<Interval>60</Interval>\r\n");
        mobilePostitionXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        transmitRequest(device.getTransport(), request, errorEvent);
        sipSender.transmitRequest( request, errorEvent);
    }
@@ -1218,12 +1181,11 @@
        if (requestOld != null) {
            callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
        } else {
            callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            callIdHeader = sipSender.getNewCallIdHeader(device.getTransport());
        }
        SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence", callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
        SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence",callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
        transmitRequest(device.getTransport(), request, errorEvent, okEvent);
        sipSender.transmitRequest( request, errorEvent, okEvent);
        return request;
    }
@@ -1270,11 +1232,10 @@
        }
        cmdXml.append("</Query>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence", callIdHeader);
        transmitRequest(device.getTransport(), request);
        Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence",sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest( request);
    }
@@ -1295,14 +1256,13 @@
        if (requestOld != null) {
            callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
        } else {
            callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                    : udpSipProvider.getNewCallId();
            callIdHeader = sipSender.getNewCallIdHeader(device.getTransport());
        }
        // 有效时间默认为60秒以上
        SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog",
                callIdHeader);
        transmitRequest(device.getTransport(), request, errorEvent, okEvent);
        sipSender.transmitRequest( request, errorEvent, okEvent);
        return request;
    }
@@ -1322,59 +1282,14 @@
        }
        dragXml.append(cmdString);
        dragXml.append("</Control>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        logger.debug("拉框信令: " + request.toString());
        transmitRequest(device.getTransport(), request);
        sipSender.transmitRequest(request);
    }
    @Override
    public void transmitRequest(String transport, Request request) throws SipException, ParseException {
        transmitRequest(transport, request, null, null);
    }
    @Override
    public void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException {
        transmitRequest(transport, request, errorEvent, null);
    }
    @Override
    public void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
        if (request.getHeader(UserAgentHeader.NAME) == null) {
            try {
                request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
            } catch (ParseException e) {
                logger.error("添加UserAgentHeader失败", e);
            }
        }
        CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
        // 添加错误订阅
        if (errorEvent != null) {
            sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
                errorEvent.response(eventResult);
                sipSubscribe.removeErrorSubscribe(eventResult.callId);
                sipSubscribe.removeOkSubscribe(eventResult.callId);
            }));
        }
        // 添加订阅
        if (okEvent != null) {
            sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
                okEvent.response(eventResult);
                sipSubscribe.removeOkSubscribe(eventResult.callId);
                sipSubscribe.removeErrorSubscribe(eventResult.callId);
            });
        }
        if ("TCP".equals(transport)) {
            tcpSipProvider.sendRequest(request);
        } else if ("UDP".equals(transport)) {
            udpSipProvider.sendRequest(request);
        }
    }
    /**
@@ -1449,7 +1364,7 @@
            return;
        }
        transmitRequest(device.getTransport(), request, errorEvent, okEvent);
        sipSender.transmitRequest( request, errorEvent, okEvent);
    }
    @Override
@@ -1478,10 +1393,9 @@
        deviceStatusXml.append("</info>\r\n");
        deviceStatusXml.append("</Notify>\r\n");
        CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
                : udpSipProvider.getNewCallId();
        Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
        transmitRequest(device.getTransport(), request);
        Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(device.getTransport()));
        sipSender.transmitRequest(request);
    }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -1,13 +1,11 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPServerTransaction;
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
import org.apache.commons.lang3.ArrayUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
@@ -51,48 +49,9 @@
    @Qualifier(value="udpSipProvider")
    private SipProviderImpl udpSipProvider;
    /**
     * 根据 RequestEvent 获取 ServerTransaction
     * @param evt
     * @return
     */
    public ServerTransaction getServerTransaction(RequestEvent evt) {
        Request request = evt.getRequest();
        SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
        // 判断TCP还是UDP
        boolean isTcp = false;
        ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = reqViaHeader.getTransport();
        if (transport.equalsIgnoreCase("TCP")) {
            isTcp = true;
        }
        if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
            serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
        }
        if (serverTransaction == null) {
            try {
                if (isTcp) {
                    SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
                    if (serverTransaction == null) {
                        serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
                    }
                } else {
                    SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
                    if (serverTransaction == null) {
                        serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
                    }
                }
            } catch (TransactionAlreadyExistsException e) {
                logger.error(e.getMessage());
            } catch (TransactionUnavailableException e) {
                logger.error(e.getMessage());
            }
        }
        return serverTransaction;
    }
    @Autowired
    private SIPSender sipSender;
    public AddressFactory getAddressFactory() {
        try {
            return SipFactory.getInstance().createAddressFactory();
@@ -134,25 +93,73 @@
     * 400
     * 404
     */
    public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode) throws SipException, InvalidArgumentException, ParseException {
        return responseAck(serverTransaction, statusCode, null);
    public SIPResponse responseAck(SIPRequest sipRequest, int statusCode) throws SipException, InvalidArgumentException, ParseException {
        return responseAck(sipRequest, statusCode, null);
    }
    public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
        return responseAck(serverTransaction, statusCode, msg, null);
    public SIPResponse responseAck(SIPRequest sipRequest, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
        return responseAck(sipRequest, statusCode, msg, null);
    }
    public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException {
        ToHeader toHeader = (ToHeader) serverTransaction.getRequest().getHeader(ToHeader.NAME);
        if (toHeader.getTag() == null) {
            toHeader.setTag(SipUtils.getNewTag());
//    public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException {
//        if (serverTransaction == null) {
//            logger.warn("[回复消息] ServerTransaction 为null");
//            return null;
//        }
//        ToHeader toHeader = (ToHeader) serverTransaction.getRequest().getHeader(ToHeader.NAME);
//        if (toHeader.getTag() == null) {
//            toHeader.setTag(SipUtils.getNewTag());
//        }
//        SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, serverTransaction.getRequest());
//        if (msg != null) {
//            response.setReasonPhrase(msg);
//        }
//        if (responseAckExtraParam != null) {
//            if (responseAckExtraParam.sipURI != null && serverTransaction.getRequest().getMethod().equals(Request.INVITE)) {
//                logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
//                Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(
//                        SipFactory.getInstance().createAddressFactory().createSipURI(responseAckExtraParam.sipURI.getUser(),  responseAckExtraParam.sipURI.getHost()+":"+responseAckExtraParam.sipURI.getPort()
//                        ));
//                response.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
//            }
//            if (responseAckExtraParam.contentTypeHeader != null) {
//                response.setContent(responseAckExtraParam.content, responseAckExtraParam.contentTypeHeader);
//            }
//
//            if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
//                if (responseAckExtraParam.expires == -1) {
//                    logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
//                }else {
//                    ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(responseAckExtraParam.expires);
//                    response.addHeader(expiresHeader);
//                }
//            }
//        }else {
//            if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
//                logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
//            }
//        }
//        serverTransaction.sendResponse(response);
//        if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(serverTransaction.getRequest().getMethod())) {
//            if (serverTransaction.getDialog() != null) {
//                serverTransaction.getDialog().delete();
//            }
//        }
//        return response;
//    }
    public SIPResponse responseAck(SIPRequest sipRequest, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException {
        if (sipRequest.getToHeader().getTag() == null) {
            sipRequest.getToHeader().setTag(SipUtils.getNewTag());
        }
        SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, serverTransaction.getRequest());
        SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, sipRequest);
        response.setStatusCode(statusCode);
        if (msg != null) {
            response.setReasonPhrase(msg);
        }
        if (responseAckExtraParam != null) {
            if (responseAckExtraParam.sipURI != null && serverTransaction.getRequest().getMethod().equals(Request.INVITE)) {
            if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
                logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
                Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(
                        SipFactory.getInstance().createAddressFactory().createSipURI(responseAckExtraParam.sipURI.getUser(),  responseAckExtraParam.sipURI.getHost()+":"+responseAckExtraParam.sipURI.getPort()
@@ -163,7 +170,7 @@
                response.setContent(responseAckExtraParam.content, responseAckExtraParam.contentTypeHeader);
            }
            if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
            if (sipRequest.getMethod().equals(Request.SUBSCRIBE)) {
                if (responseAckExtraParam.expires == -1) {
                    logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
                }else {
@@ -172,28 +179,26 @@
                }
            }
        }else {
            if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) {
            if (sipRequest.getMethod().equals(Request.SUBSCRIBE)) {
                logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header");
            }
        }
        serverTransaction.sendResponse(response);
        if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(serverTransaction.getRequest().getMethod())) {
            if (serverTransaction.getDialog() != null) {
                serverTransaction.getDialog().delete();
            }
        }
        // 发送response
        sipSender.transmitRequest(response);
        return response;
    }
    /**
     * 回复带sdp的200
     */
    public SIPResponse responseSdpAck(ServerTransaction serverTransaction, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
    public SIPResponse responseSdpAck(SIPRequest request, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
        ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
        // 兼容国标中的使用编码@域名作为RequestURI的情况
        SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
        SipURI sipURI = (SipURI)request.getRequestURI();
        if (sipURI.getPort() == -1) {
            sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(),  platform.getServerIP()+":"+platform.getServerPort());
        }
@@ -202,16 +207,16 @@
        responseAckExtraParam.content = sdp;
        responseAckExtraParam.sipURI = sipURI;
        return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
        return responseAck(request, Response.OK, null, responseAckExtraParam);
    }
    /**
     * 回复带xml的200
     */
    public SIPResponse responseXmlAck(ServerTransaction serverTransaction, String xml, ParentPlatform platform, Integer expires) throws SipException, InvalidArgumentException, ParseException {
    public SIPResponse responseXmlAck(SIPRequest request, String xml, ParentPlatform platform, Integer expires) throws SipException, InvalidArgumentException, ParseException {
        ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
        SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI();
        SipURI sipURI = (SipURI)request.getRequestURI();
        if (sipURI.getPort() == -1) {
            sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(),  platform.getServerIP()+":"+platform.getServerPort());
        }
@@ -220,7 +225,7 @@
        responseAckExtraParam.content = xml;
        responseAckExtraParam.sipURI = sipURI;
        responseAckExtraParam.expires = expires;
        return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam);
        return responseAck(request, Response.OK, null, responseAckExtraParam);
    }
    public Element getRootElement(RequestEvent evt) throws DocumentException {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -18,6 +18,7 @@
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
@@ -82,7 +83,7 @@
    public void process(RequestEvent evt) {
        try {
            responseAck(getServerTransaction(evt), Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[回复BYE信息失败],{}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -7,6 +7,7 @@
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
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.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
@@ -81,7 +82,7 @@
    private IPlayService playService;
    @Autowired
    private ISIPCommander commander;
    private SIPSender sipSender;
    @Autowired
    private ZLMRTPServerFactory zlmrtpServerFactory;
@@ -124,16 +125,15 @@
    public void process(RequestEvent evt) {
        //  Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
        try {
            Request request = evt.getRequest();
            SIPRequest request = (SIPRequest)evt.getRequest();
            String channelId = SipUtils.getChannelIdFromRequest(request);
            String requesterId = SipUtils.getUserIdFromFromHeader(request);
            CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
            ServerTransaction serverTransaction = getServerTransaction(evt);
            if (requesterId == null || channelId == null) {
                logger.info("无法从FromHeader的Address中获取到平台id,返回400");
                // 参数不全, 发400,请求错误
                try {
                    responseAck(serverTransaction, Response.BAD_REQUEST);
                    responseAck(request, Response.BAD_REQUEST);
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] invite BAD_REQUEST: {}", e.getMessage());
                }
@@ -144,7 +144,7 @@
            // 查询请求是否来自上级平台\设备
            ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
            if (platform == null) {
                inviteFromDeviceHandle(serverTransaction, requesterId);
                inviteFromDeviceHandle(request, requesterId);
            } else {
                // 查询平台下是否有该通道
@@ -159,12 +159,12 @@
                if (channel != null && gbStream == null) {
//                    if (channel.getStatus() == 0) {
//                        logger.info("通道离线,返回400");
//                        responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
//                        responseAck(request, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
//                        return;
//                    }
                    // 通道存在,发100,TRYING
                    try {
                        responseAck(serverTransaction, Response.TRYING);
                        responseAck(request, Response.TRYING);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite TRYING: {}", e.getMessage());
                    }
@@ -176,7 +176,7 @@
                        if ("proxy".equals(gbStream.getStreamType())) {
                            logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
                            try {
                                responseAck(serverTransaction, Response.GONE);
                                responseAck(request, Response.GONE);
                            } catch (SipException | InvalidArgumentException | ParseException e) {
                                logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
                            }
@@ -186,7 +186,7 @@
                            if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) {
                                logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
                                try {
                                    responseAck(serverTransaction, Response.GONE);
                                    responseAck(request, Response.GONE);
                                } catch (SipException | InvalidArgumentException | ParseException e) {
                                    logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
                                }
@@ -199,7 +199,7 @@
                            if (streamPushItem == null) {
                                logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
                                try {
                                    responseAck(serverTransaction, Response.GONE);
                                    responseAck(request, Response.GONE);
                                } catch (SipException | InvalidArgumentException | ParseException e) {
                                    logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
                                }
@@ -210,7 +210,7 @@
                            if (proxyByAppAndStream == null) {
                                logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
                                try {
                                    responseAck(serverTransaction, Response.GONE);
                                    responseAck(request, Response.GONE);
                                } catch (SipException | InvalidArgumentException | ParseException e) {
                                    logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
                                }
@@ -219,14 +219,14 @@
                        }
                    }
                    try {
                        responseAck(serverTransaction, Response.CALL_IS_BEING_FORWARDED);
                        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) {
                    try {
                        // 目录不支持点播
                        responseAck(serverTransaction, Response.BAD_REQUEST, "catalog channel can not play");
                        responseAck(request, Response.BAD_REQUEST, "catalog channel can not play");
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite 目录不支持点播: {}", e.getMessage());
                    }
@@ -235,7 +235,7 @@
                    logger.info("通道不存在,返回404");
                    try {
                        // 通道不存在,发404,资源不存在
                        responseAck(serverTransaction, Response.NOT_FOUND);
                        responseAck(request, Response.NOT_FOUND);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite 通道不存在: {}", e.getMessage());
                    }
@@ -311,7 +311,7 @@
                    // 回复不支持的格式
                    try {
                        // 不支持的格式,发415
                        responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE);
                        responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite 不支持的格式: {}", e.getMessage());
                    }
@@ -328,7 +328,7 @@
                    if (device == null) {
                        logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel);
                        try {
                            responseAck(serverTransaction, Response.SERVER_INTERNAL_ERROR);
                            responseAck(request, Response.SERVER_INTERNAL_ERROR);
                        } catch (SipException | InvalidArgumentException | ParseException e) {
                            logger.error("[命令发送失败] invite 未找到设备信息: {}", e.getMessage());
                        }
@@ -338,7 +338,7 @@
                    if (mediaServerItem == null) {
                        logger.warn("未找到可用的zlm");
                        try {
                            responseAck(serverTransaction, Response.BUSY_HERE);
                            responseAck(request, Response.BUSY_HERE);
                        } catch (SipException | InvalidArgumentException | ParseException e) {
                            logger.error("[命令发送失败] invite BUSY_HERE: {}", e.getMessage());
                        }
@@ -354,7 +354,7 @@
                    if (sendRtpItem == null) {
                        logger.warn("服务器端口资源不足");
                        try {
                            responseAck(serverTransaction, Response.BUSY_HERE);
                            responseAck(request, Response.BUSY_HERE);
                        } catch (SipException | InvalidArgumentException | ParseException e) {
                            logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage());
                        }
@@ -403,7 +403,7 @@
                                    logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
                                }
                            }, 60 * 1000);
                            responseSdpAck(serverTransaction, content.toString(), platform);
                            responseSdpAck(request, content.toString(), platform);
                        } catch (SipException e) {
                            e.printStackTrace();
@@ -415,15 +415,10 @@
                    };
                    SipSubscribe.Event errorEvent = ((event) -> {
                        // 未知错误。直接转发设备点播的错误
                        Response response = null;
                        try {
                            response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
                            serverTransaction.sendResponse(response);
                            System.out.println("未知错误。直接转发设备点播的错误");
                            if (serverTransaction.getDialog() != null) {
                                serverTransaction.getDialog().delete();
                            }
                        } catch (ParseException | SipException | InvalidArgumentException e) {
                            Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
                            sipSender.transmitRequest(response);
                        } catch (ParseException | SipException  e) {
                            e.printStackTrace();
                        }
                    });
@@ -443,7 +438,7 @@
                                        }
                                        redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
                                        try {
                                            responseAck(serverTransaction, Response.REQUEST_TIMEOUT);
                                            responseAck(request, Response.REQUEST_TIMEOUT);
                                        } catch (SipException e) {
                                            e.printStackTrace();
                                        } catch (InvalidArgumentException e) {
@@ -503,26 +498,26 @@
                    if("push".equals(gbStream.getStreamType())) {
                        if (streamPushItem != null && streamPushItem.isPushIng()) {
                            // 推流状态
                            pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                            pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        } else {
                            // 未推流 拉起
                            notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                            notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        }
                    }else if ("proxy".equals(gbStream.getStreamType())){
                        if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){
                            pushProxyStream(evt, serverTransaction, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
                            pushProxyStream(evt, request, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        }else{
                            //开启代理拉流
                            boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
                            if(start1) {
                                pushProxyStream(evt, serverTransaction, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
                                pushProxyStream(evt, request, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                            }else{
                                //失败后通知
                                notifyStreamOnline(evt, serverTransaction,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                notifyStreamOnline(evt, request,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                            }
                        }
@@ -540,7 +535,7 @@
    /**
     * 安排推流
     */
    private void pushProxyStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, 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) {
@@ -554,7 +549,7 @@
                if (sendRtpItem == null) {
                    logger.warn("服务器端口资源不足");
                    try {
                        responseAck(serverTransaction, Response.BUSY_HERE);
                        responseAck(request, Response.BUSY_HERE);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage());
                    }
@@ -567,10 +562,9 @@
                // 写入redis, 超时时回复
                sendRtpItem.setStatus(1);
                sendRtpItem.setCallId(callIdHeader.getCallId());
                SIPRequest request = (SIPRequest) evt.getRequest();
                sendRtpItem.setFromTag(request.getFromTag());
                SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
                SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
                if (response != null) {
                    sendRtpItem.setToTag(response.getToTag());
                }
@@ -579,7 +573,7 @@
        }
    }
    private void pushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
    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) {
@@ -595,7 +589,7 @@
                if (sendRtpItem == null) {
                    logger.warn("服务器端口资源不足");
                    try {
                        responseAck(serverTransaction, Response.BUSY_HERE);
                        responseAck(request, Response.BUSY_HERE);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage());
                    }
@@ -609,9 +603,8 @@
                sendRtpItem.setStatus(1);
                sendRtpItem.setCallId(callIdHeader.getCallId());
                SIPRequest request = (SIPRequest) evt.getRequest();
                sendRtpItem.setFromTag(request.getFromTag());
                SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
                SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
                if (response != null) {
                    sendRtpItem.setToTag(response.getToTag());
                }
@@ -620,20 +613,20 @@
            } else {
                // 不在线 拉起
                notifyStreamOnline(evt, serverTransaction,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, serverTransaction, 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, ServerTransaction serverTransaction, 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) {
@@ -641,7 +634,7 @@
            // TODO 控制启用以使设备上线
            logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream());
            try {
                responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
                responseAck(request, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
            } catch (SipException | InvalidArgumentException | ParseException e) {
                logger.error("[命令发送失败] invite 通道未推流: {}", e.getMessage());
            }
@@ -649,7 +642,7 @@
            if (!platform.isStartOfflinePush()) {
                // 平台设置中关闭了拉起离线的推流则直接回复
                try {
                    responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
                    responseAck(request, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing");
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] invite 通道未推流: {}", e.getMessage());
                }
@@ -667,7 +660,7 @@
                logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
                try {
                    mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
                    responseAck(serverTransaction, Response.REQUEST_TIMEOUT); // 超时
                    responseAck(request, Response.REQUEST_TIMEOUT); // 超时
                } catch (SipException e) {
                    e.printStackTrace();
                } catch (InvalidArgumentException e) {
@@ -690,7 +683,7 @@
                    if (sendRtpItem == null) {
                        logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
                        try {
                            responseAck(serverTransaction, Response.BUSY_HERE);
                            responseAck(request, Response.BUSY_HERE);
                        } catch (SipException e) {
                            e.printStackTrace();
                        } catch (InvalidArgumentException e) {
@@ -708,16 +701,15 @@
                    sendRtpItem.setStatus(1);
                    sendRtpItem.setCallId(callIdHeader.getCallId());
                    SIPRequest request = (SIPRequest) evt.getRequest();
                    sendRtpItem.setFromTag(request.getFromTag());
                    SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt);
                    SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt);
                    if (response != null) {
                        sendRtpItem.setToTag(response.getToTag());
                    }
                    redisCatchStorage.updateSendRTPSever(sendRtpItem);
                } else {
                    // 其他平台内容
                    otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                    otherWvpPushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                            mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                }
            });
@@ -728,7 +720,7 @@
                    dynamicTask.stop(callIdHeader.getCallId());
                    mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
                    try {
                        responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
                        responseAck(request, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
                    }
@@ -740,7 +732,7 @@
    /**
     * 来自其他wvp的推流
     */
    private void otherWvpPushStream(RequestEvent evt, ServerTransaction serverTransaction, 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) {
@@ -753,7 +745,7 @@
                    if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
                        logger.warn("服务器端口资源不足");
                        try {
                            responseAck(serverTransaction, Response.BUSY_HERE);
                            responseAck(request, Response.BUSY_HERE);
                        } catch (SipException e) {
                            e.printStackTrace();
                        } catch (InvalidArgumentException e) {
@@ -772,9 +764,8 @@
                    sendRtpItem.setStatus(1);
                    sendRtpItem.setCallId(callIdHeader.getCallId());
                    SIPRequest request = (SIPRequest) evt.getRequest();
                    sendRtpItem.setFromTag(request.getFromTag());
                    SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), serverTransaction,sendRtpItem, platform, evt);
                    SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request,sendRtpItem, platform, evt);
                    if (response != null) {
                        sendRtpItem.setToTag(response.getToTag());
                    }
@@ -788,24 +779,24 @@
                        StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
                        if (currentStreamPushItem.isPushIng()) {
                            // 在线状态
                            pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                            pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        } else {
                            // 不在线 拉起
                            notifyStreamOnline(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                            notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        }
                    }
                    try {
                        responseAck(serverTransaction, Response.BUSY_HERE);
                        responseAck(request, Response.BUSY_HERE);
                    } catch (InvalidArgumentException | ParseException | SipException e) {
                        logger.error("[命令发送失败] 国标级联 点播回复 BUSY_HERE: {}", e.getMessage());
                    }
                });
    }
    public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, ServerTransaction serverTransaction, 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");
@@ -828,7 +819,7 @@
        content.append("f=\r\n");
        try {
            return responseSdpAck(serverTransaction, content.toString(), platform);
            return responseSdpAck(request, content.toString(), platform);
        } catch (SipException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
@@ -839,18 +830,18 @@
        return null;
    }
    public void inviteFromDeviceHandle(ServerTransaction serverTransaction, String requesterId) {
    public void inviteFromDeviceHandle(SIPRequest request, String requesterId) {
        // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
        Device device = redisCatchStorage.getDevice(requesterId);
        if (device != null) {
            logger.info("收到设备" + requesterId + "的语音广播Invite请求");
            try {
                responseAck(serverTransaction, Response.TRYING);
                responseAck(request, Response.TRYING);
            } catch (SipException | InvalidArgumentException | ParseException e) {
                logger.error("[命令发送失败] invite BAD_REQUEST: {}", e.getMessage());
            }
            String contentString = new String(serverTransaction.getRequest().getRawContent());
            String contentString = new String(request.getRawContent());
            // jainSip不支持y=字段, 移除移除以解析。
            String substring = contentString;
            String ssrc = "0000000404";
@@ -900,7 +891,7 @@
                    logger.info("不支持的媒体格式,返回415");
                    // 回复不支持的格式
                    try {
                        responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
                        responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] invite 不支持的媒体格式,返回415, {}", e.getMessage());
                    }
@@ -918,7 +909,7 @@
        } else {
            logger.warn("来自无效设备/平台的请求");
            try {
                responseAck(serverTransaction, Response.BAD_REQUEST);; // 不支持的格式,发415
                responseAck(request, Response.BAD_REQUEST);; // 不支持的格式,发415
            } catch (SipException | InvalidArgumentException | ParseException e) {
                logger.error("[命令发送失败] invite 来自无效设备/平台的请求, {}", e.getMessage());
            }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -20,6 +20,7 @@
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -34,7 +35,6 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.header.FromHeader;
import javax.sip.message.Response;
@@ -93,9 +93,8 @@
    @Override
    public void process(RequestEvent evt) {
        ServerTransaction serverTransaction = getServerTransaction(evt);
        try {
            responseAck(serverTransaction, Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null);
        }catch (SipException | InvalidArgumentException | ParseException e) {
            e.printStackTrace();
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -4,6 +4,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
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.auth.DigestServerAuthenticationHelper;
@@ -22,9 +23,7 @@
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.header.*;
import javax.sip.message.Request;
@@ -52,6 +51,9 @@
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private SIPSender sipSender;
    @Override
    public void afterPropertiesSet() throws Exception {
@@ -86,7 +88,7 @@
                logger.info("[注册请求] 未携带授权头 回复401: {}", requestAddress);
                response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
                new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
                sendResponse(evt, response);
                sipSender.transmitRequest(response);
                return;
            }
@@ -99,7 +101,7 @@
                response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
                response.setReasonPhrase("wrong password");
                logger.info("[注册请求] 密码/SIP服务器ID错误, 回复403: {}", requestAddress);
                sendResponse(evt, response);
                sipSender.transmitRequest(response);
                return;
            }
@@ -116,11 +118,7 @@
            if (expiresHeader == null) {
                response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
                ServerTransaction serverTransaction = getServerTransaction(evt);
                serverTransaction.sendResponse(response);
                if (serverTransaction.getDialog() != null) {
                    serverTransaction.getDialog().delete();
                }
                sipSender.transmitRequest(response);
                return;
            }
            // 添加Contact头
@@ -162,7 +160,7 @@
                device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
            }
            sendResponse(evt, response);
            sipSender.transmitRequest(response);
            // 注册成功
            // 保存到redis
            if (registerFlag) {
@@ -173,22 +171,8 @@
                logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
                deviceService.offline(deviceId);
            }
        } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) {
        } catch (SipException | NoSuchAlgorithmException | ParseException e) {
            e.printStackTrace();
        }
    }
    private void sendResponse(RequestEvent evt, Response response) throws InvalidArgumentException, SipException {
        ServerTransaction serverTransaction = getServerTransaction(evt);
        if (serverTransaction == null) {
            logger.warn("[回复失败]:{}", response);
            return;
        }
        serverTransaction.sendResponse(response);
        if (serverTransaction.getDialog() != null) {
            serverTransaction.getDialog().delete();
        }
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
@@ -9,6 +9,8 @@
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
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;
@@ -19,23 +21,16 @@
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPClientTransaction;
import gov.nist.javax.sip.stack.SIPDialog;
import gov.nist.javax.sip.stack.SIPServerTransaction;
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.sip.*;
import javax.sip.header.ExpiresHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -58,6 +53,9 @@
    @Autowired
    private SubscribeHolder subscribeHolder;
    @Autowired
    private SIPSender sipSender;
    @Override
    public void afterPropertiesSet() throws Exception {
        // 添加消息处理的订阅
@@ -71,8 +69,7 @@
     */
    @Override
    public void process(RequestEvent evt) {
        ServerTransaction serverTransaction = getServerTransaction(evt);
        Request request = evt.getRequest();
        SIPRequest request = (SIPRequest) evt.getRequest();
        try {
            Element rootElement = getRootElement(evt);
            if (rootElement == null) {
@@ -81,12 +78,12 @@
            }
            String cmd = XmlUtil.getText(rootElement, "CmdType");
            if (CmdType.MOBILE_POSITION.equals(cmd)) {
                processNotifyMobilePosition(serverTransaction, rootElement);
                processNotifyMobilePosition(request, rootElement);
//            } else if (CmdType.ALARM.equals(cmd)) {
//                logger.info("接收到Alarm订阅");
//                processNotifyAlarm(serverTransaction, rootElement);
            } else if (CmdType.CATALOG.equals(cmd)) {
                processNotifyCatalogList(serverTransaction, rootElement);
                processNotifyCatalogList(request, rootElement);
            } else {
                logger.info("接收到消息:" + cmd);
@@ -96,13 +93,7 @@
                    response.setExpires(expireHeader);
                }
                logger.info("response : " + response);
                ServerTransaction transaction = getServerTransaction(evt);
                if (transaction != null) {
                    transaction.sendResponse(response);
                    transaction.terminate();
                } else {
                    logger.info("processRequest serverTransactionId is null.");
                }
                sipSender.transmitRequest(response);
            }
        } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
            e.printStackTrace();
@@ -113,14 +104,14 @@
    /**
     * 处理移动位置订阅消息
     */
    private void processNotifyMobilePosition(ServerTransaction serverTransaction, Element rootElement) throws SipException {
        if (serverTransaction == null) {
    private void processNotifyMobilePosition(SIPRequest request, Element rootElement) throws SipException {
        if (request == null) {
            return;
        }
        String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
        String platformId = SipUtils.getUserIdFromFromHeader(request);
        String deviceId = XmlUtil.getText(rootElement, "DeviceID");
        ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
        SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
        SubscribeInfo subscribeInfo = new SubscribeInfo(request, platformId);
        if (platform == null) {
            return;
        }
@@ -149,7 +140,7 @@
        try {
            ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
            SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
            SIPResponse response = responseXmlAck(request, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
            if (subscribeInfo.getExpires() == 0) {
                subscribeHolder.removeMobilePositionSubscribe(platformId);
            }else {
@@ -166,17 +157,17 @@
    }
    private void processNotifyCatalogList(ServerTransaction serverTransaction, Element rootElement) throws SipException {
        if (serverTransaction == null) {
    private void processNotifyCatalogList(SIPRequest request, Element rootElement) throws SipException {
        if (request == null) {
            return;
        }
        String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest());
        String platformId = SipUtils.getUserIdFromFromHeader(request);
        String deviceId = XmlUtil.getText(rootElement, "DeviceID");
        ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
        if (platform == null){
            return;
        }
        SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId);
        SubscribeInfo subscribeInfo = new SubscribeInfo(request, platformId);
        String sn = XmlUtil.getText(rootElement, "SN");
        logger.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId);
@@ -196,7 +187,7 @@
        }
        try {
            ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
            SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
            SIPResponse response = responseXmlAck(request, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
            if (subscribeInfo.getExpires() == 0) {
                subscribeHolder.removeCatalogSubscribe(platformId);
            }else {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
@@ -19,7 +19,6 @@
import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.header.*;
import javax.sip.message.Response;
@@ -62,8 +61,9 @@
    @Override
    public void process(RequestEvent evt) {
        logger.debug("接收到消息:" + evt.getRequest());
        String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
        CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
        SIPRequest request = (SIPRequest) evt.getRequest();
        String deviceId = SipUtils.getUserIdFromFromHeader(request);
        CallIdHeader callIdHeader = request.getCallIdHeader();
        // 先从会话内查找
        SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
@@ -71,7 +71,6 @@
        if (ssrcTransaction != null) {
            deviceId = ssrcTransaction.getDeviceId();
        }
        ServerTransaction serverTransaction = getServerTransaction(evt);
        // 查询设备是否存在
        Device device = redisCatchStorage.getDevice(deviceId);
        // 查询上级平台是否存在
@@ -79,7 +78,6 @@
        try {
            if (device != null && parentPlatform != null) {
                logger.warn("[重复]平台与设备编号重复:{}", deviceId);
                SIPRequest request = (SIPRequest) evt.getRequest();
                String hostAddress = request.getRemoteAddress().getHostAddress();
                int remotePort = request.getRemotePort();
                if (device.getHostAddress().equals(hostAddress + ":" + remotePort)) {
@@ -90,7 +88,7 @@
            }
            if (device == null && parentPlatform == null) {
                // 不存在则回复404
                responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
                responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found");
                logger.warn("[设备未找到 ]: {}", deviceId);
                if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
                    DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
@@ -107,21 +105,21 @@
                    String streamId = sendRtpItem.getStreamId();
                    StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
                    if (null == streamInfo) {
                        responseAck(serverTransaction, Response.NOT_FOUND, "stream " + streamId + " not found");
                        responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found");
                        return;
                    }
                    Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID());
                    cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> {
                        // 失败的回复
                        try {
                            responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
                            responseAck(request, eventResult.statusCode, eventResult.msg);
                        } catch (SipException | InvalidArgumentException | ParseException e) {
                            logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
                        }
                    }, eventResult -> {
                        // 成功的回复
                        try {
                            responseAck(serverTransaction, eventResult.statusCode);
                            responseAck(request, eventResult.statusCode);
                        } catch (SipException | InvalidArgumentException | ParseException e) {
                            logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
                        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
@@ -23,12 +23,8 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.Map;
@@ -80,16 +76,13 @@
        if (ssrcTransaction != null) {
            deviceId = ssrcTransaction.getDeviceId();
        }
        ServerTransaction serverTransaction = getServerTransaction(evt);
        SIPRequest request = (SIPRequest) evt.getRequest();
        // 查询设备是否存在
        Device device = redisCatchStorage.getDevice(deviceId);
        // 查询上级平台是否存在
        ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
        try {
            if (device != null && parentPlatform != null) {
                SIPRequest request = (SIPRequest) evt.getRequest();
                String hostAddress = request.getRemoteAddress().getHostAddress();
                int remotePort = request.getRemotePort();
                if (device.getHostAddress().equals(hostAddress + ":" + remotePort)) {
@@ -100,7 +93,7 @@
            }
            if (device == null && parentPlatform == null) {
                // 不存在则回复404
                responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
                responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found");
                logger.warn("[设备未找到 ]: {}", deviceId);
                if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
                    DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
@@ -114,13 +107,13 @@
                    rootElement = getRootElement(evt);
                    if (rootElement == null) {
                        logger.error("处理MESSAGE请求  未获取到消息体{}", evt.getRequest());
                        responseAck(serverTransaction, Response.BAD_REQUEST, "content is null");
                        responseAck(request, Response.BAD_REQUEST, "content is null");
                        return;
                    }
                } catch (DocumentException e) {
                    logger.warn("解析XML消息内容异常", e);
                    // 不存在则回复404
                    responseAck(serverTransaction, Response.BAD_REQUEST, e.getMessage());
                    responseAck(request, Response.BAD_REQUEST, e.getMessage());
                }
                String name = rootElement.getName();
                IMessageHandler messageHandler = messageHandlerMap.get(name);
@@ -133,7 +126,7 @@
                }else {
                    // 不支持的message
                    // 不存在则回复415
                    responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
                    responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
                }
            }
        } catch (SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
@@ -11,6 +11,7 @@
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,10 +68,10 @@
    @Override
    public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
        ServerTransaction serverTransaction = getServerTransaction(evt);
        SIPRequest request = (SIPRequest) evt.getRequest();
        // 此处是上级发出的DeviceControl指令
        String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
        String targetGBId = ((SipURI) request.getToHeader().getAddress().getURI()).getUser();
        String channelId = getText(rootElement, "DeviceID");
        // 远程启动功能
        if (!ObjectUtils.isEmpty(getText(rootElement, "TeleBoot"))) {
@@ -111,7 +112,7 @@
            Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
            if (deviceForPlatform == null) {
                try {
                    responseAck(serverTransaction, Response.NOT_FOUND);
                    responseAck(request, Response.NOT_FOUND);
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] 错误信息: {}", e.getMessage());
                }
@@ -121,14 +122,14 @@
                cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
                    // 失败的回复
                    try {
                        responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
                        responseAck(request, eventResult.statusCode, eventResult.msg);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
                    }
                }, eventResult -> {
                    // 成功的回复
                    try {
                        responseAck(serverTransaction, eventResult.statusCode);
                        responseAck(request, eventResult.statusCode);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
                    }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
@@ -16,6 +16,7 @@
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,7 +98,7 @@
                    SipMsgInfo sipMsgInfo = taskQueue.poll();
                    // 回复200 OK
                    try {
                        responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK);
                        responseAck((SIPRequest) sipMsgInfo.getEvt().getRequest(), Response.OK);
                    } catch (SipException | InvalidArgumentException | ParseException e) {
                        logger.error("[处理报警通知], 回复200OK失败", e);
                    }
@@ -216,7 +217,7 @@
        logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId());
        // 回复200 OK
        try {
            responseAck(getServerTransaction(evt), Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 报警通知回复: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -10,6 +10,7 @@
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,7 +55,7 @@
        }
        // 回复200 OK
        try {
            responseAck(getServerTransaction(evt), Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 心跳回复: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
@@ -14,6 +14,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,7 +68,7 @@
        // 回复200 OK
        try {
            responseAck(getServerTransaction(evt), Response.OK);
             responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 录像流推送完毕,回复200OK: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
@@ -11,6 +11,7 @@
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -83,7 +84,7 @@
                        if (rootElementAfterCharset == null) {
                            try {
                                logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", sipMsgInfo.getEvt().getRequest());
                                responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.BAD_REQUEST);
                                responseAck((SIPRequest) sipMsgInfo.getEvt().getRequest(), Response.BAD_REQUEST);
                            } catch (SipException | InvalidArgumentException | ParseException e) {
                                logger.error("[命令发送失败] 移动设备位置数据通知 内容为空: {}", e.getMessage());
                            }
@@ -138,7 +139,7 @@
                        storager.updateChannelPosition(deviceChannel);
                        //回复 200 OK
                        try {
                            responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK);
                            responseAck((SIPRequest) sipMsgInfo.getEvt().getRequest(), Response.OK);
                        } catch (SipException | InvalidArgumentException | ParseException e) {
                            logger.error("[命令发送失败] 移动设备位置数据回复200: {}", e.getMessage());
                        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java
@@ -9,6 +9,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,7 +59,7 @@
        logger.info("不支持alarm查询");
        try {
            responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query");
             responseAck((SIPRequest) evt.getRequest(), Response.NOT_FOUND, "not support alarm query");
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 alarm查询回复200OK: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
@@ -9,6 +9,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,7 +67,7 @@
        FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
        try {
            // 回复200 OK
            responseAck(getServerTransaction(evt), Response.OK);
             responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 目录查询回复200OK: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,7 +49,7 @@
        FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
        try {
            // 回复200 OK
            responseAck(getServerTransaction(evt), Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] DeviceInfo查询回复: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java
@@ -9,6 +9,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,7 +62,7 @@
        FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
        // 回复200 OK
        try {
            responseAck(getServerTransaction(evt), Response.OK);
             responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java
@@ -12,6 +12,7 @@
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,9 +22,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.header.FromHeader;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.List;
@@ -68,8 +67,7 @@
    @Override
    public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
        FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
        ServerTransaction serverTransaction = getServerTransaction(evt);
        SIPRequest request = (SIPRequest) evt.getRequest();
        Element snElement = rootElement.element("SN");
        int sn = Integer.parseInt(snElement.getText());
        Element deviceIDElement = rootElement.element("DeviceID");
@@ -104,7 +102,7 @@
            // 接收录像数据
            recordEndEventListener.addEndEventHandler(deviceChannel.getDeviceId(), channelId, (recordInfo)->{
                try {
                    cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, fromHeader.getTag(), recordInfo);
                    cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, request.getFromTag(), recordInfo);
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
                }
@@ -114,14 +112,14 @@
                        DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
                            // 回复200 OK
                            try {
                                responseAck(serverTransaction, Response.OK);
                                responseAck(request, Response.OK);
                            } catch (SipException | InvalidArgumentException | ParseException e) {
                                logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
                            }
                        }),(eventResult -> {
                            // 查询失败
                            try {
                                responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
                                responseAck(request, eventResult.statusCode, eventResult.msg);
                            } catch (SipException | InvalidArgumentException | ParseException e) {
                                logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
                            }
@@ -133,13 +131,13 @@
        }else if (channelSources.get(1).getCount() > 0) { // 直播流
            // TODO
            try {
                responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
                responseAck(request, Response.NOT_IMPLEMENTED); // 回复未实现
            } catch (SipException | InvalidArgumentException | ParseException e) {
                logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
            }
        }else { // 错误的请求
            try {
                responseAck(serverTransaction, Response.BAD_REQUEST);
                responseAck(request, Response.BAD_REQUEST);
            } catch (SipException | InvalidArgumentException | ParseException e) {
                logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
            }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
@@ -9,6 +9,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,7 +19,6 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -47,9 +47,8 @@
        try {
            String channelId = getText(rootElement, "DeviceID");
            String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId;
            ServerTransaction serverTransaction = getServerTransaction(evt);
            // 回复200 OK
            responseAck(serverTransaction, Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
            // 此处是对本平台发出Broadcast指令的应答
            JSONObject json = new JSONObject();
            XmlUtil.node2Json(rootElement, json);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -14,6 +14,7 @@
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -27,7 +28,6 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -71,9 +71,8 @@
    public void handForDevice(RequestEvent evt, Device device, Element element) {
        taskQueue.offer(new HandlerCatchData(evt, device, element));
        // 回复200 OK
        ServerTransaction serverTransaction = getServerTransaction(evt);
        try {
            responseAck(serverTransaction, Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java
@@ -10,6 +10,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +53,7 @@
        String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
        try {
            // 回复200 OK
            responseAck(getServerTransaction(evt), Response.OK);
            responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 设备配置查询: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java
@@ -9,6 +9,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,7 +47,7 @@
    public void handForDevice(RequestEvent evt, Device device, Element element) {
        // 此处是对本平台发出DeviceControl指令的应答
        try {
            responseAck(getServerTransaction(evt), Response.OK);
             responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 设备控制: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
@@ -13,6 +13,7 @@
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -21,11 +22,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -75,14 +74,14 @@
            logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]:" + (device != null ? device.getDeviceId():"" ));
            return;
        }
        ServerTransaction serverTransaction = getServerTransaction(evt);
        SIPRequest request = (SIPRequest) evt.getRequest();
        try {
            rootElement = getRootElement(evt, device.getCharset());
        if (rootElement == null) {
            if (rootElement == null) {
                logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest());
                try {
                    responseAck(serverTransaction, Response.BAD_REQUEST);
                    responseAck((SIPRequest) evt.getRequest(), Response.BAD_REQUEST);
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] DeviceInfo应答消息 BAD_REQUEST: {}", e.getMessage());
                }
@@ -110,7 +109,7 @@
        }
        try {
            // 回复200 OK
            responseAck(serverTransaction, Response.OK);
            responseAck(request, Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] DeviceInfo应答消息 200: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
@@ -13,6 +13,7 @@
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,7 +60,7 @@
        }
        // 回复200 OK
        try {
            responseAck(getServerTransaction(evt), Response.OK);
             responseAck((SIPRequest) evt.getRequest(), Response.OK);
        } catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 设备状态应答回复200OK: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
@@ -13,6 +13,7 @@
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.GpsUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -21,11 +22,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -64,15 +63,14 @@
    @Override
    public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
        ServerTransaction serverTransaction = getServerTransaction(evt);
        SIPRequest request = (SIPRequest) evt.getRequest();
        try {
            rootElement = getRootElement(evt, device.getCharset());
            if (rootElement == null) {
                logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest());
                try {
                    responseAck(serverTransaction, Response.BAD_REQUEST);
                    responseAck(request, Response.BAD_REQUEST);
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] 移动设备位置数据查询 BAD_REQUEST: {}", e.getMessage());
                }
@@ -138,7 +136,7 @@
            redisCatchStorage.sendMobilePositionMsg(jsonObject);
            //回复 200 OK
            try {
                responseAck(serverTransaction, Response.OK);
                responseAck(request, Response.OK);
            } catch (SipException | InvalidArgumentException | ParseException e) {
                logger.error("[命令发送失败] 移动设备位置数据查询 200: {}", e.getMessage());
            }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
@@ -7,6 +7,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -17,7 +18,6 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -51,7 +51,7 @@
    @Override
    public void handForDevice(RequestEvent evt, Device device, Element element) {
        ServerTransaction serverTransaction = getServerTransaction(evt);
        SIPRequest request = (SIPRequest) evt.getRequest();
        try {
             Element rootElement = getRootElement(evt, device.getCharset());
@@ -59,7 +59,7 @@
            if (rootElement == null) {
                logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
                try {
                    responseAck(serverTransaction, Response.BAD_REQUEST);
                    responseAck(request, Response.BAD_REQUEST);
                } catch (InvalidArgumentException | ParseException | SipException e) {
                    logger.error("[命令发送失败] 设备预置位查询应答处理: {}", e.getMessage());
                }
@@ -72,7 +72,7 @@
            String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
            if (snElement == null || presetListNumElement == null) {
                try {
                    responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
                    responseAck(request, Response.BAD_REQUEST, "xml error");
                } catch (InvalidArgumentException | ParseException | SipException e) {
                    logger.error("[命令发送失败] 设备预置位查询应答处理: {}", e.getMessage());
                }
@@ -103,7 +103,7 @@
            requestMessage.setData(presetQuerySipReqList);
            deferredResultHolder.invokeAllResult(requestMessage);
            try {
                responseAck(serverTransaction, Response.OK);
                responseAck(request, Response.OK);
            } catch (InvalidArgumentException | ParseException | SipException e) {
                logger.error("[命令发送失败] 设备预置位查询应答处理: {}", e.getMessage());
            }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
@@ -10,6 +10,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger;
@@ -71,7 +72,7 @@
    public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
        try {
            // 回复200 OK
            responseAck(getServerTransaction(evt), Response.OK);
             responseAck((SIPRequest) evt.getRequest(), Response.OK);
        }catch (SipException | InvalidArgumentException | ParseException e) {
            logger.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage());
        }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
@@ -5,6 +5,7 @@
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
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.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
@@ -49,25 +50,14 @@
    private final String method = "INVITE";
    @Autowired
    private VideoStreamSessionManager streamSession;
    @Autowired
    private SIPProcessorObserver sipProcessorObserver;
    @Autowired
    private SipConfig sipConfig;
    @Autowired
    private SipFactory sipFactory;
    @Autowired
    private GitUtil gitUtil;
    @Autowired
    private ISIPCommander commander;
    @Autowired
    private IDeviceService deviceService;
    private SIPSender sipSender;
    @Autowired
    private SIPRequestHeaderProvider headerProvider;
@@ -121,8 +111,7 @@
                Request reqAck = headerProvider.createAckRequest(requestUri, response);
                logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());
                commander.transmitRequest(response.getTopmostViaHeader().getTransport(), reqAck, null, null);
                sipSender.transmitRequest(reqAck);
            }
        } catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
            logger.info("[点播回复ACK],异常:", e );
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
@@ -4,6 +4,7 @@
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.header.Subject;
import org.springframework.util.ObjectUtils;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
@@ -52,10 +53,15 @@
    public static UserAgentHeader createUserAgentHeader(SipFactory sipFactory, GitUtil gitUtil) throws PeerUnavailableException, ParseException {
        List<String> agentParam = new ArrayList<>();
        agentParam.add("WVP-Pro v");
        if (gitUtil != null && gitUtil.getCommitTime() != null) {
            agentParam.add(gitUtil.getBuildVersion() + ".");
            agentParam.add(gitUtil.getCommitTime());
        agentParam.add("WVP-Pro ");
        if (gitUtil != null ) {
            if (!ObjectUtils.isEmpty(gitUtil.getBuildVersion())) {
                agentParam.add("v");
                agentParam.add(gitUtil.getBuildVersion() + ".");
            }
            if (!ObjectUtils.isEmpty(gitUtil.getCommitTime())) {
                agentParam.add(gitUtil.getCommitTime());
            }
        }
        return sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
    }
src/main/java/com/genersoft/iot/vmp/utils/GitUtil.java
@@ -11,22 +11,22 @@
@PropertySource(value = {"classpath:git.properties" }, ignoreResourceNotFound = true)
public class GitUtil {
    @Value("${git.branch:null}")
    @Value("${git.branch:}")
    private String branch;
    @Value("${git.commit.id:null}")
    @Value("${git.commit.id:}")
    private String gitCommitId;
    @Value("${git.remote.origin.url:null}")
    @Value("${git.remote.origin.url:}")
    private String gitUrl;
    @Value("${git.build.time:null}")
    @Value("${git.build.time:}")
    private String buildDate;
    @Value("${git.build.version:null}")
    @Value("${git.build.version:}")
    private String buildVersion;
    @Value("${git.commit.id.abbrev:null}")
    @Value("${git.commit.id.abbrev:}")
    private String commitIdShort;
    @Value("${git.commit.time:null}")
    @Value("${git.commit.time:}")
    private String commitTime;
    public String getGitCommitId() {