Commit c041aaccb43baf73d1a9f5b50fb5a1f410b88523

Authored by 648540858
1 parent 2591997d

修复录像回放中的信令错误

src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -77,38 +77,54 @@ public class VideoManagerConstants {
77 77  
78 78 //************************** redis 消息*********************************
79 79  
80   - // 流变化的通知
  80 + /**
  81 + * 流变化的通知
  82 + */
81 83 public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
82 84  
83   - // 接收推流设备的GPS变化通知
  85 + /**
  86 + * 接收推流设备的GPS变化通知
  87 + */
84 88 public static final String VM_MSG_GPS = "VM_MSG_GPS";
85 89  
86   - // 接收推流设备的GPS变化通知
  90 + /**
  91 + * 接收推流设备的GPS变化通知
  92 + */
87 93 public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
88 94  
89   - // redis 消息通知设备推流到平台
  95 + /**
  96 + * redis 消息通知设备推流到平台
  97 + */
90 98 public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
91 99  
92   - // redis 消息请求所有的在线通道
  100 + /**
  101 + * redis 消息请求所有的在线通道
  102 + */
93 103 public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED";
94 104  
95   - // 移动位置订阅通知
  105 + /**
  106 + * 移动位置订阅通知
  107 + */
96 108 public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
97 109  
98   - // 报警订阅的通知(收到报警向redis发出通知)
  110 + /**
  111 + * 报警订阅的通知(收到报警向redis发出通知)
  112 + */
99 113 public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm";
100 114  
101   - // 报警通知的发送 (收到redis发出的通知,转发给其他平台)
  115 + /**
  116 + * 报警通知的发送 (收到redis发出的通知,转发给其他平台)
  117 + */
102 118 public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive";
103 119  
104   - // 设备状态订阅的通知
  120 + /**
  121 + * 设备状态订阅的通知
  122 + */
105 123 public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
106 124  
107 125  
108   -
109   -
110   -
111 126 //************************** 第三方 ****************************************
  127 +
112 128 public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
113 129 public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
114 130  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -62,7 +62,7 @@ public class SIPRequestHeaderPlarformProvider {
62 62 // Forwards
63 63 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
64 64 // ceq
65   - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.MESSAGE), Request.MESSAGE);
  65 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
66 66  
67 67 request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
68 68 toHeader, viaHeaders, maxForwards);
... ... @@ -120,7 +120,7 @@ public class SIPRequestHeaderPlarformProvider {
120 120 String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader) throws ParseException, PeerUnavailableException, InvalidArgumentException {
121 121  
122 122  
123   - Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader);
  123 + Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader);
124 124 SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
125 125 if (www == null) {
126 126 AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest");
... ... @@ -213,7 +213,7 @@ public class SIPRequestHeaderPlarformProvider {
213 213 // Forwards
214 214 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
215 215 // ceq
216   - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.MESSAGE), Request.MESSAGE);
  216 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
217 217 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
218 218 // 设置编码, 防止中文乱码
219 219 messageFactory.setDefaultContentEncodingCharset(parentPlatform.getCharacterSet());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -2,11 +2,9 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import java.text.ParseException;
4 4 import java.util.ArrayList;
  5 +import java.util.List;
5 6  
6   -import javax.sip.Dialog;
7   -import javax.sip.InvalidArgumentException;
8   -import javax.sip.PeerUnavailableException;
9   -import javax.sip.SipFactory;
  7 +import javax.sip.*;
10 8 import javax.sip.address.Address;
11 9 import javax.sip.address.SipURI;
12 10 import javax.sip.header.*;
... ... @@ -15,7 +13,11 @@ import javax.sip.message.Request;
15 13 import com.genersoft.iot.vmp.common.StreamInfo;
16 14 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
17 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  16 +import gov.nist.javax.sip.SipProviderImpl;
  17 +import gov.nist.javax.sip.SipStackImpl;
  18 +import gov.nist.javax.sip.stack.SIPDialog;
18 19 import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.beans.factory.annotation.Qualifier;
19 21 import org.springframework.stereotype.Component;
20 22  
21 23 import com.genersoft.iot.vmp.conf.SipConfig;
... ... @@ -40,6 +42,14 @@ public class SIPRequestHeaderProvider {
40 42  
41 43 @Autowired
42 44 private VideoStreamSessionManager streamSession;
  45 +
  46 + @Autowired
  47 + @Qualifier(value="tcpSipProvider")
  48 + private SipProviderImpl tcpSipProvider;
  49 +
  50 + @Autowired
  51 + @Qualifier(value="udpSipProvider")
  52 + private SipProviderImpl udpSipProvider;
43 53  
44 54 public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
45 55 Request request = null;
... ... @@ -95,7 +105,7 @@ public class SIPRequestHeaderProvider {
95 105 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
96 106  
97 107 //ceq
98   - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.INVITE), Request.INVITE);
  108 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
