Commit 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
Showing
49 changed files
with
461 additions
and
343 deletions
LICENSE
0 → 100644
| 1 | +MIT License | ||
| 2 | + | ||
| 3 | +Copyright (c) 2020 swwhaha | ||
| 4 | + | ||
| 5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | +of this software and associated documentation files (the "Software"), to deal | ||
| 7 | +in the Software without restriction, including without limitation the rights | ||
| 8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | +copies of the Software, and to permit persons to whom the Software is | ||
| 10 | +furnished to do so, subject to the following conditions: | ||
| 11 | + | ||
| 12 | +The above copyright notice and this permission notice shall be included in all | ||
| 13 | +copies or substantial portions of the Software. | ||
| 14 | + | ||
| 15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | +SOFTWARE. |
pom.xml
| @@ -39,7 +39,7 @@ | @@ -39,7 +39,7 @@ | ||
| 39 | </dependency> | 39 | </dependency> |
| 40 | <dependency> | 40 | <dependency> |
| 41 | <groupId>org.springframework.boot</groupId> | 41 | <groupId>org.springframework.boot</groupId> |
| 42 | - <artifactId>spring-boot-starter-undertow</artifactId> | 42 | + <artifactId>spring-boot-starter-tomcat</artifactId> |
| 43 | </dependency> | 43 | </dependency> |
| 44 | <dependency> | 44 | <dependency> |
| 45 | <groupId>org.springframework.boot</groupId> | 45 | <groupId>org.springframework.boot</groupId> |
| @@ -127,7 +127,7 @@ | @@ -127,7 +127,7 @@ | ||
| 127 | <dependency> | 127 | <dependency> |
| 128 | <groupId>org.dom4j</groupId> | 128 | <groupId>org.dom4j</groupId> |
| 129 | <artifactId>dom4j</artifactId> | 129 | <artifactId>dom4j</artifactId> |
| 130 | - <version>2.1.1</version> | 130 | + <version>2.1.3</version> |
| 131 | </dependency> | 131 | </dependency> |
| 132 | <dependency> | 132 | <dependency> |
| 133 | <groupId>com.google.code.gson</groupId> | 133 | <groupId>com.google.code.gson</groupId> |
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
| @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.common; | @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.common; | ||
| 2 | 2 | ||
| 3 | /** | 3 | /** |
| 4 | * @Description:TODO(这里用一句话描述这个类的作用) | 4 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 5 | - * @author: swwheihei | 5 | + * @author: songww |
| 6 | * @date: 2019年5月30日 下午3:04:04 | 6 | * @date: 2019年5月30日 下午3:04:04 |
| 7 | * | 7 | * |
| 8 | */ | 8 | */ |
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
| @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; | @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; | ||
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置 | 15 | * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置 |
| 16 | - * @author: swwheihei | 16 | + * @author: songww |
| 17 | * @date: 2019年5月30日 上午10:58:25 | 17 | * @date: 2019年5月30日 上午10:58:25 |
| 18 | * | 18 | * |
| 19 | */ | 19 | */ |
src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java
| @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration; | @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration; | ||
| 5 | 5 | ||
| 6 | /** | 6 | /** |
| 7 | * @Description:TODO(这里用一句话描述这个类的作用) | 7 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 8 | - * @author: swwheihei | 8 | + * @author: songww |
| 9 | * @date: 2020年5月6日 下午2:46:00 | 9 | * @date: 2020年5月6日 下午2:46:00 |
| 10 | */ | 10 | */ |
| 11 | @Configuration("vmConfig") | 11 | @Configuration("vmConfig") |
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
| 1 | -package com.genersoft.iot.vmp.gb28181; | ||
| 2 | - | ||
| 3 | -import java.util.Properties; | ||
| 4 | - | ||
| 5 | -import javax.annotation.PostConstruct; | ||
| 6 | -import javax.sip.DialogTerminatedEvent; | ||
| 7 | -import javax.sip.IOExceptionEvent; | ||
| 8 | -import javax.sip.ListeningPoint; | ||
| 9 | -import javax.sip.RequestEvent; | ||
| 10 | -import javax.sip.ResponseEvent; | ||
| 11 | -import javax.sip.ServerTransaction; | ||
| 12 | -import javax.sip.SipFactory; | ||
| 13 | -import javax.sip.SipListener; | ||
| 14 | -import javax.sip.SipProvider; | ||
| 15 | -import javax.sip.SipStack; | ||
| 16 | -import javax.sip.TimeoutEvent; | ||
| 17 | -import javax.sip.TransactionAlreadyExistsException; | ||
| 18 | -import javax.sip.TransactionTerminatedEvent; | ||
| 19 | -import javax.sip.TransactionUnavailableException; | ||
| 20 | -import javax.sip.address.AddressFactory; | ||
| 21 | -import javax.sip.header.HeaderFactory; | ||
| 22 | -import javax.sip.header.ViaHeader; | ||
| 23 | -import javax.sip.message.MessageFactory; | ||
| 24 | -import javax.sip.message.Request; | ||
| 25 | -import javax.sip.message.Response; | ||
| 26 | - | ||
| 27 | -import org.slf4j.Logger; | ||
| 28 | -import org.slf4j.LoggerFactory; | ||
| 29 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 30 | -import org.springframework.stereotype.Component; | ||
| 31 | - | ||
| 32 | -import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 33 | -import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; | ||
| 34 | -import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 35 | -import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | ||
| 36 | - | ||
| 37 | -import gov.nist.javax.sip.SipStackImpl; | ||
| 38 | - | ||
| 39 | -@Component | ||
| 40 | -public class SipLayer implements SipListener, Runnable { | ||
| 41 | - | ||
| 42 | - private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); | ||
| 43 | - | ||
| 44 | - @Autowired | ||
| 45 | - private SipConfig sipConfig; | ||
| 46 | - | ||
| 47 | - private SipProvider tcpSipProvider; | ||
| 48 | - | ||
| 49 | - private SipProvider udpSipProvider; | ||
| 50 | - | ||
| 51 | - @Autowired | ||
| 52 | - private SIPProcessorFactory processorFactory; | ||
| 53 | - | ||
| 54 | - private SipStack sipStack; | ||
| 55 | - | ||
| 56 | - private AddressFactory addressFactory; | ||
| 57 | - private HeaderFactory headerFactory; | ||
| 58 | - private MessageFactory messageFactory; | ||
| 59 | - | ||
| 60 | - @PostConstruct | ||
| 61 | - private void initSipServer() { | ||
| 62 | - Thread thread=new Thread(this); | ||
| 63 | - thread.setDaemon(true); | ||
| 64 | - thread.setName("sip server thread start"); | ||
| 65 | - thread.start(); | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - @Override | ||
| 69 | - public void run() { | ||
| 70 | - SipFactory sipFactory = SipFactory.getInstance(); | ||
| 71 | - sipFactory.setPathName("gov.nist"); | ||
| 72 | - try { | ||
| 73 | - headerFactory = sipFactory.createHeaderFactory(); | ||
| 74 | - | ||
| 75 | - addressFactory = sipFactory.createAddressFactory(); | ||
| 76 | - messageFactory = sipFactory.createMessageFactory(); | ||
| 77 | - | ||
| 78 | - Properties properties = new Properties(); | ||
| 79 | - properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); | ||
| 80 | - properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getSipIp()); | ||
| 81 | - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); | ||
| 82 | - /** | ||
| 83 | - * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = | ||
| 84 | - * 0; public static final int TRACE_MESSAGES = 16; public static final int | ||
| 85 | - * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32; | ||
| 86 | - */ | ||
| 87 | - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); | ||
| 88 | - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log"); | ||
| 89 | - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log"); | ||
| 90 | - sipStack = (SipStackImpl) sipFactory.createSipStack(properties); | ||
| 91 | - | ||
| 92 | - startTcpListener(); | ||
| 93 | - startUdpListener(); | ||
| 94 | - } catch (Exception e) { | ||
| 95 | - logger.error("Sip Server 启动失败! port {" + sipConfig.getSipPort() + "}"); | ||
| 96 | - e.printStackTrace(); | ||
| 97 | - } | ||
| 98 | - logger.info("Sip Server 启动成功 port {" + sipConfig.getSipPort() + "}"); | ||
| 99 | - } | ||
| 100 | - | ||
| 101 | - private void startTcpListener() throws Exception { | ||
| 102 | - ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(), "TCP"); | ||
| 103 | - tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint); | ||
| 104 | - tcpSipProvider.addSipListener(this); | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - private void startUdpListener() throws Exception { | ||
| 108 | - ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(), "UDP"); | ||
| 109 | - udpSipProvider = sipStack.createSipProvider(udpListeningPoint); | ||
| 110 | - udpSipProvider.addSipListener(this); | ||
| 111 | - } | ||
| 112 | - | ||
| 113 | - /** | ||
| 114 | - * SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a | ||
| 115 | - * new request arrives. | ||
| 116 | - */ | ||
| 117 | - @Override | ||
| 118 | - public void processRequest(RequestEvent evt) { | ||
| 119 | - ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt); | ||
| 120 | - processor.process(evt, this); | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - @Override | ||
| 124 | - public void processResponse(ResponseEvent evt) { | ||
| 125 | - Response response = evt.getResponse(); | ||
| 126 | - int status = response.getStatusCode(); | ||
| 127 | - if ((status >= 200) && (status < 300)) { // Success! | ||
| 128 | - ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); | ||
| 129 | - processor.process(evt, this, sipConfig); | ||
| 130 | - } else { | ||
| 131 | - logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getContent().toString()); | ||
| 132 | - } | ||
| 133 | - // trying不会回复 | ||
| 134 | - if (status == Response.TRYING) { | ||
| 135 | - | ||
| 136 | - } | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - /** | ||
| 140 | - * <p> | ||
| 141 | - * Title: processTimeout | ||
| 142 | - * </p> | ||
| 143 | - * <p> | ||
| 144 | - * Description: | ||
| 145 | - * </p> | ||
| 146 | - * | ||
| 147 | - * @param timeoutEvent | ||
| 148 | - */ | ||
| 149 | - @Override | ||
| 150 | - public void processTimeout(TimeoutEvent timeoutEvent) { | ||
| 151 | - // TODO Auto-generated method stub | ||
| 152 | - | ||
| 153 | - } | ||
| 154 | - | ||
| 155 | - /** | ||
| 156 | - * <p> | ||
| 157 | - * Title: processIOException | ||
| 158 | - * </p> | ||
| 159 | - * <p> | ||
| 160 | - * Description: | ||
| 161 | - * </p> | ||
| 162 | - * | ||
| 163 | - * @param exceptionEvent | ||
| 164 | - */ | ||
| 165 | - @Override | ||
| 166 | - public void processIOException(IOExceptionEvent exceptionEvent) { | ||
| 167 | - // TODO Auto-generated method stub | ||
| 168 | - | ||
| 169 | - } | ||
| 170 | - | ||
| 171 | - /** | ||
| 172 | - * <p> | ||
| 173 | - * Title: processTransactionTerminated | ||
| 174 | - * </p> | ||
| 175 | - * <p> | ||
| 176 | - * Description: | ||
| 177 | - * </p> | ||
| 178 | - * | ||
| 179 | - * @param transactionTerminatedEvent | ||
| 180 | - */ | ||
| 181 | - @Override | ||
| 182 | - public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { | ||
| 183 | - // TODO Auto-generated method stub | ||
| 184 | - | ||
| 185 | - } | ||
| 186 | - | ||
| 187 | - /** | ||
| 188 | - * <p> | ||
| 189 | - * Title: processDialogTerminated | ||
| 190 | - * </p> | ||
| 191 | - * <p> | ||
| 192 | - * Description: | ||
| 193 | - * </p> | ||
| 194 | - * | ||
| 195 | - * @param dialogTerminatedEvent | ||
| 196 | - */ | ||
| 197 | - @Override | ||
| 198 | - public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { | ||
| 199 | - // TODO Auto-generated method stub | ||
| 200 | - | ||
| 201 | - } | ||
| 202 | - | ||
| 203 | - public ServerTransaction getServerTransaction(RequestEvent evt) { | ||
| 204 | - Request request = evt.getRequest(); | ||
| 205 | - ServerTransaction serverTransaction = evt.getServerTransaction(); | ||
| 206 | - // 判断TCP还是UDP | ||
| 207 | - boolean isTcp = false; | ||
| 208 | - ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 209 | - String transport = reqViaHeader.getTransport(); | ||
| 210 | - if (transport.equals("TCP")) { | ||
| 211 | - isTcp = true; | ||
| 212 | - } | ||
| 213 | - | ||
| 214 | - if (serverTransaction == null) { | ||
| 215 | - try { | ||
| 216 | - if (isTcp) { | ||
| 217 | - serverTransaction = tcpSipProvider.getNewServerTransaction(request); | ||
| 218 | - } else { | ||
| 219 | - serverTransaction = udpSipProvider.getNewServerTransaction(request); | ||
| 220 | - } | ||
| 221 | - } catch (TransactionAlreadyExistsException e) { | ||
| 222 | - e.printStackTrace(); | ||
| 223 | - } catch (TransactionUnavailableException e) { | ||
| 224 | - e.printStackTrace(); | ||
| 225 | - } | ||
| 226 | - } | ||
| 227 | - return serverTransaction; | ||
| 228 | - } | ||
| 229 | - | ||
| 230 | - public AddressFactory getAddressFactory() { | ||
| 231 | - return addressFactory; | ||
| 232 | - } | ||
| 233 | - | ||
| 234 | - public HeaderFactory getHeaderFactory() { | ||
| 235 | - return headerFactory; | ||
| 236 | - } | ||
| 237 | - | ||
| 238 | - public MessageFactory getMessageFactory() { | ||
| 239 | - return messageFactory; | ||
| 240 | - } | ||
| 241 | - | ||
| 242 | - public SipProvider getTcpSipProvider() { | ||
| 243 | - return tcpSipProvider; | ||
| 244 | - } | ||
| 245 | - | ||
| 246 | - public SipProvider getUdpSipProvider() { | ||
| 247 | - return udpSipProvider; | ||
| 248 | - } | ||
| 249 | - | ||
| 250 | -} | 1 | +package com.genersoft.iot.vmp.gb28181; |
| 2 | + | ||
| 3 | +import java.text.ParseException; | ||
| 4 | +import java.util.Properties; | ||
| 5 | + | ||
| 6 | +import javax.annotation.PostConstruct; | ||
| 7 | +import javax.sip.DialogTerminatedEvent; | ||
| 8 | +import javax.sip.IOExceptionEvent; | ||
| 9 | +import javax.sip.ListeningPoint; | ||
| 10 | +import javax.sip.RequestEvent; | ||
| 11 | +import javax.sip.ResponseEvent; | ||
| 12 | +import javax.sip.ServerTransaction; | ||
| 13 | +import javax.sip.SipFactory; | ||
| 14 | +import javax.sip.SipListener; | ||
| 15 | +import javax.sip.SipProvider; | ||
| 16 | +import javax.sip.SipStack; | ||
| 17 | +import javax.sip.TimeoutEvent; | ||
| 18 | +import javax.sip.TransactionAlreadyExistsException; | ||
| 19 | +import javax.sip.TransactionTerminatedEvent; | ||
| 20 | +import javax.sip.TransactionUnavailableException; | ||
| 21 | +import javax.sip.address.AddressFactory; | ||
| 22 | +import javax.sip.header.HeaderFactory; | ||
| 23 | +import javax.sip.header.ViaHeader; | ||
| 24 | +import javax.sip.message.MessageFactory; | ||
| 25 | +import javax.sip.message.Request; | ||
| 26 | +import javax.sip.message.Response; | ||
| 27 | + | ||
| 28 | +import org.slf4j.Logger; | ||
| 29 | +import org.slf4j.LoggerFactory; | ||
| 30 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 31 | +import org.springframework.stereotype.Component; | ||
| 32 | + | ||
| 33 | +import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 34 | +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; | ||
| 35 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 36 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | ||
| 37 | + | ||
| 38 | +import gov.nist.javax.sip.SipStackImpl; | ||
| 39 | + | ||
| 40 | +@Component | ||
| 41 | +public class SipLayer implements SipListener, Runnable { | ||
| 42 | + | ||
| 43 | + private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); | ||
| 44 | + | ||
| 45 | + @Autowired | ||
| 46 | + private SipConfig sipConfig; | ||
| 47 | + | ||
| 48 | + private SipProvider tcpSipProvider; | ||
| 49 | + | ||
| 50 | + private SipProvider udpSipProvider; | ||
| 51 | + | ||
| 52 | + @Autowired | ||
| 53 | + private SIPProcessorFactory processorFactory; | ||
| 54 | + | ||
| 55 | + private SipStack sipStack; | ||
| 56 | + | ||
| 57 | + private AddressFactory addressFactory; | ||
| 58 | + private HeaderFactory headerFactory; | ||
| 59 | + private MessageFactory messageFactory; | ||
| 60 | + | ||
| 61 | + @PostConstruct | ||
| 62 | + private void initSipServer() { | ||
| 63 | + Thread thread = new Thread(this); | ||
| 64 | + thread.setDaemon(true); | ||
| 65 | + thread.setName("sip server thread start"); | ||
| 66 | + thread.start(); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + public void run() { | ||
| 71 | + SipFactory sipFactory = SipFactory.getInstance(); | ||
| 72 | + sipFactory.setPathName("gov.nist"); | ||
| 73 | + try { | ||
| 74 | + headerFactory = sipFactory.createHeaderFactory(); | ||
| 75 | + | ||
| 76 | + addressFactory = sipFactory.createAddressFactory(); | ||
| 77 | + messageFactory = sipFactory.createMessageFactory(); | ||
| 78 | + | ||
| 79 | + Properties properties = new Properties(); | ||
| 80 | + properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); | ||
| 81 | + properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getSipIp()); | ||
| 82 | + properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); | ||
| 83 | + /** | ||
| 84 | + * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = | ||
| 85 | + * 0; public static final int TRACE_MESSAGES = 16; public static final int | ||
| 86 | + * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32; | ||
| 87 | + */ | ||
| 88 | + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); | ||
| 89 | + properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log"); | ||
| 90 | + properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log"); | ||
| 91 | + sipStack = (SipStackImpl) sipFactory.createSipStack(properties); | ||
| 92 | + | ||
| 93 | + startTcpListener(); | ||
| 94 | + startUdpListener(); | ||
| 95 | + } catch (Exception e) { | ||
| 96 | + logger.error("Sip Server 启动失败! port {" + sipConfig.getSipPort() + "}"); | ||
| 97 | + e.printStackTrace(); | ||
| 98 | + } | ||
| 99 | + logger.info("Sip Server 启动成功 port {" + sipConfig.getSipPort() + "}"); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + private void startTcpListener() throws Exception { | ||
| 103 | + ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(), | ||
| 104 | + "TCP"); | ||
| 105 | + tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint); | ||
| 106 | + tcpSipProvider.addSipListener(this); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + private void startUdpListener() throws Exception { | ||
| 110 | + ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getSipIp(), sipConfig.getSipPort(), | ||
| 111 | + "UDP"); | ||
| 112 | + udpSipProvider = sipStack.createSipProvider(udpListeningPoint); | ||
| 113 | + udpSipProvider.addSipListener(this); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a | ||
| 118 | + * new request arrives. | ||
| 119 | + */ | ||
| 120 | + @Override | ||
| 121 | + public void processRequest(RequestEvent evt) { | ||
| 122 | + ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt); | ||
| 123 | + processor.process(evt, this); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + @Override | ||
| 127 | + public void processResponse(ResponseEvent evt) { | ||
| 128 | + Response response = evt.getResponse(); | ||
| 129 | + int status = response.getStatusCode(); | ||
| 130 | + if ((status >= 200) && (status < 300)) { // Success! | ||
| 131 | + ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); | ||
| 132 | + try { | ||
| 133 | + processor.process(evt, this, sipConfig); | ||
| 134 | + } catch (ParseException e) { | ||
| 135 | + // TODO Auto-generated catch block | ||
| 136 | + e.printStackTrace(); | ||
| 137 | + } | ||
| 138 | + // } else if (status == Response.TRYING) { | ||
| 139 | + // trying不会回复 | ||
| 140 | + } else if ((status >= 100) && (status < 200)) { | ||
| 141 | + // 增加其它无需回复的响应,如101、180等 | ||
| 142 | + } else { | ||
| 143 | + logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); | ||
| 144 | + } | ||
| 145 | + // trying不会回复 | ||
| 146 | + // if (status == Response.TRYING) { | ||
| 147 | + | ||
| 148 | + // } | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + /** | ||
| 152 | + * <p> | ||
| 153 | + * Title: processTimeout | ||
| 154 | + * </p> | ||
| 155 | + * <p> | ||
| 156 | + * Description: | ||
| 157 | + * </p> | ||
| 158 | + * | ||
| 159 | + * @param timeoutEvent | ||
| 160 | + */ | ||
| 161 | + @Override | ||
| 162 | + public void processTimeout(TimeoutEvent timeoutEvent) { | ||
| 163 | + // TODO Auto-generated method stub | ||
| 164 | + | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + /** | ||
| 168 | + * <p> | ||
| 169 | + * Title: processIOException | ||
| 170 | + * </p> | ||
| 171 | + * <p> | ||
| 172 | + * Description: | ||
| 173 | + * </p> | ||
| 174 | + * | ||
| 175 | + * @param exceptionEvent | ||
| 176 | + */ | ||
| 177 | + @Override | ||
| 178 | + public void processIOException(IOExceptionEvent exceptionEvent) { | ||
| 179 | + // TODO Auto-generated method stub | ||
| 180 | + | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + /** | ||
| 184 | + * <p> | ||
| 185 | + * Title: processTransactionTerminated | ||
| 186 | + * </p> | ||
| 187 | + * <p> | ||
| 188 | + * Description: | ||
| 189 | + * </p> | ||
| 190 | + * | ||
| 191 | + * @param transactionTerminatedEvent | ||
| 192 | + */ | ||
| 193 | + @Override | ||
| 194 | + public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { | ||
| 195 | + // TODO Auto-generated method stub | ||
| 196 | + | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * <p> | ||
| 201 | + * Title: processDialogTerminated | ||
| 202 | + * </p> | ||
| 203 | + * <p> | ||
| 204 | + * Description: | ||
| 205 | + * </p> | ||
| 206 | + * | ||
| 207 | + * @param dialogTerminatedEvent | ||
| 208 | + */ | ||
| 209 | + @Override | ||
| 210 | + public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { | ||
| 211 | + // TODO Auto-generated method stub | ||
| 212 | + | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + public ServerTransaction getServerTransaction(RequestEvent evt) { | ||
| 216 | + Request request = evt.getRequest(); | ||
| 217 | + ServerTransaction serverTransaction = evt.getServerTransaction(); | ||
| 218 | + // 判断TCP还是UDP | ||
| 219 | + boolean isTcp = false; | ||
| 220 | + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 221 | + String transport = reqViaHeader.getTransport(); | ||
| 222 | + if (transport.equals("TCP")) { | ||
| 223 | + isTcp = true; | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + if (serverTransaction == null) { | ||
| 227 | + try { | ||
| 228 | + if (isTcp) { | ||
| 229 | + serverTransaction = tcpSipProvider.getNewServerTransaction(request); | ||
| 230 | + } else { | ||
| 231 | + serverTransaction = udpSipProvider.getNewServerTransaction(request); | ||
| 232 | + } | ||
| 233 | + } catch (TransactionAlreadyExistsException e) { | ||
| 234 | + e.printStackTrace(); | ||
| 235 | + } catch (TransactionUnavailableException e) { | ||
| 236 | + e.printStackTrace(); | ||
| 237 | + } | ||
| 238 | + } | ||
| 239 | + return serverTransaction; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + public AddressFactory getAddressFactory() { | ||
| 243 | + return addressFactory; | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + public HeaderFactory getHeaderFactory() { | ||
| 247 | + return headerFactory; | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + public MessageFactory getMessageFactory() { | ||
| 251 | + return messageFactory; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + public SipProvider getTcpSipProvider() { | ||
| 255 | + return tcpSipProvider; | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + public SipProvider getUdpSipProvider() { | ||
| 259 | + return udpSipProvider; | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | +} |
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
| @@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | @@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | * @Description:注册逻辑处理,当设备注册后触发逻辑。 | 10 | * @Description:注册逻辑处理,当设备注册后触发逻辑。 |
| 11 | - * @author: swwheihei | 11 | + * @author: songww |
| 12 | * @date: 2020年5月8日 下午9:41:46 | 12 | * @date: 2020年5月8日 下午9:41:46 |
| 13 | */ | 13 | */ |
| 14 | @Component | 14 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
| @@ -4,7 +4,7 @@ import java.util.List; | @@ -4,7 +4,7 @@ import java.util.List; | ||
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * @Description:设备录像信息bean | 6 | * @Description:设备录像信息bean |
| 7 | - * @author: swwheihei | 7 | + * @author: songww |
| 8 | * @date: 2020年5月8日 下午2:05:56 | 8 | * @date: 2020年5月8日 下午2:05:56 |
| 9 | */ | 9 | */ |
| 10 | public class RecordInfo { | 10 | public class RecordInfo { |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
| @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean; | @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean; | ||
| 2 | 2 | ||
| 3 | /** | 3 | /** |
| 4 | * @Description:设备录像bean | 4 | * @Description:设备录像bean |
| 5 | - * @author: swwheihei | 5 | + * @author: songww |
| 6 | * @date: 2020年5月8日 下午2:06:54 | 6 | * @date: 2020年5月8日 下午2:06:54 |
| 7 | */ | 7 | */ |
| 8 | public class RecordItem { | 8 | public class RecordItem { |
src/main/java/com/genersoft/iot/vmp/gb28181/event/DeviceOffLineDetector.java
| @@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | @@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | * @Description:设备离在线状态检测器,用于检测设备状态 | 10 | * @Description:设备离在线状态检测器,用于检测设备状态 |
| 11 | - * @author: swwheihei | 11 | + * @author: songww |
| 12 | * @date: 2020年5月13日 下午2:40:29 | 12 | * @date: 2020年5月13日 下午2:40:29 |
| 13 | */ | 13 | */ |
| 14 | @Component | 14 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
| @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent; | @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent; | ||
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| 11 | * @Description:Event事件通知推送器,支持推送在线事件、离线事件 | 11 | * @Description:Event事件通知推送器,支持推送在线事件、离线事件 |
| 12 | - * @author: swwheihei | 12 | + * @author: songww |
| 13 | * @date: 2020年5月6日 上午11:30:50 | 13 | * @date: 2020年5月6日 上午11:30:50 |
| 14 | */ | 14 | */ |
| 15 | @Component | 15 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java
| @@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | @@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | ||
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| 13 | * @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 | 13 | * @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 |
| 14 | - * @author: swwheihei | 14 | + * @author: songww |
| 15 | * @date: 2020年5月6日 上午11:35:46 | 15 | * @date: 2020年5月6日 上午11:35:46 |
| 16 | */ | 16 | */ |
| 17 | @Component | 17 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java
| @@ -4,7 +4,7 @@ import org.springframework.context.ApplicationEvent; | @@ -4,7 +4,7 @@ import org.springframework.context.ApplicationEvent; | ||
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * @Description:TODO(这里用一句话描述这个类的作用) | 6 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 7 | - * @author: swwheihei | 7 | + * @author: songww |
| 8 | * @date: 2020年5月6日 上午11:33:13 | 8 | * @date: 2020年5月6日 上午11:33:13 |
| 9 | */ | 9 | */ |
| 10 | public class OfflineEvent extends ApplicationEvent { | 10 | public class OfflineEvent extends ApplicationEvent { |
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java
| @@ -14,7 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | @@ -14,7 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 14 | * @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源: | 14 | * @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源: |
| 15 | * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} | 15 | * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} |
| 16 | * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener} | 16 | * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener} |
| 17 | - * @author: swwheihei | 17 | + * @author: songww |
| 18 | * @date: 2020年5月6日 下午1:51:23 | 18 | * @date: 2020年5月6日 下午1:51:23 |
| 19 | */ | 19 | */ |
| 20 | @Component | 20 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java
| @@ -4,7 +4,7 @@ import org.springframework.context.ApplicationEvent; | @@ -4,7 +4,7 @@ import org.springframework.context.ApplicationEvent; | ||
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * @Description:TODO(这里用一句话描述这个类的作用) | 6 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 7 | - * @author: swwheihei | 7 | + * @author: songww |
| 8 | * @date: 2020年5月6日 上午11:32:56 | 8 | * @date: 2020年5月6日 上午11:32:56 |
| 9 | */ | 9 | */ |
| 10 | public class OnlineEvent extends ApplicationEvent { | 10 | public class OnlineEvent extends ApplicationEvent { |
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
| @@ -14,7 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | @@ -14,7 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 14 | * @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: | 14 | * @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: |
| 15 | * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} | 15 | * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} |
| 16 | * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor} | 16 | * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor} |
| 17 | - * @author: swwheihei | 17 | + * @author: songww |
| 18 | * @date: 2020年5月6日 下午1:51:23 | 18 | * @date: 2020年5月6日 下午1:51:23 |
| 19 | */ | 19 | */ |
| 20 | @Component | 20 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java
| @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.utils.SpringBeanFactory; | @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.utils.SpringBeanFactory; | ||
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| 11 | * @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数 | 11 | * @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数 |
| 12 | - * @author: swwheihei | 12 | + * @author: songww |
| 13 | * @date: 2020年5月10日 上午11:57:57 | 13 | * @date: 2020年5月10日 上午11:57:57 |
| 14 | */ | 14 | */ |
| 15 | public class SsrcUtil { | 15 | public class SsrcUtil { |
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
| @@ -8,7 +8,7 @@ import org.springframework.stereotype.Component; | @@ -8,7 +8,7 @@ import org.springframework.stereotype.Component; | ||
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | * @Description:视频流session管理器,管理视频预览、预览回放的通信句柄 | 10 | * @Description:视频流session管理器,管理视频预览、预览回放的通信句柄 |
| 11 | - * @author: swwheihei | 11 | + * @author: songww |
| 12 | * @date: 2020年5月13日 下午4:03:02 | 12 | * @date: 2020年5月13日 下午4:03:02 |
| 13 | */ | 13 | */ |
| 14 | @Component | 14 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
| @@ -26,7 +26,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcess | @@ -26,7 +26,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcess | ||
| 26 | 26 | ||
| 27 | /** | 27 | /** |
| 28 | * @Description:TODO(这里用一句话描述这个类的作用) | 28 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 29 | - * @author: swwheihei | 29 | + * @author: songww |
| 30 | * @date: 2020年5月3日 下午4:24:37 | 30 | * @date: 2020年5月3日 下午4:24:37 |
| 31 | */ | 31 | */ |
| 32 | @Component | 32 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
| @@ -10,7 +10,7 @@ import org.springframework.web.context.request.async.DeferredResult; | @@ -10,7 +10,7 @@ import org.springframework.web.context.request.async.DeferredResult; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:TODO(这里用一句话描述这个类的作用) | 12 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月8日 下午7:59:05 | 14 | * @date: 2020年5月8日 下午7:59:05 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
| @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback; | @@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback; | ||
| 2 | 2 | ||
| 3 | /** | 3 | /** |
| 4 | * @Description:TODO(这里用一句话描述这个类的作用) | 4 | * @Description:TODO(这里用一句话描述这个类的作用) |
| 5 | - * @author: swwheihei | 5 | + * @author: songww |
| 6 | * @date: 2020年5月8日 下午1:09:18 | 6 | * @date: 2020年5月8日 下午1:09:18 |
| 7 | */ | 7 | */ |
| 8 | public class RequestMessage { | 8 | public class RequestMessage { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| @@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; | @@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * @Description:设备能力接口,用于定义设备的控制、查询能力 | 6 | * @Description:设备能力接口,用于定义设备的控制、查询能力 |
| 7 | - * @author: swwheihei | 7 | + * @author: songww |
| 8 | * @date: 2020年5月3日 下午9:16:34 | 8 | * @date: 2020年5月3日 下午9:16:34 |
| 9 | */ | 9 | */ |
| 10 | public interface ISIPCommander { | 10 | public interface ISIPCommander { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| @@ -25,7 +25,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Host; | @@ -25,7 +25,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Host; | ||
| 25 | 25 | ||
| 26 | /** | 26 | /** |
| 27 | * @Description:摄像头命令request创造器 TODO 冗余代码太多待优化 | 27 | * @Description:摄像头命令request创造器 TODO 冗余代码太多待优化 |
| 28 | - * @author: swwheihei | 28 | + * @author: songww |
| 29 | * @date: 2020年5月6日 上午9:29:02 | 29 | * @date: 2020年5月6日 上午9:29:02 |
| 30 | */ | 30 | */ |
| 31 | @Component | 31 | @Component |
| @@ -79,7 +79,8 @@ public class SIPRequestHeaderProvider { | @@ -79,7 +79,8 @@ public class SIPRequestHeaderProvider { | ||
| 79 | SipURI requestLine = layer.getAddressFactory().createSipURI(channelId, host.getAddress()); | 79 | SipURI requestLine = layer.getAddressFactory().createSipURI(channelId, host.getAddress()); |
| 80 | //via | 80 | //via |
| 81 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 81 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 82 | - ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag); | 82 | + // ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag); |
| 83 | + ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(device.getHost().getIp(), device.getHost().getPort(), device.getTransport(), viaTag); | ||
| 83 | viaHeader.setRPort(); | 84 | viaHeader.setRPort(); |
| 84 | viaHeaders.add(viaHeader); | 85 | viaHeaders.add(viaHeader); |
| 85 | //from | 86 | //from |
| @@ -108,6 +109,7 @@ public class SIPRequestHeaderProvider { | @@ -108,6 +109,7 @@ public class SIPRequestHeaderProvider { | ||
| 108 | request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 109 | request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); |
| 109 | 110 | ||
| 110 | Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); | 111 | Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); |
| 112 | + // Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort())); | ||
| 111 | request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress)); | 113 | request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress)); |
| 112 | 114 | ||
| 113 | ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP"); | 115 | ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP"); |
| @@ -122,7 +124,8 @@ public class SIPRequestHeaderProvider { | @@ -122,7 +124,8 @@ public class SIPRequestHeaderProvider { | ||
| 122 | SipURI requestLine = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress()); | 124 | SipURI requestLine = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress()); |
| 123 | //via | 125 | //via |
| 124 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 126 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 125 | - ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag); | 127 | + // ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag); |
| 128 | + ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(device.getHost().getIp(), device.getHost().getPort(), device.getTransport(), viaTag); | ||
| 126 | viaHeader.setRPort(); | 129 | viaHeader.setRPort(); |
| 127 | viaHeaders.add(viaHeader); | 130 | viaHeaders.add(viaHeader); |
| 128 | //from | 131 | //from |
| @@ -151,6 +154,7 @@ public class SIPRequestHeaderProvider { | @@ -151,6 +154,7 @@ public class SIPRequestHeaderProvider { | ||
| 151 | request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | 154 | request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); |
| 152 | 155 | ||
| 153 | Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); | 156 | Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); |
| 157 | + // Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort())); | ||
| 154 | request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress)); | 158 | request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress)); |
| 155 | 159 | ||
| 156 | ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP"); | 160 | 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.Dialog; | @@ -7,10 +7,13 @@ import javax.sip.Dialog; | ||
| 7 | import javax.sip.InvalidArgumentException; | 7 | import javax.sip.InvalidArgumentException; |
| 8 | import javax.sip.SipException; | 8 | import javax.sip.SipException; |
| 9 | import javax.sip.TransactionDoesNotExistException; | 9 | import javax.sip.TransactionDoesNotExistException; |
| 10 | +import javax.sip.address.Address; | ||
| 11 | +import javax.sip.address.SipURI; | ||
| 10 | import javax.sip.header.ViaHeader; | 12 | import javax.sip.header.ViaHeader; |
| 11 | import javax.sip.message.Request; | 13 | import javax.sip.message.Request; |
| 12 | 14 | ||
| 13 | import org.springframework.beans.factory.annotation.Autowired; | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 16 | +import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers; | ||
| 14 | import org.springframework.stereotype.Component; | 17 | import org.springframework.stereotype.Component; |
| 15 | 18 | ||
| 16 | import com.genersoft.iot.vmp.conf.SipConfig; | 19 | import com.genersoft.iot.vmp.conf.SipConfig; |
| @@ -21,9 +24,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | @@ -21,9 +24,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | ||
| 21 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; | 24 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; |
| 22 | import com.genersoft.iot.vmp.gb28181.utils.DateUtil; | 25 | import com.genersoft.iot.vmp.gb28181.utils.DateUtil; |
| 23 | 26 | ||
| 27 | +import java.util.regex.Pattern; | ||
| 28 | +import java.util.regex.Matcher; | ||
| 29 | + | ||
| 24 | /** | 30 | /** |
| 25 | * @Description:设备能力接口,用于定义设备的控制、查询能力 | 31 | * @Description:设备能力接口,用于定义设备的控制、查询能力 |
| 26 | - * @author: swwheihei | 32 | + * @author: songww |
| 27 | * @date: 2020年5月3日 下午9:22:48 | 33 | * @date: 2020年5月3日 下午9:22:48 |
| 28 | */ | 34 | */ |
| 29 | @Component | 35 | @Component |
| @@ -94,6 +100,49 @@ public class SIPCommander implements ISIPCommander { | @@ -94,6 +100,49 @@ public class SIPCommander implements ISIPCommander { | ||
| 94 | return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed); | 100 | return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed); |
| 95 | } | 101 | } |
| 96 | 102 | ||
| 103 | + /** | ||
| 104 | + * 云台指令码计算 | ||
| 105 | + * | ||
| 106 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | ||
| 107 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | ||
| 108 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | ||
| 109 | + * @param moveSpeed 镜头移动速度 默认 0XFF (0-255) | ||
| 110 | + * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255) | ||
| 111 | + */ | ||
| 112 | + public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) { | ||
| 113 | + int cmdCode = 0; | ||
| 114 | + if (leftRight == 2) { | ||
| 115 | + cmdCode|=0x01; // 右移 | ||
| 116 | + } else if(leftRight == 1) { | ||
| 117 | + cmdCode|=0x02; // 左移 | ||
| 118 | + } | ||
| 119 | + if (upDown == 2) { | ||
| 120 | + cmdCode|=0x04; // 下移 | ||
| 121 | + } else if(upDown == 1) { | ||
| 122 | + cmdCode|=0x08; // 上移 | ||
| 123 | + } | ||
| 124 | + if (inOut == 2) { | ||
| 125 | + cmdCode |= 0x10; // 放大 | ||
| 126 | + } else if(inOut == 1) { | ||
| 127 | + cmdCode |= 0x20; // 缩小 | ||
| 128 | + } | ||
| 129 | + StringBuilder builder = new StringBuilder("A50F01"); | ||
| 130 | + String strTmp; | ||
| 131 | + strTmp = String.format("%02X", cmdCode); | ||
| 132 | + builder.append(strTmp, 0, 2); | ||
| 133 | + strTmp = String.format("%02X", moveSpeed); | ||
| 134 | + builder.append(strTmp, 0, 2); | ||
| 135 | + builder.append(strTmp, 0, 2); | ||
| 136 | + strTmp = String.format("%X", zoomSpeed); | ||
| 137 | + builder.append(strTmp, 0, 1).append("0"); | ||
| 138 | + //计算校验码 | ||
| 139 | + int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100; | ||
| 140 | + strTmp = String.format("%02X", checkCode); | ||
| 141 | + builder.append(strTmp, 0, 2); | ||
| 142 | + return builder.toString(); | ||
| 143 | +} | ||
| 144 | + | ||
| 145 | + | ||
| 97 | /** | 146 | /** |
| 98 | * 云台控制,支持方向与缩放控制 | 147 | * 云台控制,支持方向与缩放控制 |
| 99 | * | 148 | * |
| @@ -109,13 +158,14 @@ public class SIPCommander implements ISIPCommander { | @@ -109,13 +158,14 @@ public class SIPCommander implements ISIPCommander { | ||
| 109 | public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, | 158 | public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, |
| 110 | int zoomSpeed) { | 159 | int zoomSpeed) { |
| 111 | try { | 160 | try { |
| 161 | + String cmdStr= cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed); | ||
| 112 | StringBuffer ptzXml = new StringBuffer(200); | 162 | StringBuffer ptzXml = new StringBuffer(200); |
| 113 | ptzXml.append("<?xml version=\"1.0\" ?>"); | 163 | ptzXml.append("<?xml version=\"1.0\" ?>"); |
| 114 | ptzXml.append("<Control>"); | 164 | ptzXml.append("<Control>"); |
| 115 | ptzXml.append("<CmdType>DeviceControl</CmdType>"); | 165 | ptzXml.append("<CmdType>DeviceControl</CmdType>"); |
| 116 | ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>"); | 166 | ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>"); |
| 117 | ptzXml.append("<DeviceID>" + channelId + "</DeviceID>"); | 167 | ptzXml.append("<DeviceID>" + channelId + "</DeviceID>"); |
| 118 | - ptzXml.append("<PTZCmd>" + "</PTZCmd>"); | 168 | + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>"); |
| 119 | ptzXml.append("<Info>"); | 169 | ptzXml.append("<Info>"); |
| 120 | ptzXml.append("</Info>"); | 170 | ptzXml.append("</Info>"); |
| 121 | ptzXml.append("</Control>"); | 171 | ptzXml.append("</Control>"); |
| @@ -123,7 +173,6 @@ public class SIPCommander implements ISIPCommander { | @@ -123,7 +173,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 123 | Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag"); | 173 | Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag"); |
| 124 | 174 | ||
| 125 | transmitRequest(device, request); | 175 | transmitRequest(device, request); |
| 126 | - | ||
| 127 | return true; | 176 | return true; |
| 128 | } catch (SipException | ParseException | InvalidArgumentException e) { | 177 | } catch (SipException | ParseException | InvalidArgumentException e) { |
| 129 | e.printStackTrace(); | 178 | e.printStackTrace(); |
| @@ -245,6 +294,13 @@ public class SIPCommander implements ISIPCommander { | @@ -245,6 +294,13 @@ public class SIPCommander implements ISIPCommander { | ||
| 245 | return; | 294 | return; |
| 246 | } | 295 | } |
| 247 | Request byeRequest = dialog.createRequest(Request.BYE); | 296 | Request byeRequest = dialog.createRequest(Request.BYE); |
| 297 | + SipURI byeURI = (SipURI) byeRequest.getRequestURI(); | ||
| 298 | + String vh = transaction.getRequest().getHeader(ViaHeader.NAME).toString(); | ||
| 299 | + Pattern p = Pattern.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+)\\:(\\d+)"); | ||
| 300 | + Matcher matcher = p.matcher(vh); | ||
| 301 | + if (matcher.find()) { | ||
| 302 | + byeURI.setHost(matcher.group(1)); | ||
| 303 | + } | ||
| 248 | ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME); | 304 | ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME); |
| 249 | String protocol = viaHeader.getTransport().toUpperCase(); | 305 | String protocol = viaHeader.getTransport().toUpperCase(); |
| 250 | ClientTransaction clientTransaction = null; | 306 | ClientTransaction clientTransaction = null; |
| @@ -258,6 +314,8 @@ public class SIPCommander implements ISIPCommander { | @@ -258,6 +314,8 @@ public class SIPCommander implements ISIPCommander { | ||
| 258 | e.printStackTrace(); | 314 | e.printStackTrace(); |
| 259 | } catch (SipException e) { | 315 | } catch (SipException e) { |
| 260 | e.printStackTrace(); | 316 | e.printStackTrace(); |
| 317 | + } catch (ParseException e) { | ||
| 318 | + e.printStackTrace(); | ||
| 261 | } | 319 | } |
| 262 | } | 320 | } |
| 263 | 321 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/ISIPRequestProcessor.java
| @@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; | @@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; | ||
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | * @Description:处理接收IPCamera发来的SIP协议请求消息 | 8 | * @Description:处理接收IPCamera发来的SIP协议请求消息 |
| 9 | - * @author: swwheihei | 9 | + * @author: songww |
| 10 | * @date: 2020年5月3日 下午4:42:22 | 10 | * @date: 2020年5月3日 下午4:42:22 |
| 11 | */ | 11 | */ |
| 12 | public interface ISIPRequestProcessor { | 12 | public interface ISIPRequestProcessor { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
| @@ -16,7 +16,7 @@ import gov.nist.javax.sip.header.CSeq; | @@ -16,7 +16,7 @@ import gov.nist.javax.sip.header.CSeq; | ||
| 16 | 16 | ||
| 17 | /** | 17 | /** |
| 18 | * @Description:ACK请求处理器 | 18 | * @Description:ACK请求处理器 |
| 19 | - * @author: swwheihei | 19 | + * @author: songww |
| 20 | * @date: 2020年5月3日 下午5:31:45 | 20 | * @date: 2020年5月3日 下午5:31:45 |
| 21 | */ | 21 | */ |
| 22 | @Component | 22 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description: BYE请求处理器 | 12 | * @Description: BYE请求处理器 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午5:32:05 | 14 | * @date: 2020年5月3日 下午5:32:05 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/CancelRequestProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:CANCEL请求处理器 | 12 | * @Description:CANCEL请求处理器 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午5:32:23 | 14 | * @date: 2020年5月3日 下午5:32:23 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:处理INVITE请求 | 12 | * @Description:处理INVITE请求 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午4:43:52 | 14 | * @date: 2020年5月3日 下午4:43:52 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
| @@ -43,7 +43,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | @@ -43,7 +43,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 43 | 43 | ||
| 44 | /** | 44 | /** |
| 45 | * @Description:MESSAGE请求处理器 | 45 | * @Description:MESSAGE请求处理器 |
| 46 | - * @author: swwheihei | 46 | + * @author: songww |
| 47 | * @date: 2020年5月3日 下午5:32:41 | 47 | * @date: 2020年5月3日 下午5:32:41 |
| 48 | */ | 48 | */ |
| 49 | @Component | 49 | @Component |
| @@ -100,6 +100,7 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { | @@ -100,6 +100,7 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { | ||
| 100 | 100 | ||
| 101 | Request request = evt.getRequest(); | 101 | Request request = evt.getRequest(); |
| 102 | SAXReader reader = new SAXReader(); | 102 | SAXReader reader = new SAXReader(); |
| 103 | + reader.setEncoding("gbk"); | ||
| 103 | Document xml; | 104 | Document xml; |
| 104 | try { | 105 | try { |
| 105 | xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | 106 | xml = reader.read(new ByteArrayInputStream(request.getRawContent())); |
| @@ -375,7 +376,7 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { | @@ -375,7 +376,7 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { | ||
| 375 | private Element getRootElement(RequestEvent evt) throws DocumentException { | 376 | private Element getRootElement(RequestEvent evt) throws DocumentException { |
| 376 | Request request = evt.getRequest(); | 377 | Request request = evt.getRequest(); |
| 377 | SAXReader reader = new SAXReader(); | 378 | SAXReader reader = new SAXReader(); |
| 378 | - reader.setEncoding("GB2312"); | 379 | + reader.setEncoding("gbk"); |
| 379 | Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | 380 | Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); |
| 380 | return xml.getRootElement(); | 381 | return xml.getRootElement(); |
| 381 | } | 382 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:暂不支持的消息请求处理器 | 12 | * @Description:暂不支持的消息请求处理器 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午5:32:59 | 14 | * @date: 2020年5月3日 下午5:32:59 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
| @@ -38,7 +38,7 @@ import gov.nist.javax.sip.header.Expires; | @@ -38,7 +38,7 @@ import gov.nist.javax.sip.header.Expires; | ||
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | * @Description:收到注册请求 处理 | 40 | * @Description:收到注册请求 处理 |
| 41 | - * @author: swwheihei | 41 | + * @author: songww |
| 42 | * @date: 2020年5月3日 下午4:47:25 | 42 | * @date: 2020年5月3日 下午4:47:25 |
| 43 | */ | 43 | */ |
| 44 | @Component | 44 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/SubscribeRequestProcessor.java
| @@ -17,7 +17,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | @@ -17,7 +17,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | ||
| 17 | 17 | ||
| 18 | /** | 18 | /** |
| 19 | * @Description:SUBSCRIBE请求处理器 | 19 | * @Description:SUBSCRIBE请求处理器 |
| 20 | - * @author: swwheihei | 20 | + * @author: songww |
| 21 | * @date: 2020年5月3日 下午5:31:20 | 21 | * @date: 2020年5月3日 下午5:31:20 |
| 22 | */ | 22 | */ |
| 23 | @Component | 23 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.response; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.response; |
| 2 | 2 | ||
| 3 | +import java.text.ParseException; | ||
| 4 | + | ||
| 3 | import javax.sip.ResponseEvent; | 5 | import javax.sip.ResponseEvent; |
| 4 | 6 | ||
| 5 | import com.genersoft.iot.vmp.conf.SipConfig; | 7 | import com.genersoft.iot.vmp.conf.SipConfig; |
| @@ -7,11 +9,11 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; | @@ -7,11 +9,11 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; | ||
| 7 | 9 | ||
| 8 | /** | 10 | /** |
| 9 | * @Description:处理接收IPCamera发来的SIP协议响应消息 | 11 | * @Description:处理接收IPCamera发来的SIP协议响应消息 |
| 10 | - * @author: swwheihei | 12 | + * @author: songww |
| 11 | * @date: 2020年5月3日 下午4:42:22 | 13 | * @date: 2020年5月3日 下午4:42:22 |
| 12 | */ | 14 | */ |
| 13 | public interface ISIPResponseProcessor { | 15 | public interface ISIPResponseProcessor { |
| 14 | 16 | ||
| 15 | - public void process(ResponseEvent evt, SipLayer layer, SipConfig config); | 17 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException; |
| 16 | 18 | ||
| 17 | } | 19 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/ByeResponseProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description: BYE请求响应器 | 12 | * @Description: BYE请求响应器 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午5:32:05 | 14 | * @date: 2020年5月3日 下午5:32:05 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/CancelResponseProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:CANCEL响应处理器 | 12 | * @Description:CANCEL响应处理器 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午5:32:23 | 14 | * @date: 2020年5月3日 下午5:32:23 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
| @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.response.impl; | @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.response.impl; | ||
| 2 | 2 | ||
| 3 | import java.text.ParseException; | 3 | import java.text.ParseException; |
| 4 | 4 | ||
| 5 | -import javax.sip.ClientTransaction; | ||
| 6 | import javax.sip.Dialog; | 5 | import javax.sip.Dialog; |
| 7 | import javax.sip.InvalidArgumentException; | 6 | import javax.sip.InvalidArgumentException; |
| 8 | import javax.sip.ResponseEvent; | 7 | import javax.sip.ResponseEvent; |
| @@ -22,57 +21,76 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; | @@ -22,57 +21,76 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; | ||
| 22 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; | 21 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; |
| 23 | import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | 22 | import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; |
| 24 | 23 | ||
| 25 | -/** | ||
| 26 | - * @Description:处理INVITE响应 | ||
| 27 | - * @author: swwheihei | ||
| 28 | - * @date: 2020年5月3日 下午4:43:52 | 24 | + |
| 25 | +/** | ||
| 26 | + * @Description:处理INVITE响应 | ||
| 27 | + * @author: songww | ||
| 28 | + * @date: 2020年5月3日 下午4:43:52 | ||
| 29 | */ | 29 | */ |
| 30 | @Component | 30 | @Component |
| 31 | public class InviteResponseProcessor implements ISIPResponseProcessor { | 31 | public class InviteResponseProcessor implements ISIPResponseProcessor { |
| 32 | 32 | ||
| 33 | private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); | 33 | private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); |
| 34 | - | 34 | + |
| 35 | /** | 35 | /** |
| 36 | * 处理invite响应 | 36 | * 处理invite响应 |
| 37 | * | 37 | * |
| 38 | - * @param evt | ||
| 39 | - * 响应消息 | ||
| 40 | - */ | 38 | + * @param evt 响应消息 |
| 39 | + * @throws ParseException | ||
| 40 | + */ | ||
| 41 | @Override | 41 | @Override |
| 42 | - public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { | 42 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException { |
| 43 | try { | 43 | try { |
| 44 | Response response = evt.getResponse(); | 44 | Response response = evt.getResponse(); |
| 45 | int statusCode = response.getStatusCode(); | 45 | int statusCode = response.getStatusCode(); |
| 46 | - //trying不会回复 | ||
| 47 | - if(statusCode == Response.TRYING){ | ||
| 48 | - | 46 | + // trying不会回复 |
| 47 | + if (statusCode == Response.TRYING) { | ||
| 49 | } | 48 | } |
| 50 | - //成功响应 | ||
| 51 | - //下发ack | ||
| 52 | - if(statusCode == Response.OK){ | ||
| 53 | -// ClientTransaction clientTransaction = evt.getClientTransaction(); | ||
| 54 | -// if(clientTransaction == null){ | ||
| 55 | -// logger.error("回复ACK时,clientTransaction为null >>> {}",response); | ||
| 56 | -// return; | ||
| 57 | -// } | ||
| 58 | -// Dialog clientDialog = clientTransaction.getDialog(); | ||
| 59 | -// | ||
| 60 | -// CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); | ||
| 61 | -// long cseqId = clientCSeqHeader.getSeqNumber(); | ||
| 62 | -// /* | ||
| 63 | -// createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。 | ||
| 64 | -// 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流 | ||
| 65 | -// 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。 | ||
| 66 | -// */ | ||
| 67 | -// Request ackRequest = clientDialog.createAck(cseqId); | ||
| 68 | -// SipURI requestURI = (SipURI) ackRequest.getRequestURI(); | ||
| 69 | -// ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME); | ||
| 70 | -// requestURI.setHost(viaHeader.getHost()); | ||
| 71 | -// requestURI.setPort(viaHeader.getPort()); | ||
| 72 | -// clientDialog.sendAck(ackRequest); | ||
| 73 | - | 49 | + // 成功响应 |
| 50 | + // 下发ack | ||
| 51 | + if (statusCode == Response.OK) { | ||
| 52 | + // ClientTransaction clientTransaction = evt.getClientTransaction(); | ||
| 53 | + // if(clientTransaction == null){ | ||
| 54 | + // logger.error("回复ACK时,clientTransaction为null >>> {}",response); | ||
| 55 | + // return; | ||
| 56 | + // } | ||
| 57 | + // Dialog clientDialog = clientTransaction.getDialog(); | ||
| 58 | + | ||
| 59 | + // CSeqHeader clientCSeqHeader = (CSeqHeader) | ||
| 60 | + // response.getHeader(CSeqHeader.NAME); | ||
| 61 | + // long cseqId = clientCSeqHeader.getSeqNumber(); | ||
| 62 | + // /* | ||
| 63 | + // createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。 | ||
| 64 | + // 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流 | ||
| 65 | + // 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。 | ||
| 66 | + // */ | ||
| 67 | + // Request ackRequest = clientDialog.createAck(cseqId); | ||
| 68 | + // SipURI requestURI = (SipURI) ackRequest.getRequestURI(); | ||
| 69 | + // ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME); | ||
| 70 | + // try { | ||
| 71 | + // requestURI.setHost(viaHeader.getHost()); | ||
| 72 | + // } catch (Exception e) { | ||
| 73 | + // e.printStackTrace(); | ||
| 74 | + // } | ||
| 75 | + // requestURI.setPort(viaHeader.getPort()); | ||
| 76 | + // clientDialog.sendAck(ackRequest); | ||
| 77 | + | ||
| 74 | Dialog dialog = evt.getDialog(); | 78 | Dialog dialog = evt.getDialog(); |
| 75 | - Request reqAck =dialog.createAck(1L); | 79 | + CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
| 80 | + Request reqAck = dialog.createAck(cseq.getSeqNumber()); | ||
| 81 | + | ||
| 82 | + SipURI requestURI = (SipURI) reqAck.getRequestURI(); | ||
| 83 | + ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME); | ||
| 84 | + // String viaHost =viaHeader.getHost(); | ||
| 85 | + //getHost()函数取回的IP地址是“[xxx.xxx.xxx.xxx:yyyy]”的格式,需用正则表达式截取为“xxx.xxx.xxx.xxx"格式 | ||
| 86 | + // Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+"); | ||
| 87 | + // Matcher matcher = p.matcher(viaHeader.getHost()); | ||
| 88 | + // if (matcher.find()) { | ||
| 89 | + // requestURI.setHost(matcher.group()); | ||
| 90 | + // } | ||
| 91 | + requestURI.setHost(viaHeader.getHost()); | ||
| 92 | + requestURI.setPort(viaHeader.getPort()); | ||
| 93 | + reqAck.setRequestURI(requestURI); | ||
| 76 | dialog.sendAck(reqAck); | 94 | dialog.sendAck(reqAck); |
| 77 | } | 95 | } |
| 78 | } catch (InvalidArgumentException | SipException e) { | 96 | } catch (InvalidArgumentException | SipException e) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/OtherResponseProcessor.java
| @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:暂不支持的消息响应处理器 | 12 | * @Description:暂不支持的消息响应处理器 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月3日 下午5:32:59 | 14 | * @date: 2020年5月3日 下午5:32:59 |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java
| @@ -7,7 +7,7 @@ import java.util.Locale; | @@ -7,7 +7,7 @@ import java.util.Locale; | ||
| 7 | 7 | ||
| 8 | /** | 8 | /** |
| 9 | * @Description:时间工具类,主要处理ISO 8601格式转换 | 9 | * @Description:时间工具类,主要处理ISO 8601格式转换 |
| 10 | - * @author: swwheihei | 10 | + * @author: songww |
| 11 | * @date: 2020年5月8日 下午3:24:42 | 11 | * @date: 2020年5月8日 下午3:24:42 |
| 12 | */ | 12 | */ |
| 13 | public class DateUtil { | 13 | public class DateUtil { |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| @@ -18,11 +18,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | @@ -18,11 +18,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 18 | 18 | ||
| 19 | /** | 19 | /** |
| 20 | * @Description:针对 ZLMediaServer的hook事件监听 | 20 | * @Description:针对 ZLMediaServer的hook事件监听 |
| 21 | - * @author: swwheihei | 21 | + * @author: songww |
| 22 | * @date: 2020年5月8日 上午10:46:48 | 22 | * @date: 2020年5月8日 上午10:46:48 |
| 23 | */ | 23 | */ |
| 24 | @RestController | 24 | @RestController |
| 25 | -@RequestMapping("/hook/zlm") | 25 | +@RequestMapping("/index/hook") |
| 26 | public class ZLMHttpHookListener { | 26 | public class ZLMHttpHookListener { |
| 27 | 27 | ||
| 28 | private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class); | 28 | private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class); |
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
| @@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; | @@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | * @Description:视频设备数据存储接口 | 8 | * @Description:视频设备数据存储接口 |
| 9 | - * @author: swwheihei | 9 | + * @author: songww |
| 10 | * @date: 2020年5月6日 下午2:14:31 | 10 | * @date: 2020年5月6日 下午2:14:31 |
| 11 | */ | 11 | */ |
| 12 | public interface IVideoManagerStorager { | 12 | public interface IVideoManagerStorager { |
src/main/java/com/genersoft/iot/vmp/storager/VideoManagerStoragerFactory.java
| @@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.conf.VManagerConfig; | @@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.conf.VManagerConfig; | ||
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| 10 | * @Description:视频设备数据存储工厂,根据存储策略,返回对应的存储器 | 10 | * @Description:视频设备数据存储工厂,根据存储策略,返回对应的存储器 |
| 11 | - * @author: swwheihei | 11 | + * @author: songww |
| 12 | * @date: 2020年5月6日 下午2:15:16 | 12 | * @date: 2020年5月6日 下午2:15:16 |
| 13 | */ | 13 | */ |
| 14 | @Component | 14 | @Component |
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
| @@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | @@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | ||
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| 13 | * @Description:视频设备数据存储-jdbc实现 | 13 | * @Description:视频设备数据存储-jdbc实现 |
| 14 | - * @author: swwheihei | 14 | + * @author: songww |
| 15 | * @date: 2020年5月6日 下午2:28:12 | 15 | * @date: 2020年5月6日 下午2:28:12 |
| 16 | */ | 16 | */ |
| 17 | @Component("jdbcStorager") | 17 | @Component("jdbcStorager") |
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
| @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * @Description:视频设备数据存储-redis实现 | 15 | * @Description:视频设备数据存储-redis实现 |
| 16 | - * @author: swwheihei | 16 | + * @author: songww |
| 17 | * @date: 2020年5月6日 下午2:31:42 | 17 | * @date: 2020年5月6日 下午2:31:42 |
| 18 | */ | 18 | */ |
| 19 | @Component("redisStorager") | 19 | @Component("redisStorager") |
src/main/java/com/genersoft/iot/vmp/utils/SpringBeanFactory.java
| @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; | @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; | ||
| 7 | 7 | ||
| 8 | /** | 8 | /** |
| 9 | * @Description:spring bean获取工厂,获取spring中的已初始化的bean | 9 | * @Description:spring bean获取工厂,获取spring中的已初始化的bean |
| 10 | - * @author: swwheihei | 10 | + * @author: songww |
| 11 | * @date: 2019年6月25日 下午4:51:52 | 11 | * @date: 2019年6月25日 下午4:51:52 |
| 12 | * | 12 | * |
| 13 | */ | 13 | */ |
src/main/java/com/genersoft/iot/vmp/utils/redis/FastJsonRedisSerializer.java
| @@ -10,7 +10,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature; | @@ -10,7 +10,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature; | ||
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * @Description:使用fastjson实现redis的序列化 | 12 | * @Description:使用fastjson实现redis的序列化 |
| 13 | - * @author: swwheihei | 13 | + * @author: songww |
| 14 | * @date: 2020年5月6日 下午8:40:11 | 14 | * @date: 2020年5月6日 下午8:40:11 |
| 15 | */ | 15 | */ |
| 16 | public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { | 16 | public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { |
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
| @@ -13,7 +13,7 @@ import org.springframework.util.CollectionUtils; | @@ -13,7 +13,7 @@ import org.springframework.util.CollectionUtils; | ||
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * @Description:Redis工具类 | 15 | * @Description:Redis工具类 |
| 16 | - * @author: swwheihei | 16 | + * @author: songww |
| 17 | * @date: 2020年5月6日 下午8:27:29 | 17 | * @date: 2020年5月6日 下午8:27:29 |
| 18 | */ | 18 | */ |
| 19 | @Component | 19 | @Component |
src/main/resources/application.yml
| @@ -26,7 +26,8 @@ spring: | @@ -26,7 +26,8 @@ spring: | ||
| 26 | server: | 26 | server: |
| 27 | port: 8080 | 27 | port: 8080 |
| 28 | sip: | 28 | sip: |
| 29 | - ip: 10.200.64.63 | 29 | +# ip: 10.200.64.63 |
| 30 | + ip: 192.168.0.102 | ||
| 30 | port: 5060 | 31 | port: 5060 |
| 31 | # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) | 32 | # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) |
| 32 | # 后两位为行业编码,定义参照附录D.3 | 33 | # 后两位为行业编码,定义参照附录D.3 |
| @@ -34,7 +35,8 @@ sip: | @@ -34,7 +35,8 @@ sip: | ||
| 34 | domain: 3701020049 | 35 | domain: 3701020049 |
| 35 | id: 37010200492000000001 | 36 | id: 37010200492000000001 |
| 36 | # 默认设备认证密码,后续扩展使用设备单独密码 | 37 | # 默认设备认证密码,后续扩展使用设备单独密码 |
| 37 | - password: admin | 38 | + password: admin123 |
| 38 | media: | 39 | media: |
| 39 | - ip: 10.200.64.88 | 40 | +# ip: 10.200.64.88 |
| 41 | + ip: 192.168.0.102 | ||
| 40 | port: 10000 | 42 | port: 10000 |
| 41 | \ No newline at end of file | 43 | \ No newline at end of file |
wikis/images/核心流程.png