swwheihei
2020-07-16 29710b7cc154191ae56acf6af32ec70241886e78
Merge branch 'master' of https://github.com/swwheihei/wvp.git

Conflicts:
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
48个文件已修改
1个文件已添加
804 ■■■■■ 已修改文件
LICENSE 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java 512 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/DeviceOffLineDetector.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/ISIPRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/CancelRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/SubscribeRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/ByeResponseProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/CancelResponseProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/OtherResponseProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/VideoManagerStoragerFactory.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/SpringBeanFactory.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/redis/FastJsonRedisSerializer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wikis/images/核心流程.png 补丁 | 查看 | 原始文档 | blame | 历史
LICENSE
New file
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 swwhaha
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
pom.xml
@@ -39,7 +39,7 @@
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
@@ -127,7 +127,7 @@
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.1</version>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -2,7 +2,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2019å¹´5月30日 ä¸‹åˆ3:04:04   
 *   
 */
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
@@ -13,7 +13,7 @@
/**
 * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
 * @author: swwheihei
 * @author: songww
 * @date: 2019å¹´5月30日 ä¸Šåˆ10:58:25
 * 
 */
src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java
@@ -5,7 +5,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ2:46:00     
 */
@Configuration("vmConfig")
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -1,250 +1,262 @@
package com.genersoft.iot.vmp.gb28181;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.ListeningPoint;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipFactory;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionAlreadyExistsException;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.TransactionUnavailableException;
import javax.sip.address.AddressFactory;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
import gov.nist.javax.sip.SipStackImpl;
@Component
public class SipLayer implements SipListener, Runnable {
    private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
    @Autowired
    private SipConfig sipConfig;
    private SipProvider tcpSipProvider;
    private SipProvider udpSipProvider;
    @Autowired
    private SIPProcessorFactory processorFactory;
    private SipStack sipStack;
    private AddressFactory addressFactory;
    private HeaderFactory headerFactory;
    private MessageFactory messageFactory;
    @PostConstruct
    private void initSipServer() {
        Thread thread=new Thread(this);
        thread.setDaemon(true);
        thread.setName("sip server thread start");
        thread.start();
    }
    @Override
    public void run() {
        SipFactory sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");
        try {
            headerFactory = sipFactory.createHeaderFactory();
            addressFactory = sipFactory.createAddressFactory();
            messageFactory = sipFactory.createMessageFactory();
            Properties properties = new Properties();
            properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
            properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getSipIp());
            properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
            /**
             * sip_server_log.log å’Œ sip_debug_log.log public static final int TRACE_NONE =
             * 0; public static final int TRACE_MESSAGES = 16; public static final int
             * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
             */
            properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0");
            properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
            properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
            sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
            startTcpListener();
            startUdpListener();
        } catch (Exception e) {
            logger.error("Sip Server å¯åŠ¨å¤±è´¥ï¼ port {" + sipConfig.getSipPort() + "}");
            e.printStackTrace();
        }
        logger.info("Sip Server å¯åŠ¨æˆåŠŸ port {" + sipConfig.getSipPort() + "}");
    }
    private void startTcpListener() throws Exception {
        ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(), "TCP");
        tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
        tcpSipProvider.addSipListener(this);
    }
    private void startUdpListener() throws Exception {
        ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(), "UDP");
        udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
        udpSipProvider.addSipListener(this);
    }
    /**
     * SIP服务端接收消息的方法 Content é‡Œé¢æ˜¯GBK编码 This method is called by the SIP stack when a
     * new request arrives.
     */
    @Override
    public void processRequest(RequestEvent evt) {
        ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt);
        processor.process(evt, this);
    }
    @Override
    public void processResponse(ResponseEvent evt) {
        Response response = evt.getResponse();
        int status = response.getStatusCode();
        if ((status >= 200) && (status < 300)) { // Success!
            ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
            processor.process(evt, this, sipConfig);
        } else {
            logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getContent().toString());
        }
        // trying不会回复
        if (status == Response.TRYING) {
        }
    }
    /**
     * <p>
     * Title: processTimeout
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param timeoutEvent
     */
    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        // TODO Auto-generated method stub
    }
    /**
     * <p>
     * Title: processIOException
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param exceptionEvent
     */
    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
        // TODO Auto-generated method stub
    }
    /**
     * <p>
     * Title: processTransactionTerminated
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param transactionTerminatedEvent
     */
    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        // TODO Auto-generated method stub
    }
    /**
     * <p>
     * Title: processDialogTerminated
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param dialogTerminatedEvent
     */
    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        // TODO Auto-generated method stub
    }
    public ServerTransaction getServerTransaction(RequestEvent evt) {
        Request request = evt.getRequest();
        ServerTransaction serverTransaction = evt.getServerTransaction();
        // åˆ¤æ–­TCP还是UDP
        boolean isTcp = false;
        ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = reqViaHeader.getTransport();
        if (transport.equals("TCP")) {
            isTcp = true;
        }
        if (serverTransaction == null) {
            try {
                if (isTcp) {
                    serverTransaction = tcpSipProvider.getNewServerTransaction(request);
                } else {
                    serverTransaction = udpSipProvider.getNewServerTransaction(request);
                }
            } catch (TransactionAlreadyExistsException e) {
                e.printStackTrace();
            } catch (TransactionUnavailableException e) {
                e.printStackTrace();
            }
        }
        return serverTransaction;
    }
    public AddressFactory getAddressFactory() {
        return addressFactory;
    }
    public HeaderFactory getHeaderFactory() {
        return headerFactory;
    }
    public MessageFactory getMessageFactory() {
        return messageFactory;
    }
    public SipProvider getTcpSipProvider() {
        return tcpSipProvider;
    }
    public SipProvider getUdpSipProvider() {
        return udpSipProvider;
    }
}
package com.genersoft.iot.vmp.gb28181;
import java.text.ParseException;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.ListeningPoint;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipFactory;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionAlreadyExistsException;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.TransactionUnavailableException;
import javax.sip.address.AddressFactory;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
import gov.nist.javax.sip.SipStackImpl;
@Component
public class SipLayer implements SipListener, Runnable {
    private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
    @Autowired
    private SipConfig sipConfig;
    private SipProvider tcpSipProvider;
    private SipProvider udpSipProvider;
    @Autowired
    private SIPProcessorFactory processorFactory;
    private SipStack sipStack;
    private AddressFactory addressFactory;
    private HeaderFactory headerFactory;
    private MessageFactory messageFactory;
    @PostConstruct
    private void initSipServer() {
        Thread thread = new Thread(this);
        thread.setDaemon(true);
        thread.setName("sip server thread start");
        thread.start();
    }
    @Override
    public void run() {
        SipFactory sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");
        try {
            headerFactory = sipFactory.createHeaderFactory();
            addressFactory = sipFactory.createAddressFactory();
            messageFactory = sipFactory.createMessageFactory();
            Properties properties = new Properties();
            properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
            properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getSipIp());
            properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
            /**
             * sip_server_log.log å’Œ sip_debug_log.log public static final int TRACE_NONE =
             * 0; public static final int TRACE_MESSAGES = 16; public static final int
             * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
             */
            properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
            properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
            properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
            sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
            startTcpListener();
            startUdpListener();
        } catch (Exception e) {
            logger.error("Sip Server å¯åŠ¨å¤±è´¥ï¼ port {" + sipConfig.getSipPort() + "}");
            e.printStackTrace();
        }
        logger.info("Sip Server å¯åŠ¨æˆåŠŸ port {" + sipConfig.getSipPort() + "}");
    }
    private void startTcpListener() throws Exception {
        ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(),
                "TCP");
        tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
        tcpSipProvider.addSipListener(this);
    }
    private void startUdpListener() throws Exception {
        ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(),
                "UDP");
        udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
        udpSipProvider.addSipListener(this);
    }
    /**
     * SIP服务端接收消息的方法 Content é‡Œé¢æ˜¯GBK编码 This method is called by the SIP stack when a
     * new request arrives.
     */
    @Override
    public void processRequest(RequestEvent evt) {
        ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt);
        processor.process(evt, this);
    }
    @Override
    public void processResponse(ResponseEvent evt) {
        Response response = evt.getResponse();
        int status = response.getStatusCode();
        if ((status >= 200) && (status < 300)) { // Success!
            ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
            try {
                processor.process(evt, this, sipConfig);
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        // } else if (status == Response.TRYING) {
            // trying不会回复
        } else if ((status >= 100) && (status < 200)) {
            // å¢žåŠ å…¶å®ƒæ— éœ€å›žå¤çš„å“åº”ï¼Œå¦‚101、180等
        } else {
            logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
        }
        // trying不会回复
        // if (status == Response.TRYING) {
        // }
    }
    /**
     * <p>
     * Title: processTimeout
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param timeoutEvent
     */
    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        // TODO Auto-generated method stub
    }
    /**
     * <p>
     * Title: processIOException
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param exceptionEvent
     */
    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
        // TODO Auto-generated method stub
    }
    /**
     * <p>
     * Title: processTransactionTerminated
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param transactionTerminatedEvent
     */
    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        // TODO Auto-generated method stub
    }
    /**
     * <p>
     * Title: processDialogTerminated
     * </p>
     * <p>
     * Description:
     * </p>
     *
     * @param dialogTerminatedEvent
     */
    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        // TODO Auto-generated method stub
    }
    public ServerTransaction getServerTransaction(RequestEvent evt) {
        Request request = evt.getRequest();
        ServerTransaction serverTransaction = evt.getServerTransaction();
        // åˆ¤æ–­TCP还是UDP
        boolean isTcp = false;
        ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = reqViaHeader.getTransport();
        if (transport.equals("TCP")) {
            isTcp = true;
        }
        if (serverTransaction == null) {
            try {
                if (isTcp) {
                    serverTransaction = tcpSipProvider.getNewServerTransaction(request);
                } else {
                    serverTransaction = udpSipProvider.getNewServerTransaction(request);
                }
            } catch (TransactionAlreadyExistsException e) {
                e.printStackTrace();
            } catch (TransactionUnavailableException e) {
                e.printStackTrace();
            }
        }
        return serverTransaction;
    }
    public AddressFactory getAddressFactory() {
        return addressFactory;
    }
    public HeaderFactory getHeaderFactory() {
        return headerFactory;
    }
    public MessageFactory getMessageFactory() {
        return messageFactory;
    }
    public SipProvider getTcpSipProvider() {
        return tcpSipProvider;
    }
    public SipProvider getUdpSipProvider() {
        return udpSipProvider;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
@@ -8,7 +8,7 @@
/**    
 * @Description:注册逻辑处理,当设备注册后触发逻辑。
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸‹åˆ9:41:46     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
@@ -4,7 +4,7 @@
/**    
 * @Description:设备录像信息bean 
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸‹åˆ2:05:56     
 */
public class RecordInfo {
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
@@ -2,7 +2,7 @@
/**    
 * @Description:设备录像bean 
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸‹åˆ2:06:54     
 */
public class RecordItem {
src/main/java/com/genersoft/iot/vmp/gb28181/event/DeviceOffLineDetector.java
@@ -8,7 +8,7 @@
/**    
 * @Description:设备离在线状态检测器,用于检测设备状态
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月13日 ä¸‹åˆ2:40:29     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
@@ -9,7 +9,7 @@
/**    
 * @Description:Event事件通知推送器,支持推送在线事件、离线事件
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸Šåˆ11:30:50     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java
@@ -11,7 +11,7 @@
/**    
 * @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸Šåˆ11:35:46     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java
@@ -4,7 +4,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸Šåˆ11:33:13     
 */
public class OfflineEvent extends ApplicationEvent {
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java
@@ -14,7 +14,7 @@
 * @Description: ç¦»çº¿äº‹ä»¶ç›‘听器,监听到离线后,修改设备离在线状态。 è®¾å¤‡ç¦»çº¿æœ‰ä¸¤ä¸ªæ¥æºï¼š
 *               1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
 *               2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}
 * @author: swwheihei
 * @author: songww
 * @date: 2020å¹´5月6日 ä¸‹åˆ1:51:23
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java
@@ -4,7 +4,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸Šåˆ11:32:56     
 */
public class OnlineEvent extends ApplicationEvent {
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
@@ -14,7 +14,7 @@
 * @Description: åœ¨çº¿äº‹ä»¶ç›‘听器,监听到离线后,修改设备离在线状态。 è®¾å¤‡åœ¨çº¿æœ‰ä¸¤ä¸ªæ¥æºï¼š
 *               1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
 *               2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor}
 * @author: swwheihei
 * @author: songww
 * @date: 2020å¹´5月6日 ä¸‹åˆ1:51:23
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java
@@ -9,7 +9,7 @@
/**
 * @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数
 * @author: swwheihei
 * @author: songww
 * @date: 2020å¹´5月10日 ä¸Šåˆ11:57:57
 */
public class SsrcUtil {
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -8,7 +8,7 @@
/**    
 * @Description:视频流session管理器,管理视频预览、预览回放的通信句柄 
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月13日 ä¸‹åˆ4:03:02     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -26,7 +26,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ4:24:37     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
@@ -10,7 +10,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸‹åˆ7:59:05     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
@@ -2,7 +2,7 @@
/**    
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸‹åˆ1:09:18     
 */
public class RequestMessage {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -4,7 +4,7 @@
/**    
 * @Description:设备能力接口,用于定义设备的控制、查询能力   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ9:16:34     
 */
public interface ISIPCommander {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -25,7 +25,7 @@
/**
 * @Description:摄像头命令request创造器 TODO å†—余代码太多待优化
 * @author: swwheihei
 * @author: songww
 * @date: 2020å¹´5月6日 ä¸Šåˆ9:29:02
 */
@Component
@@ -79,7 +79,8 @@
        SipURI requestLine = layer.getAddressFactory().createSipURI(channelId, host.getAddress());
        //via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
        // ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
        ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(device.getHost().getIp(), device.getHost().getPort(), device.getTransport(), viaTag);
        viaHeader.setRPort();
        viaHeaders.add(viaHeader);
        //from
@@ -108,6 +109,7 @@
        request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
        
        Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
        // Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort()));
        request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress));
        
        ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
@@ -122,7 +124,8 @@
        SipURI requestLine = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
        //via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
        // ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
        ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(device.getHost().getIp(), device.getHost().getPort(), device.getTransport(), viaTag);
        viaHeader.setRPort();
        viaHeaders.add(viaHeader);
        //from
@@ -151,6 +154,7 @@
        request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
        
        Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
        // Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort()));
        request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress));
        
        ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -7,10 +7,13 @@
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.TransactionDoesNotExistException;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.conf.SipConfig;
@@ -21,9 +24,12 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**    
 * @Description:设备能力接口,用于定义设备的控制、查询能力   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ9:22:48     
 */
@Component
@@ -94,6 +100,49 @@
        return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
    }
  
   /**
    * äº‘台指令码计算
    *
    * @param leftRight  é•œå¤´å·¦ç§»å³ç§» 0:停止 1:左移 2:右移
    * @param upDown     é•œå¤´ä¸Šç§»ä¸‹ç§» 0:停止 1:上移 2:下移
    * @param inOut      é•œå¤´æ”¾å¤§ç¼©å° 0:停止 1:缩小 2:放大
    * @param moveSpeed  é•œå¤´ç§»åŠ¨é€Ÿåº¦ é»˜è®¤ 0XFF (0-255)
    * @param zoomSpeed  é•œå¤´ç¼©æ”¾é€Ÿåº¦ é»˜è®¤ 0X1 (0-255)
    */
    public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) {
        int cmdCode = 0;
        if (leftRight == 2) {
            cmdCode|=0x01;        // å³ç§»
        } else if(leftRight == 1) {
            cmdCode|=0x02;        // å·¦ç§»
        }
        if (upDown == 2) {
            cmdCode|=0x04;        // ä¸‹ç§»
        } else if(upDown == 1) {
            cmdCode|=0x08;        // ä¸Šç§»
        }
        if (inOut == 2) {
            cmdCode |= 0x10;    // æ”¾å¤§
        } else if(inOut == 1) {
            cmdCode |= 0x20;    // ç¼©å°
        }
        StringBuilder builder = new StringBuilder("A50F01");
        String strTmp;
        strTmp = String.format("%02X", cmdCode);
        builder.append(strTmp, 0, 2);
        strTmp = String.format("%02X", moveSpeed);
        builder.append(strTmp, 0, 2);
        builder.append(strTmp, 0, 2);
        strTmp = String.format("%X", zoomSpeed);
        builder.append(strTmp, 0, 1).append("0");
        //计算校验码
        int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100;
        strTmp = String.format("%02X", checkCode);
        builder.append(strTmp, 0, 2);
        return builder.toString();
}
    /**
     * äº‘台控制,支持方向与缩放控制
     * 
@@ -109,13 +158,14 @@
    public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
            int zoomSpeed) {
        try {
            String cmdStr= cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed);
            StringBuffer ptzXml = new StringBuffer(200);
            ptzXml.append("<?xml version=\"1.0\" ?>");
            ptzXml.append("<Control>");
            ptzXml.append("<CmdType>DeviceControl</CmdType>");
            ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>");
            ptzXml.append("<DeviceID>" + channelId + "</DeviceID>");
            ptzXml.append("<PTZCmd>" + "</PTZCmd>");
            ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>");
            ptzXml.append("<Info>");
            ptzXml.append("</Info>");
            ptzXml.append("</Control>");
@@ -123,7 +173,6 @@
            Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
            
            transmitRequest(device, request);
            return true;
        } catch (SipException | ParseException | InvalidArgumentException e) {
            e.printStackTrace();
@@ -245,6 +294,13 @@
                return;
            }
            Request byeRequest = dialog.createRequest(Request.BYE);
            SipURI byeURI = (SipURI) byeRequest.getRequestURI();
            String vh = transaction.getRequest().getHeader(ViaHeader.NAME).toString();
            Pattern p = Pattern.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+)\\:(\\d+)");
            Matcher matcher = p.matcher(vh);
            if (matcher.find()) {
                byeURI.setHost(matcher.group(1));
            }
            ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
            String protocol = viaHeader.getTransport().toUpperCase();
            ClientTransaction clientTransaction = null;
@@ -258,6 +314,8 @@
            e.printStackTrace();
        } catch (SipException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/ISIPRequestProcessor.java
@@ -6,7 +6,7 @@
/**    
 * @Description:处理接收IPCamera发来的SIP协议请求消息
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ4:42:22     
 */