99 109 request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
100 110  
101 111 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
... ... @@ -131,7 +141,7 @@ public class SIPRequestHeaderProvider {
131 141 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
132 142  
133 143 //ceq
134   - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.INVITE), Request.INVITE);
  144 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
135 145 request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
136 146  
137 147 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
... ... @@ -200,7 +210,7 @@ public class SIPRequestHeaderProvider {
200 210 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
201 211  
202 212 // ceq
203   - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.SUBSCRIBE), Request.SUBSCRIBE);
  213 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE);
204 214  
205 215 request = sipFactory.createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
206 216 toHeader, viaHeaders, maxForwards);
... ... @@ -226,55 +236,55 @@ public class SIPRequestHeaderProvider {
226 236 }
227 237  
228 238 public Request createInfoRequest(Device device, StreamInfo streamInfo, String content)
229   - throws PeerUnavailableException, ParseException, InvalidArgumentException {
230   - Request request = null;
  239 + throws SipException, ParseException, InvalidArgumentException {
231 240 if (streamInfo == null) {
232 241 return null;
233 242 }
234   - Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
  243 + Request request = null;
  244 + SIPDialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
235 245 if (dialog == null) {
236 246 return null;
237 247 }
238 248  
239   - SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
240   - device.getHostAddress());
241   - // via
242   - ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
243   - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(),
244   - device.getTransport(), null);
  249 + SipStack sipStack = udpSipProvider.getSipStack();
  250 + SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
  251 + if (dialog != sipDialog) {
  252 + dialog = sipDialog;
  253 + }else {
  254 + dialog.setSipProvider(udpSipProvider);
  255 + }
  256 + streamSession.put(streamInfo.getDeviceID(), streamInfo.getChannelId(), dialog.getCallId().getCallId(), dialog);
  257 + Request infoRequest = dialog.createRequest(Request.INFO);
  258 + SipURI sipURI = (SipURI) infoRequest.getRequestURI();
  259 + sipURI.setHost(device.getIp());
  260 + sipURI.setPort(device.getPort());
  261 + sipURI.setUser(streamInfo.getChannelId());
  262 +
  263 + ViaHeader viaHeader = (ViaHeader) infoRequest.getHeader(ViaHeader.NAME);
245 264 viaHeader.setRPort();
246   - viaHeaders.add(viaHeader);
247   - // from
248   - SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),
249   - sipConfig.getDomain());
250   - Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
251   - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, dialog.getLocalTag());
252   - // to
253   - SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(streamInfo.getChannelId(),
254   - sipConfig.getDomain());
255   - Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
256   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, dialog.getRemoteTag());
257   -
258   - // callid
259   - CallIdHeader callIdHeader = dialog.getCallId();
260   -
261   - // Forwards
262   - MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
263   -
264   - Long cseq = redisCatchStorage.getCSEQ(Request.INVITE);
265   - // ceq
266   - CSeqHeader cSeqHeader = sipFactory.createHeaderFactory()
267   - .createCSeqHeader(cseq, Request.INFO);
268   -
269   - request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,
270   - fromHeader, toHeader, viaHeaders, maxForwards);
  265 + // 增加Contact header
271 266 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
272 267 .createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort()));
273   - request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  268 + infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  269 + List<String> agentParam = new ArrayList<>();
  270 + agentParam.add("wvp-pro");
  271 + // TODO 添加版本信息以及日期
  272 + UserAgentHeader userAgentHeader = null;
  273 + try {
  274 + userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
  275 + } catch (ParseException e) {
  276 + throw new RuntimeException(e);
  277 + }
  278 + infoRequest.addHeader(userAgentHeader);
274 279  
275 280 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application",
276 281 "MANSRTSP");
277   - request.setContent(content, contentTypeHeader);
278   - return request;
  282 + infoRequest.setContent(content, contentTypeHeader);
  283 +
  284 + CSeqHeader cSeqHeader = (CSeqHeader)infoRequest.getHeader(CSeqHeader.NAME);
  285 + cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
  286 + // ceq
  287 + infoRequest.addHeader(cSeqHeader);
  288 + return infoRequest;
