Conflicts:
	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
master
swwheihei 2020-07-16 16:09:48 +08:00
commit 29710b7cc1
49 changed files with 461 additions and 343 deletions

21
LICENSE Normal file
View 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.

View File

@ -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>

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.common;
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 2019530 3:04:04
*
*/

View File

@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
/**
* @Description:Redis使spring-data-redisapplication.ymlredis
* @author: swwheihei
* @author: songww
* @date: 2019530 10:58:25
*
*/

View File

@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration;
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 202056 2:46:00
*/
@Configuration("vmConfig")

View File

@ -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;
}
}

View File

@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202058 9:41:46
*/
@Component

View File

@ -4,7 +4,7 @@ import java.util.List;
/**
* @Description:bean
* @author: swwheihei
* @author: songww
* @date: 202058 2:05:56
*/
public class RecordInfo {

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.bean;
/**
* @Description:bean
* @author: swwheihei
* @author: songww
* @date: 202058 2:06:54
*/
public class RecordItem {

View File

@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
/**
* @Description:线
* @author: swwheihei
* @author: songww
* @date: 2020513 2:40:29
*/
@Component

View File

@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
/**
* @Description:Event线线
* @author: swwheihei
* @author: songww
* @date: 202056 11:30:50
*/
@Component

View File

@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
/**
* @Description:,redis线
* @author: swwheihei
* @author: songww
* @date: 202056 11:35:46
*/
@Component

View File

@ -4,7 +4,7 @@ import org.springframework.context.ApplicationEvent;
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 202056 11:33:13
*/
public class OfflineEvent extends ApplicationEvent {

View File

@ -14,7 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
* @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: 202056 1:51:23
*/
@Component

View File

@ -4,7 +4,7 @@ import org.springframework.context.ApplicationEvent;
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 202056 11:32:56
*/
public class OnlineEvent extends ApplicationEvent {

View File

@ -14,7 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
* @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: 202056 1:51:23
*/
@Component

View File

@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.utils.SpringBeanFactory;
/**
* @Description:SIPSSRCSSRC1001ID4844
* @author: swwheihei
* @author: songww
* @date: 2020510 11:57:57
*/
public class SsrcUtil {

View File

@ -8,7 +8,7 @@ import org.springframework.stereotype.Component;
/**
* @Description:session
* @author: swwheihei
* @author: songww
* @date: 2020513 4:03:02
*/
@Component

View File

@ -26,7 +26,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcess
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 202053 4:24:37
*/
@Component

View File

@ -10,7 +10,7 @@ import org.springframework.web.context.request.async.DeferredResult;
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 202058 7:59:05
*/
@Component

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback;
/**
* @Description:TODO()
* @author: swwheihei
* @author: songww
* @date: 202058 1:09:18
*/
public class RequestMessage {

View File

@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202053 9:16:34
*/
public interface ISIPCommander {

View File

@ -25,7 +25,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Host;
/**
* @Description:request TODO
* @author: swwheihei
* @author: songww
* @date: 202056 9:29:02
*/
@Component
@ -79,7 +79,8 @@ public class SIPRequestHeaderProvider {
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 @@ public class SIPRequestHeaderProvider {
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 @@ public class SIPRequestHeaderProvider {
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 @@ public class SIPRequestHeaderProvider {
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");

View File

@ -7,10 +7,13 @@ import javax.sip.Dialog;
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.ISIPCommander;
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: 202053 9:22:48
*/
@Component
@ -94,6 +100,49 @@ public class SIPCommander implements ISIPCommander {
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 class SIPCommander implements ISIPCommander {
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 @@ public class SIPCommander implements ISIPCommander {
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 @@ public class SIPCommander implements ISIPCommander {
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 @@ public class SIPCommander implements ISIPCommander {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}

View File

@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.SipLayer;
/**
* @Description:IPCameraSIP
* @author: swwheihei
* @author: songww
* @date: 202053 4:42:22
*/
public interface ISIPRequestProcessor {

View File

@ -16,7 +16,7 @@ import gov.nist.javax.sip.header.CSeq;
/**
* @Description:ACK
* @author: swwheihei
* @author: songww
* @date: 202053 5:31:45
*/
@Component

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
/**
* @Description: BYE
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:05
*/
@Component

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
/**
* @Description:CANCEL
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:23
*/
@Component

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
/**
* @Description:INVITE
* @author: swwheihei
* @author: songww
* @date: 202053 4:43:52
*/
@Component

View File

@ -43,7 +43,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
/**
* @Description:MESSAGE
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:41
*/
@Component
@ -100,6 +100,7 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
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 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
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();
}

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:59
*/
@Component

View File

@ -38,7 +38,7 @@ import gov.nist.javax.sip.header.Expires;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202053 4:47:25
*/
@Component

View File

@ -17,7 +17,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
/**
* @Description:SUBSCRIBE
* @author: swwheihei
* @author: songww
* @date: 202053 5:31:20
*/
@Component

View File

@ -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 @@ import com.genersoft.iot.vmp.gb28181.SipLayer;
/**
* @Description:IPCameraSIP
* @author: swwheihei
* @author: songww
* @date: 202053 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;
}

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
/**
* @Description: BYE
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:05
*/
@Component

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
/**
* @Description:CANCEL
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:23
*/
@Component

View File

@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
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.SipLayer;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
/**
* @Description:INVITE
* @author: swwheihei
* @date: 202053 4:43:52
/**
* @Description:INVITE
* @author: songww
* @date: 202053 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) {

View File

@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202053 5:32:59
*/
@Component

View File

@ -7,7 +7,7 @@ import java.util.Locale;
/**
* @Description:ISO 8601
* @author: swwheihei
* @author: songww
* @date: 202058 3:24:42
*/
public class DateUtil {

View File

@ -18,11 +18,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
/**
* @Description: ZLMediaServerhook
* @author: swwheihei
* @author: songww
* @date: 202058 10:46:48
*/
@RestController
@RequestMapping("/hook/zlm")
@RequestMapping("/index/hook")
public class ZLMHttpHookListener {
private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);

View File

@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202056 2:14:31
*/
public interface IVideoManagerStorager {

View File

@ -8,7 +8,7 @@ import com.genersoft.iot.vmp.conf.VManagerConfig;
/**
* @Description:
* @author: swwheihei
* @author: songww
* @date: 202056 2:15:16
*/
@Component

View File

@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
/**
* @Description:-jdbc
* @author: swwheihei
* @author: songww
* @date: 202056 2:28:12
*/
@Component("jdbcStorager")

View File

@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
/**
* @Description:-redis
* @author: swwheihei
* @author: songww
* @date: 202056 2:31:42
*/
@Component("redisStorager")

View File

@ -7,7 +7,7 @@ import org.springframework.stereotype.Component;
/**
* @Description:spring beanspringbean
* @author: swwheihei
* @author: songww
* @date: 2019625 4:51:52
*
*/

View File

@ -10,7 +10,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
/**
* @Description:使fastjsonredis
* @author: swwheihei
* @author: songww
* @date: 202056 8:40:11
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

View File

@ -13,7 +13,7 @@ import org.springframework.util.CollectionUtils;
/**
* @Description:Redis
* @author: swwheihei
* @author: songww
* @date: 202056 8:27:29
*/
@Component

View File

@ -26,7 +26,8 @@ spring:
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 @@ sip:
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 169 KiB