public interface ISIPRequestProcessor {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
@@ -16,7 +16,7 @@
/**    
 * @Description:ACK请求处理器  
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:31:45     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description: BYE请求处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:05     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/CancelRequestProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description:CANCEL请求处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:23     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description:处理INVITE请求
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ4:43:52     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -43,7 +43,7 @@
/**    
 * @Description:MESSAGE请求处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:41     
 */
@Component
@@ -100,6 +100,7 @@
        
        Request request = evt.getRequest();
        SAXReader reader = new SAXReader();
        reader.setEncoding("gbk");
        Document xml;
        try {
            xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
@@ -375,7 +376,7 @@
    private Element getRootElement(RequestEvent evt) throws DocumentException {
        Request request = evt.getRequest();
        SAXReader reader = new SAXReader();
        reader.setEncoding("GB2312");
        reader.setEncoding("gbk");
        Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
        return xml.getRootElement();
    }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description:暂不支持的消息请求处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:59     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
@@ -38,7 +38,7 @@
/**    
 * @Description:收到注册请求 å¤„理 
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ4:47:25     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/SubscribeRequestProcessor.java
@@ -17,7 +17,7 @@
/**    
 * @Description:SUBSCRIBE请求处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:31:20     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java
@@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.response;
import java.text.ParseException;
import javax.sip.ResponseEvent;
import com.genersoft.iot.vmp.conf.SipConfig;
@@ -7,11 +9,11 @@
/**    
 * @Description:处理接收IPCamera发来的SIP协议响应消息
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ4:42:22     
 */
public interface ISIPResponseProcessor {
    public void process(ResponseEvent evt, SipLayer layer, SipConfig config);
    public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException;
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/ByeResponseProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description: BYE请求响应器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:05     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/CancelResponseProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description:CANCEL响应处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:23     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
@@ -2,7 +2,6 @@
import java.text.ParseException;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
@@ -22,57 +21,76 @@
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
/**
 * @Description:处理INVITE响应
 * @author: swwheihei
 * @date:   2020å¹´5月3日 ä¸‹åˆ4:43:52
/**
 * @Description:处理INVITE响应
 * @author: songww
 * @date: 2020å¹´5月3日 ä¸‹åˆ4:43:52
 */
@Component
public class InviteResponseProcessor implements ISIPResponseProcessor {
    private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
    /**
     * å¤„理invite响应
     * 
     * @param evt
     *            å“åº”消息
     */
     * @param evt å“åº”消息
     * @throws ParseException
     */
    @Override
    public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
    public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException {
        try {
            Response response = evt.getResponse();
            int statusCode = response.getStatusCode();
            //trying不会回复
            if(statusCode == Response.TRYING){
            // trying不会回复
            if (statusCode == Response.TRYING) {
            }
            //成功响应
            //下发ack
            if(statusCode == Response.OK){
//                ClientTransaction clientTransaction = evt.getClientTransaction();
//                if(clientTransaction == null){
//                    logger.error("回复ACK时,clientTransaction为null >>> {}",response);
//                    return;
//                }
//                Dialog clientDialog = clientTransaction.getDialog();
//
//                CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
//                long cseqId = clientCSeqHeader.getSeqNumber();
//                /*
//                createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
//                æœ‰çš„终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
//                æ‰€ä»¥åœ¨æ­¤å¤„统一替换地址。和响应消息的Via头中的地址保持一致。
//                 */
//                Request ackRequest = clientDialog.createAck(cseqId);
//                SipURI requestURI = (SipURI) ackRequest.getRequestURI();
//                ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
//                requestURI.setHost(viaHeader.getHost());
//                requestURI.setPort(viaHeader.getPort());
//                clientDialog.sendAck(ackRequest);
            // æˆåŠŸå“åº”
            // ä¸‹å‘ack
            if (statusCode == Response.OK) {
                // ClientTransaction clientTransaction = evt.getClientTransaction();
                // if(clientTransaction == null){
                // logger.error("回复ACK时,clientTransaction为null >>> {}",response);
                // return;
                // }
                // Dialog clientDialog = clientTransaction.getDialog();
                // CSeqHeader clientCSeqHeader = (CSeqHeader)
                // response.getHeader(CSeqHeader.NAME);
                // long cseqId = clientCSeqHeader.getSeqNumber();
                // /*
                // createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
                // æœ‰çš„终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
                // æ‰€ä»¥åœ¨æ­¤å¤„统一替换地址。和响应消息的Via头中的地址保持一致。
                // */
                // Request ackRequest = clientDialog.createAck(cseqId);
                // SipURI requestURI = (SipURI) ackRequest.getRequestURI();
                // ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
                // try {
                // requestURI.setHost(viaHeader.getHost());
                // } catch (Exception e) {
                // e.printStackTrace();
                // }
                // requestURI.setPort(viaHeader.getPort());
                // clientDialog.sendAck(ackRequest);
                Dialog dialog = evt.getDialog();
                Request reqAck =dialog.createAck(1L);
                CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
                Request reqAck = dialog.createAck(cseq.getSeqNumber());
                SipURI requestURI = (SipURI) reqAck.getRequestURI();
                ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
                // String viaHost =viaHeader.getHost();
                //getHost()函数取回的IP地址是“[xxx.xxx.xxx.xxx:yyyy]”的格式,需用正则表达式截取为“xxx.xxx.xxx.xxx"格式
                // Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+");
                // Matcher matcher = p.matcher(viaHeader.getHost());
                // if (matcher.find()) {
                //     requestURI.setHost(matcher.group());
                // }
                requestURI.setHost(viaHeader.getHost());
                requestURI.setPort(viaHeader.getPort());
                reqAck.setRequestURI(requestURI);
                dialog.sendAck(reqAck);
            }
        } catch (InvalidArgumentException | SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/OtherResponseProcessor.java
@@ -10,7 +10,7 @@
/**    
 * @Description:暂不支持的消息响应处理器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月3日 ä¸‹åˆ5:32:59     
 */
@Component
src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java
@@ -7,7 +7,7 @@
/**    
 * @Description:时间工具类,主要处理ISO 8601格式转换
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸‹åˆ3:24:42     
 */
public class DateUtil {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -18,11 +18,11 @@
/**    
 * @Description:针对 ZLMediaServer的hook事件监听
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月8日 ä¸Šåˆ10:46:48     
 */
@RestController
@RequestMapping("/hook/zlm")
@RequestMapping("/index/hook")
public class ZLMHttpHookListener {
    private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -6,7 +6,7 @@
/**    
 * @Description:视频设备数据存储接口
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ2:14:31     
 */
public interface IVideoManagerStorager {
src/main/java/com/genersoft/iot/vmp/storager/VideoManagerStoragerFactory.java
@@ -8,7 +8,7 @@
/**    
 * @Description:视频设备数据存储工厂,根据存储策略,返回对应的存储器
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ2:15:16     
 */
@Component
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
@@ -11,7 +11,7 @@
/**    
 * @Description:视频设备数据存储-jdbc实现  
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ2:28:12     
 */
@Component("jdbcStorager")
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
@@ -13,7 +13,7 @@
/**    
 * @Description:视频设备数据存储-redis实现  
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ2:31:42     
 */
@Component("redisStorager")
src/main/java/com/genersoft/iot/vmp/utils/SpringBeanFactory.java
@@ -7,7 +7,7 @@
/**    
 * @Description:spring bean获取工厂,获取spring中的已初始化的bean
 * @author: swwheihei
 * @author: songww
 * @date:   2019å¹´6月25日 ä¸‹åˆ4:51:52   
 * 
 */
src/main/java/com/genersoft/iot/vmp/utils/redis/FastJsonRedisSerializer.java
@@ -10,7 +10,7 @@
/**    
 * @Description:使用fastjson实现redis的序列化   
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ8:40:11     
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
@@ -13,7 +13,7 @@
/**    
 * @Description:Redis工具类
 * @author: swwheihei
 * @author: songww
 * @date:   2020å¹´5月6日 ä¸‹åˆ8:27:29     
 */
@Component
src/main/resources/application.yml
@@ -26,7 +26,8 @@
server:
    port: 8080
sip:
    ip: 10.200.64.63
#   ip: 10.200.64.63
    ip: 192.168.0.102
    port: 5060
    # æ ¹æ®å›½æ ‡6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
    # åŽä¸¤ä½ä¸ºè¡Œä¸šç¼–码,定义参照附录D.3
@@ -34,7 +35,8 @@
    domain: 3701020049
    id: 37010200492000000001
    # é»˜è®¤è®¾å¤‡è®¤è¯å¯†ç ï¼ŒåŽç»­æ‰©å±•使用设备单独密码
    password: admin
    password: admin123
media:
    ip: 10.200.64.88
#   ip: 10.200.64.88
    ip: 192.168.0.102
    port: 10000
wikis/images/ºËÐÄÁ÷³Ì.png