279 289 }
280 290 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -732,8 +732,23 @@ public class SIPCommander implements ISIPCommander {
732 732 SIPRequest request = (SIPRequest)transaction.getRequest();
733 733 byeURI.setHost(request.getRemoteAddress().getHostAddress());
734 734 byeURI.setPort(request.getRemotePort());
  735 + byeURI.setUser(channelId);
735 736 ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
736 737 String protocol = viaHeader.getTransport().toUpperCase();
  738 + viaHeader.setRPort();
  739 + // 增加Contact header
  740 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
  741 + byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  742 + List<String> agentParam = new ArrayList<>();
  743 + agentParam.add("wvp-pro");
  744 + // TODO 添加版本信息以及日期
  745 + UserAgentHeader userAgentHeader = null;
  746 + try {
  747 + userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
  748 + } catch (ParseException e) {
  749 + throw new RuntimeException(e);
  750 + }
  751 + byeRequest.addHeader(userAgentHeader);
737 752 ClientTransaction clientTransaction = null;
738 753 if("TCP".equals(protocol)) {
739 754 clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
... ... @@ -745,11 +760,14 @@ public class SIPCommander implements ISIPCommander {
745 760 if (okEvent != null) {
746 761 sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);
747 762 }
748   -
  763 + CSeqHeader cSeqHeader = (CSeqHeader)byeRequest.getHeader(CSeqHeader.NAME);
  764 + cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
749 765 dialog.sendRequest(clientTransaction);
750 766  
751 767 } catch (SipException | ParseException e) {
752 768 e.printStackTrace();
  769 + } catch (InvalidArgumentException e) {
  770 + throw new RuntimeException(e);
753 771 }
754 772 }
755 773  
... ... @@ -1483,7 +1501,7 @@ public class SIPCommander implements ISIPCommander {
1483 1501 request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
1484 1502  
1485 1503 CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
1486   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ(Request.SUBSCRIBE));
  1504 + cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
1487 1505 request.removeHeader(CSeqHeader.NAME);
1488 1506 request.addHeader(cSeqHeader);
1489 1507 }else {
... ... @@ -1587,7 +1605,7 @@ public class SIPCommander implements ISIPCommander {
1587 1605 request.setContent(cmdXml.toString(), contentTypeHeader);
1588 1606  
1589 1607 CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME);
1590   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ(Request.SUBSCRIBE));
  1608 + cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
