diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index b70c5eb6..64525d7a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.gb28181; +import java.text.ParseException; import java.util.Properties; import javax.annotation.PostConstruct; @@ -128,11 +129,18 @@ public class SipLayer implements SipListener, Runnable { int status = response.getStatusCode(); if ((status >= 200) && (status < 300)) { // Success! ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); - processor.process(evt, this, sipConfig); - } else if (status == Response.TRYING) { + 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.getContent().toString()); + logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); } // trying不会回复 // if (status == Response.TRYING) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index c15b9b68..7a95268c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -79,7 +79,8 @@ public class SIPRequestHeaderProvider { SipURI requestLine = layer.getAddressFactory().createSipURI(channelId, host.getAddress()); //via ArrayList viaHeaders = new ArrayList(); - 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 viaHeaders = new ArrayList(); - 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"); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index b70f353e..96618d05 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -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,6 +24,9 @@ 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: songww @@ -288,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; @@ -301,6 +314,8 @@ public class SIPCommander implements ISIPCommander { e.printStackTrace(); } catch (SipException e) { e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java index fd5ca377..f5c3c8bc 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java @@ -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(); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java index 9ff99597..458158b4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java @@ -1,5 +1,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.response; +import java.text.ParseException; + import javax.sip.ResponseEvent; import com.genersoft.iot.vmp.conf.SipConfig; @@ -12,6 +14,6 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; */ public interface ISIPResponseProcessor { - public void process(ResponseEvent evt, SipLayer layer, SipConfig config); + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java index 9b1783f8..9c862fad 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java @@ -7,8 +7,11 @@ import javax.sip.Dialog; import javax.sip.InvalidArgumentException; import javax.sip.ResponseEvent; import javax.sip.SipException; +import javax.sip.address.Address; import javax.sip.address.SipURI; import javax.sip.header.CSeqHeader; +import javax.sip.header.ContactHeader; +import javax.sip.header.FromHeader; import javax.sip.header.ViaHeader; import javax.sip.message.Request; import javax.sip.message.Response; @@ -22,57 +25,78 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; -/** +// import java.util.regex.Pattern; +// import java.util.regex.Matcher; + +/** * @Description:处理INVITE响应 * @author: songww - * @date: 2020年5月3日 下午4:43:52 + * @date: 2020年5月3日 下午4:43:52 */ @Component public class InviteResponseProcessor implements ISIPResponseProcessor { private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class); - + /** * 处理invite响应 * - * @param evt - * 响应消息 - */ + * @param evt 响应消息 + * @throws ParseException + */ @Override - public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException { try { Response response = evt.getResponse(); int statusCode = response.getStatusCode(); - //trying不会回复 - if(statusCode == Response.TRYING){ - + // trying不会回复 + if (statusCode == Response.TRYING) { } - //成功响应 - //下发ack - if(statusCode == Response.OK){ -// ClientTransaction clientTransaction = evt.getClientTransaction(); -// if(clientTransaction == null){ -// logger.error("回复ACK时,clientTransaction为null >>> {}",response); -// return; -// } -// Dialog clientDialog = clientTransaction.getDialog(); -// -// CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); -// long cseqId = clientCSeqHeader.getSeqNumber(); -// /* -// createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。 -// 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流 -// 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。 -// */ -// Request ackRequest = clientDialog.createAck(cseqId); -// SipURI requestURI = (SipURI) ackRequest.getRequestURI(); -// ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME); -// requestURI.setHost(viaHeader.getHost()); -// requestURI.setPort(viaHeader.getPort()); -// clientDialog.sendAck(ackRequest); - + // 成功响应 + // 下发ack + if (statusCode == Response.OK) { + // ClientTransaction clientTransaction = evt.getClientTransaction(); + // if(clientTransaction == null){ + // logger.error("回复ACK时,clientTransaction为null >>> {}",response); + // return; + // } + // Dialog clientDialog = clientTransaction.getDialog(); + + // CSeqHeader clientCSeqHeader = (CSeqHeader) + // response.getHeader(CSeqHeader.NAME); + // long cseqId = clientCSeqHeader.getSeqNumber(); + // /* + // createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。 + // 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流 + // 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。 + // */ + // Request ackRequest = clientDialog.createAck(cseqId); + // SipURI requestURI = (SipURI) ackRequest.getRequestURI(); + // ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME); + // try { + // requestURI.setHost(viaHeader.getHost()); + // } catch (Exception e) { + // e.printStackTrace(); + // } + // requestURI.setPort(viaHeader.getPort()); + // clientDialog.sendAck(ackRequest); + Dialog dialog = evt.getDialog(); - Request reqAck =dialog.createAck(1L); + CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); + Request reqAck = dialog.createAck(cseq.getSeqNumber()); + + SipURI requestURI = (SipURI) reqAck.getRequestURI(); + ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME); + // String viaHost =viaHeader.getHost(); + //getHost()函数取回的IP地址是“[xxx.xxx.xxx.xxx:yyyy]”的格式,需用正则表达式截取为“xxx.xxx.xxx.xxx"格式 + // Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+"); + // Matcher matcher = p.matcher(viaHeader.getHost()); + // if (matcher.find()) { + // requestURI.setHost(matcher.group()); + // } + requestURI.setHost(viaHeader.getHost()); + requestURI.setPort(viaHeader.getPort()); + reqAck.setRequestURI(requestURI); dialog.sendAck(reqAck); } } catch (InvalidArgumentException | SipException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index e4be40b0..25f000b5 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -22,7 +22,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; * @date: 2020年5月8日 上午10:46:48 */ @RestController -@RequestMapping("/hook/zlm") +@RequestMapping("/index/hook") public class ZLMHttpHookListener { private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);