1591 1609 request.removeHeader(CSeqHeader.NAME);
1592 1610 request.addHeader(cSeqHeader);
1593 1611  
... ... @@ -1697,10 +1715,9 @@ public class SIPCommander implements ISIPCommander {
1697 1715 @Override
1698 1716 public void playPauseCmd(Device device, StreamInfo streamInfo) {
1699 1717 try {
1700   - Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1701 1718 StringBuffer content = new StringBuffer(200);
1702 1719 content.append("PAUSE RTSP/1.0\r\n");
1703   - content.append("CSeq: " + cseq + "\r\n");
  1720 + content.append("CSeq: " + getInfoCseq() + "\r\n");
1704 1721 content.append("PauseTime: now\r\n");
1705 1722 Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1706 1723 if (request == null) {
... ... @@ -1728,10 +1745,9 @@ public class SIPCommander implements ISIPCommander {
1728 1745 @Override
1729 1746 public void playResumeCmd(Device device, StreamInfo streamInfo) {
1730 1747 try {
1731   - Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1732 1748 StringBuffer content = new StringBuffer(200);
1733 1749 content.append("PLAY RTSP/1.0\r\n");
1734   - content.append("CSeq: " + cseq + "\r\n");
  1750 + content.append("CSeq: " + getInfoCseq() + "\r\n");
1735 1751 content.append("Range: npt=now-\r\n");
1736 1752 Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1737 1753 if (request == null) {
... ... @@ -1758,10 +1774,9 @@ public class SIPCommander implements ISIPCommander {
1758 1774 @Override
1759 1775 public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) {
1760 1776 try {
1761   - Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1762 1777 StringBuffer content = new StringBuffer(200);
1763 1778 content.append("PLAY RTSP/1.0\r\n");
1764   - content.append("CSeq: " + cseq + "\r\n");
  1779 + content.append("CSeq: " + getInfoCseq() + "\r\n");
1765 1780 content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
1766 1781  
1767 1782 Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
... ... @@ -1789,11 +1804,11 @@ public class SIPCommander implements ISIPCommander {
1789 1804 @Override
1790 1805 public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) {
1791 1806 try {
1792   - Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
  1807 +
1793 1808 StringBuffer content = new StringBuffer(200);
1794 1809 content.append("PLAY RTSP/1.0\r\n");
1795   - content.append("CSeq: " + cseq + "\r\n");
1796   - content.append("Scale: " + String.format("%.1f",speed) + "\r\n");
  1810 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1811 + content.append("Scale: " + String.format("%.6f",speed) + "\r\n");
1797 1812 Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1798 1813 if (request == null) {
1799 1814 return;
... ... @@ -1812,6 +1827,10 @@ public class SIPCommander implements ISIPCommander {
1812 1827 e.printStackTrace();
1813 1828 }
1814 1829 }
  1830 +
  1831 + private int getInfoCseq() {
  1832 + return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8));
  1833 + }
1815 1834  
1816 1835 @Override
1817 1836 public void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) {
... ... @@ -1820,7 +1839,6 @@ public class SIPCommander implements ISIPCommander {
1820 1839 if (request == null) {
1821 1840 return;
1822 1841 }
1823   - logger.info(request.toString());
1824 1842 ClientTransaction clientTransaction = null;
1825 1843 if ("TCP".equals(device.getTransport())) {
1826 1844 clientTransaction = tcpSipProvider.getNewClientTransaction(request);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -105,7 +105,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
105 105 }
106 106  
107 107 request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform,
108   - redisCatchStorage.getCSEQ(Request.REGISTER), "FromRegister" + tm,
  108 + redisCatchStorage.getCSEQ(), "FromRegister" + tm,
109 109 "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), callIdHeader);
110 110 // 将 callid 写入缓存, 等注册成功可以更新状态
111 111 String callIdFromHeader = callIdHeader.getCallId();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
... ... @@ -2,24 +2,32 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
4 4 import com.genersoft.iot.vmp.gb28181.SipLayer;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
5 6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
7 8 import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
8 9 import gov.nist.javax.sip.ResponseEventExt;
  10 +import gov.nist.javax.sip.message.SIPResponse;
9 11 import gov.nist.javax.sip.stack.SIPDialog;
10 12 import org.slf4j.Logger;
11 13 import org.slf4j.LoggerFactory;
12 14 import org.springframework.beans.factory.annotation.Autowired;
13 15 import org.springframework.stereotype.Component;
14 16  
15   -import javax.sip.InvalidArgumentException;
16   -import javax.sip.ResponseEvent;
17   -import javax.sip.SipException;
  17 +import javax.sdp.SdpFactory;
  18 +import javax.sdp.SdpParseException;
  19 +import javax.sdp.SessionDescription;
  20 +import javax.sip.*;
  21 +import javax.sip.address.Address;
18 22 import javax.sip.address.SipURI;
19 23 import javax.sip.header.CSeqHeader;
  24 +import javax.sip.header.CallIdHeader;
  25 +import javax.sip.header.UserAgentHeader;
20 26 import javax.sip.message.Request;
21 27 import javax.sip.message.Response;
22 28 import java.text.ParseException;
  29 +import java.util.ArrayList;
  30 +import java.util.List;
23 31  
24 32  
25 33 /**
... ... @@ -34,14 +42,16 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
34 42 private final String method = "INVITE";
35 43  
36 44 @Autowired
37   - private SipLayer sipLayer;
  45 + private VideoStreamSessionManager streamSession;
38 46  
39 47 @Autowired
40   - private SipConfig config;
  48 + private SIPProcessorObserver sipProcessorObserver;
41 49  
  50 + @Autowired
  51 + private SipConfig sipConfig;
42 52  
43 53 @Autowired
44   - private SIPProcessorObserver sipProcessorObserver;
  54 + private SipFactory sipFactory;
45 55  
46 56 @Override
47 57 public void afterPropertiesSet() throws Exception {
... ... @@ -49,8 +59,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
49 59 sipProcessorObserver.addResponseProcessor(method, this);
50 60 }
51 61  
52   - @Autowired
53   - private VideoStreamSessionManager streamSession;
  62 +
54 63  
55 64 /**
56 65 * 处理invite响应
... ... @@ -74,6 +83,19 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
74 83 CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
75 84 Request reqAck = dialog.createAck(cseq.getSeqNumber());
76 85 SipURI requestURI = (SipURI) reqAck.getRequestURI();
  86 + String contentString = new String(response.getRawContent());
  87 + // jainSip不支持y=字段, 移除以解析。
  88 + int ssrcIndex = contentString.indexOf("y=");
  89 + // 检查是否有y字段
  90 + SessionDescription sdp;
  91 + if (ssrcIndex >= 0) {
  92 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
  93 + String substring = contentString.substring(0, contentString.indexOf("y="));
  94 + sdp = SdpFactory.getInstance().createSessionDescription(substring);
  95 + } else {
  96 + sdp = SdpFactory.getInstance().createSessionDescription(contentString);
  97 + }
  98 + requestURI.setUser(sdp.getOrigin().getUsername());
77 99 try {
78 100 requestURI.setHost(event.getRemoteIpAddress());
79 101 } catch (ParseException e) {
... ... @@ -81,6 +103,18 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
81 103 }
82 104 requestURI.setPort(event.getRemotePort());
83 105 reqAck.setRequestURI(requestURI);
  106 + List<String> agentParam = new ArrayList<>();
  107 + agentParam.add("wvp-pro");
  108 + // TODO 添加版本信息以及日期
  109 + UserAgentHeader userAgentHeader = null;
  110 + try {
  111 + userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
  112 + } catch (ParseException e) {
  113 + throw new RuntimeException(e);
  114 + }
  115 + reqAck.addHeader(userAgentHeader);
  116 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
  117 + reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
84 118 logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
85 119  
86 120 dialog.sendAck(reqAck);
... ... @@ -88,6 +122,10 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
88 122 }
89 123 } catch (InvalidArgumentException | SipException e) {
90 124 e.printStackTrace();
  125 + } catch (ParseException e) {
  126 + throw new RuntimeException(e);
  127 + } catch (SdpParseException e) {
  128 + throw new RuntimeException(e);
91 129 }
92 130 }
93 131  
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -98,9 +98,7 @@ public class ZLMHttpHookListener {
98 98 @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
99 99 public ResponseEntity<String> onServerKeepalive(@RequestBody JSONObject json){
100 100  
101   - if (logger.isDebugEnabled()) {
102   - logger.debug("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString());
103   - }
  101 + logger.info("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString());
104 102 String mediaServerId = json.getString("mediaServerId");
105 103 List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
106 104 if (subscribes != null && subscribes.size() > 0) {
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
... ... @@ -277,13 +277,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
277 277 return null;
278 278 }
279 279 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
280   - MediaServerItem serverItem=(MediaServerItem)redisUtil.get(key);
281   - if(null==serverItem){
282   - //zlm服务不在线,启动重连
283   - reloadZlm();
284   - serverItem=(MediaServerItem)redisUtil.get(key);
285   - }
286   - return serverItem;
  280 + return (MediaServerItem)redisUtil.get(key);
287 281 }
288 282  
289 283 @Override
... ... @@ -412,7 +406,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
412 406 }
413 407 redisUtil.set(key, serverItem);
414 408 resetOnlineServerItem(serverItem);
415   - updateMediaServerKeepalive(serverItem.getId(), null);
416 409 if (serverItem.isAutoConfig()) {
417 410 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
418 411 }
... ... @@ -476,9 +469,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
476 469 String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
477 470  
478 471 if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
479   - logger.info("获取负载最低的节点时无在线节点,启动重连机制");
480   - //启动重连
481   - reloadZlm();
482 472 if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
483 473 logger.info("获取负载最低的节点时无在线节点");
484 474 return null;
... ... @@ -643,6 +633,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
643 633 public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) {
644 634 MediaServerItem mediaServerItem = getOne(mediaServerId);
645 635 if (mediaServerItem == null) {
  636 + // 缓存不存在,从数据库查询,如果数据库不存在则是错误的
  637 + MediaServerItem mediaServerItemFromDatabase = getOneFromDatabase(mediaServerId);
  638 + if (mediaServerItemFromDatabase == null) {
  639 + return;
  640 + }
646 641 // zlm连接重试
647 642 logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息,尝试重连zlm");
648 643 reloadZlm();
... ... @@ -658,6 +653,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
658 653 redisUtil.set(key, data, hookAliveInterval);
659 654 }
660 655  
  656 + private MediaServerItem getOneFromDatabase(String mediaServerId) {
  657 + return mediaServerMapper.queryOne(mediaServerId);
  658 + }
  659 +
661 660 @Override
662 661 public void syncCatchFromDatabase() {
663 662 List<MediaServerItem> allInCatch = getAll();
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -17,10 +17,9 @@ public interface IRedisCatchStorage {
17 17 /**
18 18 * 计数器。为cseq进行计数
19 19 *
20   - * @param method sip 方法
21 20 * @return
22 21 */
23   - Long getCSEQ(String method);
  22 + Long getCSEQ();
24 23  
25 24 /**
26 25 * 开始播放时将流存入
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -42,8 +42,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
42 42 private UserSetting userSetting;
43 43  
44 44 @Override
45   - public Long getCSEQ(String method) {
46   - String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId() + "_" + method;
  45 + public Long getCSEQ() {
  46 + String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId();
47 47  
48 48 long result = redis.incr(key, 1L);
49 49 if (result > Integer.MAX_VALUE) {
... ...