Commit 503f891c9e443551309a91b38493ac49413dbe35

Authored by panlinlin
1 parent cf8a22f5

完成向上级联->点播--增加了sdp解析

修复修改平台主键带来的bug
Showing 21 changed files with 976 additions and 81 deletions
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -28,6 +28,8 @@ public class VideoManagerConstants { @@ -28,6 +28,8 @@ public class VideoManagerConstants {
28 28
29 public static final String PLATFORM_REGISTER_PREFIX = "VMP_platform_register_"; 29 public static final String PLATFORM_REGISTER_PREFIX = "VMP_platform_register_";
30 30
  31 + public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_platform_register_info_";
  32 +
31 public static final String Pattern_Topic = "VMP_keeplive_platform_"; 33 public static final String Pattern_Topic = "VMP_keeplive_platform_";
32 34
33 public static final String EVENT_ONLINE_REGISTER = "1"; 35 public static final String EVENT_ONLINE_REGISTER = "1";
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
@@ -45,11 +45,11 @@ public class SipPlatformRunner implements CommandLineRunner { @@ -45,11 +45,11 @@ public class SipPlatformRunner implements CommandLineRunner {
45 ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); 45 ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch();
46 46
47 parentPlatformCatch.setParentPlatform(parentPlatform); 47 parentPlatformCatch.setParentPlatform(parentPlatform);
48 - parentPlatformCatch.setId(parentPlatform.getDeviceGBId()); 48 + parentPlatformCatch.setId(parentPlatform.getServerGBId());
49 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); 49 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
50 50
51 // 发送平台未注册消息 51 // 发送平台未注册消息
52 - publisher.platformNotRegisterEventPublish(parentPlatform.getDeviceGBId()); 52 + publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId());
53 } 53 }
54 } 54 }
55 } 55 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
@@ -10,6 +10,8 @@ public class ParentPlatformCatch { @@ -10,6 +10,8 @@ public class ParentPlatformCatch {
10 // 注册未回复次数 10 // 注册未回复次数
11 private int registerAliveReply; 11 private int registerAliveReply;
12 12
  13 + private String callId;
  14 +
13 private ParentPlatform parentPlatform; 15 private ParentPlatform parentPlatform;
14 16
15 public String getId() { 17 public String getId() {
@@ -43,4 +45,12 @@ public class ParentPlatformCatch { @@ -43,4 +45,12 @@ public class ParentPlatformCatch {
43 public void setParentPlatform(ParentPlatform parentPlatform) { 45 public void setParentPlatform(ParentPlatform parentPlatform) {
44 this.parentPlatform = parentPlatform; 46 this.parentPlatform = parentPlatform;
45 } 47 }
  48 +
  49 + public String getCallId() {
  50 + return callId;
  51 + }
  52 +
  53 + public void setCallId(String callId) {
  54 + this.callId = callId;
  55 + }
46 } 56 }
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/Codec.java 0 → 100755
  1 +/*
  2 + This file is part of Peers, a java SIP softphone.
  3 +
  4 + This program is free software: you can redistribute it and/or modify
  5 + it under the terms of the GNU General Public License as published by
  6 + the Free Software Foundation, either version 3 of the License, or
  7 + any later version.
  8 +
  9 + This program is distributed in the hope that it will be useful,
  10 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + GNU General Public License for more details.
  13 +
  14 + You should have received a copy of the GNU General Public License
  15 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 + Copyright 2010 Yohann Martineau
  18 +*/
  19 +
  20 +package com.genersoft.iot.vmp.gb28181.sdp;
  21 +
  22 +public class Codec {
  23 +
  24 + private int payloadType;
  25 + private String name;
  26 +
  27 + public int getPayloadType() {
  28 + return payloadType;
  29 + }
  30 +
  31 + public void setPayloadType(int payloadType) {
  32 + this.payloadType = payloadType;
  33 + }
  34 +
  35 + public String getName() {
  36 + return name;
  37 + }
  38 +
  39 + public void setName(String name) {
  40 + this.name = name;
  41 + }
  42 +
  43 + @Override
  44 + public boolean equals(Object obj) {
  45 + if (!(obj instanceof Codec)) {
  46 + return false;
  47 + }
  48 + Codec codec = (Codec)obj;
  49 + if (codec.getName() == null) {
  50 + return name == null;
  51 + }
  52 + return codec.getName().equalsIgnoreCase(name);
  53 + }
  54 +
  55 + @Override
  56 + public String toString() {
  57 + StringBuffer buf = new StringBuffer();
  58 + buf.append(RFC4566_28181.TYPE_ATTRIBUTE).append(RFC4566_28181.SEPARATOR);
  59 + buf.append(RFC4566_28181.ATTR_RTPMAP).append(RFC4566_28181.ATTR_SEPARATOR);
  60 + buf.append(payloadType).append(" ").append(name).append("/");
  61 + buf.append(9000).append("\r\n");
  62 + return buf.toString();
  63 + }
  64 +
  65 +}
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/MediaDescription.java 0 → 100755
  1 +/*
  2 + This file is part of Peers, a java SIP softphone.
  3 +
  4 + This program is free software: you can redistribute it and/or modify
  5 + it under the terms of the GNU General Public License as published by
  6 + the Free Software Foundation, either version 3 of the License, or
  7 + any later version.
  8 +
  9 + This program is distributed in the hope that it will be useful,
  10 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + GNU General Public License for more details.
  13 +
  14 + You should have received a copy of the GNU General Public License
  15 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 + Copyright 2007, 2008, 2009, 2010 Yohann Martineau
  18 + */
  19 +
  20 +package com.genersoft.iot.vmp.gb28181.sdp;
  21 +
  22 +import java.net.Inet4Address;
  23 +import java.net.Inet6Address;
  24 +import java.net.InetAddress;
  25 +import java.util.Hashtable;
  26 +import java.util.List;
  27 +
  28 +public class MediaDescription {
  29 +
  30 + private String type;
  31 + private InetAddress ipAddress;
  32 + // attributes not codec-related
  33 + private Hashtable<String, String> attributes;
  34 + private int port;
  35 + private List<Codec> codecs;
  36 +
  37 + public String getType() {
  38 + return type;
  39 + }
  40 +
  41 + public void setType(String type) {
  42 + this.type = type;
  43 + }
  44 +
  45 + public Hashtable<String, String> getAttributes() {
  46 + return attributes;
  47 + }
  48 +
  49 + public void setAttributes(Hashtable<String, String> attributes) {
  50 + this.attributes = attributes;
  51 + }
  52 +
  53 + public InetAddress getIpAddress() {
  54 + return ipAddress;
  55 + }
  56 +
  57 + public void setIpAddress(InetAddress ipAddress) {
  58 + this.ipAddress = ipAddress;
  59 + }
  60 +
  61 + public int getPort() {
  62 + return port;
  63 + }
  64 +
  65 + public void setPort(int port) {
  66 + this.port = port;
  67 + }
  68 +
  69 + public List<Codec> getCodecs() {
  70 + return codecs;
  71 + }
  72 +
  73 + public void setCodecs(List<Codec> codecs) {
  74 + this.codecs = codecs;
  75 + }
  76 +
  77 + @Override
  78 + public String toString() {
  79 + StringBuffer buf = new StringBuffer();
  80 + buf.append(RFC4566_28181.TYPE_MEDIA).append(RFC4566_28181.SEPARATOR);
  81 + buf.append(type).append(" ").append(port);
  82 + buf.append(" RTP/AVP");
  83 + if (codecs != null) {
  84 + for (Codec codec: codecs) {
  85 + buf.append(" ");
  86 + buf.append(codec.getPayloadType());
  87 + }
  88 + buf.append("\r\n");
  89 + }
  90 + if (ipAddress != null) {
  91 + int ipVersion;
  92 + if (ipAddress instanceof Inet4Address) {
  93 + ipVersion = 4;
  94 + } else if (ipAddress instanceof Inet6Address) {
  95 + ipVersion = 6;
  96 + } else {
  97 + throw new RuntimeException("unknown ip version: " + ipAddress);
  98 + }
  99 + buf.append(RFC4566_28181.TYPE_CONNECTION).append(RFC4566_28181.SEPARATOR);
  100 + buf.append("IN IP").append(ipVersion).append(" ");
  101 + buf.append(ipAddress.getHostAddress()).append("\r\n");
  102 + }
  103 + if (codecs != null) {
  104 + for (Codec codec: codecs) {
  105 + buf.append(codec.toString());
  106 + }
  107 + }
  108 +
  109 + if (attributes != null) {
  110 + for (String attributeName: attributes.keySet()) {
  111 + buf.append(RFC4566_28181.TYPE_ATTRIBUTE).append(RFC4566_28181.SEPARATOR);
  112 + buf.append(attributeName);
  113 + String attributeValue = attributes.get(attributeName);
  114 + if (attributeValue != null && !"".equals(attributeValue.trim())) {
  115 + buf.append(":").append(attributeValue);
  116 + }
  117 + buf.append("\r\n");
  118 + }
  119 + }
  120 + return buf.toString();
  121 + }
  122 +
  123 +}
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/RFC4566_28181.java 0 → 100755
  1 +/*
  2 + This file is part of Peers, a java SIP softphone.
  3 +
  4 + This program is free software: you can redistribute it and/or modify
  5 + it under the terms of the GNU General Public License as published by
  6 + the Free Software Foundation, either version 3 of the License, or
  7 + any later version.
  8 +
  9 + This program is distributed in the hope that it will be useful,
  10 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + GNU General Public License for more details.
  13 +
  14 + You should have received a copy of the GNU General Public License
  15 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 + Copyright 2007, 2008, 2009, 2010 Yohann Martineau
  18 +*/
  19 +
  20 +package com.genersoft.iot.vmp.gb28181.sdp;
  21 +
  22 +public class RFC4566_28181 {
  23 +
  24 + public static final char VERSION = '0';
  25 +
  26 + public static final char TYPE_VERSION = 'v';
  27 + public static final char TYPE_ORIGIN = 'o';
  28 + public static final char TYPE_SUBJECT = 's';
  29 + public static final char TYPE_INFO = 'i';
  30 + public static final char TYPE_URI = 'u';
  31 + public static final char TYPE_EMAIL = 'e';
  32 + public static final char TYPE_PHONE = 'p';
  33 + public static final char TYPE_CONNECTION = 'c';
  34 + public static final char TYPE_BANDWITH = 'b';
  35 + public static final char TYPE_TIME = 't';
  36 + public static final char TYPE_REPEAT = 'r';
  37 + public static final char TYPE_ZONE = 'z';
  38 + public static final char TYPE_KEY = 'k';
  39 + public static final char TYPE_ATTRIBUTE = 'a';
  40 + public static final char TYPE_MEDIA = 'm';
  41 + public static final char TYPE_SSRC = 'y';
  42 + public static final char TYPE_MEDIA_DES = 'f';
  43 +
  44 + public static final char SEPARATOR = '=';
  45 + public static final char ATTR_SEPARATOR = ':';
  46 +
  47 + public static final String MEDIA_AUDIO = "audio";
  48 +
  49 + public static final String ATTR_RTPMAP = "rtpmap";
  50 + public static final String ATTR_SENDRECV = "sendrecv";
  51 +}
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/SdpLine.java 0 → 100755
  1 +/*
  2 + This file is part of Peers, a java SIP softphone.
  3 +
  4 + This program is free software: you can redistribute it and/or modify
  5 + it under the terms of the GNU General Public License as published by
  6 + the Free Software Foundation, either version 3 of the License, or
  7 + any later version.
  8 +
  9 + This program is distributed in the hope that it will be useful,
  10 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + GNU General Public License for more details.
  13 +
  14 + You should have received a copy of the GNU General Public License
  15 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 + Copyright 2007, 2008, 2009, 2010 Yohann Martineau
  18 +*/
  19 +
  20 +package com.genersoft.iot.vmp.gb28181.sdp;
  21 +
  22 +public class SdpLine {
  23 + private char type;
  24 + private String value;
  25 + public char getType() {
  26 + return type;
  27 + }
  28 + public void setType(char type) {
  29 + this.type = type;
  30 + }
  31 + public String getValue() {
  32 + return value;
  33 + }
  34 + public void setValue(String value) {
  35 + this.value = value;
  36 + }
  37 +
  38 +}
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/SdpParser.java 0 → 100755
  1 +/*
  2 + This file is part of Peers, a java SIP softphone.
  3 +
  4 + This program is free software: you can redistribute it and/or modify
  5 + it under the terms of the GNU General Public License as published by
  6 + the Free Software Foundation, either version 3 of the License, or
  7 + any later version.
  8 +
  9 + This program is distributed in the hope that it will be useful,
  10 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + GNU General Public License for more details.
  13 +
  14 + You should have received a copy of the GNU General Public License
  15 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 + Copyright 2007, 2008, 2009, 2010 Yohann Martineau
  18 +*/
  19 +
  20 +package com.genersoft.iot.vmp.gb28181.sdp;
  21 +
  22 +import java.io.BufferedReader;
  23 +import java.io.ByteArrayInputStream;
  24 +import java.io.IOException;
  25 +import java.io.InputStreamReader;
  26 +import java.net.InetAddress;
  27 +import java.util.ArrayList;
  28 +import java.util.Hashtable;
  29 +import java.util.List;
  30 +
  31 +public class SdpParser {
  32 +
  33 + public SessionDescription parse(byte[] body) throws IOException {
  34 + if (body == null || body.length == 0) {
  35 + return null;
  36 + }
  37 + ByteArrayInputStream in = new ByteArrayInputStream(body);
  38 + InputStreamReader inputStreamReader = new InputStreamReader(in);
  39 + BufferedReader reader = new BufferedReader(inputStreamReader);
  40 + SessionDescription sessionDescription = new SessionDescription();
  41 +
  42 + //version
  43 +
  44 + String line = reader.readLine();
  45 + if (line.length() < 3) {
  46 + return null;
  47 + }
  48 + if (line.charAt(0) != RFC4566_28181.TYPE_VERSION
  49 + || line.charAt(1) != RFC4566_28181.SEPARATOR
  50 + || line.charAt(2) != RFC4566_28181.VERSION) {
  51 + return null;
  52 + }
  53 +
  54 + //origin
  55 +
  56 + line = reader.readLine();
  57 + if (line.length() < 3) {
  58 + return null;
  59 + }
  60 + if (line.charAt(0) != RFC4566_28181.TYPE_ORIGIN
  61 + || line.charAt(1) != RFC4566_28181.SEPARATOR) {
  62 + return null;
  63 + }
  64 + line = line.substring(2);
  65 + String[] originArr = line.split(" ");
  66 + if (originArr == null || originArr.length != 6) {
  67 + return null;
  68 + }
  69 + sessionDescription.setUsername(originArr[0]);
  70 + sessionDescription.setId(Long.parseLong(originArr[1]));
  71 + sessionDescription.setVersion(Long.parseLong(originArr[2]));
  72 + sessionDescription.setIpAddress(InetAddress.getByName(originArr[5]));
  73 +
  74 + //name
  75 +
  76 + line = reader.readLine();
  77 + if (line.length() < 3) {
  78 + return null;
  79 + }
  80 + if (line.charAt(0) != RFC4566_28181.TYPE_SUBJECT
  81 + || line.charAt(1) != RFC4566_28181.SEPARATOR) {
  82 + return null;
  83 + }
  84 + sessionDescription.setName(line.substring(2));
  85 +
  86 + //session connection and attributes
  87 + Hashtable<String, String> sessionAttributes = new Hashtable<String, String>();
  88 + sessionDescription.setAttributes(sessionAttributes);
  89 +
  90 + while ((line = reader.readLine()) != null
  91 + && line.charAt(0) != RFC4566_28181.TYPE_MEDIA) {
  92 + if (line.length() > 3
  93 + && line.charAt(0) == RFC4566_28181.TYPE_CONNECTION
  94 + && line.charAt(1) == RFC4566_28181.SEPARATOR) {
  95 + String connection = parseConnection(line.substring(2));
  96 + if (connection == null) {
  97 + continue;
  98 + }
  99 + sessionDescription.setIpAddress(InetAddress.getByName(connection));
  100 + } else if (line.length() > 3
  101 + && line.charAt(0) == RFC4566_28181.TYPE_ATTRIBUTE
  102 + && line.charAt(1) == RFC4566_28181.SEPARATOR) {
  103 + String value = line.substring(2);
  104 + int pos = value.indexOf(RFC4566_28181.ATTR_SEPARATOR);
  105 + if (pos > -1) {
  106 + sessionAttributes.put(value.substring(0, pos),
  107 + value.substring(pos + 1));
  108 + } else {
  109 + sessionAttributes.put(value, "");
  110 + }
  111 + }
  112 + }
  113 + if (line == null) {
  114 + return null;
  115 + }
  116 + //we are at the first media line
  117 +
  118 + ArrayList<SdpLine> mediaLines = new ArrayList<SdpLine>();
  119 + do {
  120 + if (line.length() < 2) {
  121 + return null;
  122 + }
  123 + if (line.charAt(1) != RFC4566_28181.SEPARATOR) {
  124 + return null;
  125 + }
  126 + if (line.charAt(0) == RFC4566_28181.TYPE_SSRC) {
  127 + sessionDescription.setSsrc(line.length() >=2 ?line.substring(2):"");
  128 + }else if (line.charAt(0) == RFC4566_28181.TYPE_MEDIA_DES) {
  129 + sessionDescription.setGbMediaDescriptions(line.length() >=2 ?line.substring(2):"");
  130 + }else {
  131 + SdpLine mediaLine = new SdpLine();
  132 + mediaLine.setType(line.charAt(0));
  133 + mediaLine.setValue(line.substring(2));
  134 + mediaLines.add(mediaLine);
  135 + }
  136 +
  137 + }
  138 + while ((line = reader.readLine()) != null );
  139 +
  140 + ArrayList<MediaDescription> mediaDescriptions = new ArrayList<MediaDescription>();
  141 + sessionDescription.setMediaDescriptions(mediaDescriptions);
  142 +
  143 + for (SdpLine sdpLine : mediaLines) {
  144 + MediaDescription mediaDescription;
  145 + if (sdpLine.getType() == RFC4566_28181.TYPE_MEDIA) {
  146 + String[] mediaArr = sdpLine.getValue().split(" ");
  147 + if (mediaArr == null || mediaArr.length < 4) {
  148 + return null;
  149 + }
  150 + mediaDescription = new MediaDescription();
  151 + mediaDescription.setType(mediaArr[0]);
  152 + //TODO manage port range
  153 + mediaDescription.setPort(Integer.parseInt(mediaArr[1]));
  154 + mediaDescription.setAttributes(new Hashtable<String, String>());
  155 + List<Codec> codecs = new ArrayList<Codec>();
  156 + for (int i = 3; i < mediaArr.length; ++i) {
  157 + int payloadType = Integer.parseInt(mediaArr[i]);
  158 + Codec codec = new Codec();
  159 + codec.setPayloadType(payloadType);
  160 + codec.setName("unsupported");
  161 + codecs.add(codec);
  162 + }
  163 + mediaDescription.setCodecs(codecs);
  164 + mediaDescriptions.add(mediaDescription);
  165 + } else {
  166 + mediaDescription = mediaDescriptions.get(mediaDescriptions.size() - 1);
  167 + String sdpLineValue = sdpLine.getValue();
  168 + if (sdpLine.getType() == RFC4566_28181.TYPE_CONNECTION) {
  169 + String ipAddress = parseConnection(sdpLineValue);
  170 + mediaDescription.setIpAddress(InetAddress.getByName(ipAddress));
  171 + } else if (sdpLine.getType() == RFC4566_28181.TYPE_ATTRIBUTE) {
  172 + Hashtable<String, String> attributes = mediaDescription.getAttributes();
  173 + int pos = sdpLineValue.indexOf(RFC4566_28181.ATTR_SEPARATOR);
  174 + if (pos > -1) {
  175 + String name = sdpLineValue.substring(0, pos);
  176 + String value = sdpLineValue.substring(pos + 1);
  177 + pos = value.indexOf(" ");
  178 + if (pos > -1) {
  179 + int payloadType;
  180 + try {
  181 + payloadType = Integer.parseInt(value.substring(0, pos));
  182 + List<Codec> codecs = mediaDescription.getCodecs();
  183 + for (Codec codec: codecs) {
  184 + if (codec.getPayloadType() == payloadType) {
  185 + value = value.substring(pos + 1);
  186 + pos = value.indexOf("/");
  187 + if (pos > -1) {
  188 + value = value.substring(0, pos);
  189 + codec.setName(value);
  190 + }
  191 + break;
  192 + }
  193 + }
  194 + } catch (NumberFormatException e) {
  195 + attributes.put(name, value);
  196 + }
  197 + } else {
  198 + attributes.put(name, value);
  199 + }
  200 + } else {
  201 + attributes.put(sdpLineValue, "");
  202 + }
  203 + }
  204 + }
  205 + }
  206 + sessionDescription.setMediaDescriptions(mediaDescriptions);
  207 +
  208 + for (MediaDescription description : mediaDescriptions) {
  209 + if (description.getIpAddress() == null) {
  210 + InetAddress sessionAddress = sessionDescription.getIpAddress();
  211 + if (sessionAddress == null) {
  212 + return null;
  213 + }
  214 + description.setIpAddress(sessionAddress);
  215 + }
  216 + }
  217 +
  218 +
  219 + return sessionDescription;
  220 + }
  221 +
  222 + private String parseConnection(String line) {
  223 + String[] connectionArr = line.split(" ");
  224 + if (connectionArr == null || connectionArr.length != 3) {
  225 + return null;
  226 + }
  227 + return connectionArr[2];
  228 + }
  229 +
  230 +}
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/SessionDescription.java 0 → 100755
  1 +/*
  2 + This file is part of Peers, a java SIP softphone.
  3 +
  4 + This program is free software: you can redistribute it and/or modify
  5 + it under the terms of the GNU General Public License as published by
  6 + the Free Software Foundation, either version 3 of the License, or
  7 + any later version.
  8 +
  9 + This program is distributed in the hope that it will be useful,
  10 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + GNU General Public License for more details.
  13 +
  14 + You should have received a copy of the GNU General Public License
  15 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 + Copyright 2007, 2008, 2009, 2010 Yohann Martineau
  18 +*/
  19 +
  20 +package com.genersoft.iot.vmp.gb28181.sdp;
  21 +
  22 +import java.net.Inet4Address;
  23 +import java.net.Inet6Address;
  24 +import java.net.InetAddress;
  25 +import java.util.Hashtable;
  26 +import java.util.List;
  27 +
  28 +public class SessionDescription {
  29 +
  30 + private long id;
  31 + private long version;
  32 + private String name;
  33 + private String username;
  34 + private InetAddress ipAddress;
  35 + private List<MediaDescription> mediaDescriptions;
  36 + private Hashtable<String, String> attributes;
  37 + private String ssrc;
  38 + private String gbMediaDescriptions;
  39 +
  40 + public SessionDescription() {
  41 + }
  42 +
  43 + public long getId() {
  44 + return id;
  45 + }
  46 +
  47 + public void setId(long id) {
  48 + this.id = id;
  49 + }
  50 +
  51 + public InetAddress getIpAddress() {
  52 + return ipAddress;
  53 + }
  54 +
  55 + public void setIpAddress(InetAddress ipAddress) {
  56 + this.ipAddress = ipAddress;
  57 + }
  58 +
  59 + public List<MediaDescription> getMediaDescriptions() {
  60 + return mediaDescriptions;
  61 + }
  62 +
  63 + public void setMediaDescriptions(List<MediaDescription> mediaDescriptions) {
  64 + this.mediaDescriptions = mediaDescriptions;
  65 + }
  66 +
  67 + public String getName() {
  68 + return name;
  69 + }
  70 +
  71 + public void setName(String name) {
  72 + this.name = name;
  73 + }
  74 +
  75 + public String getUsername() {
  76 + return username;
  77 + }
  78 +
  79 + public void setUsername(String username) {
  80 + this.username = username;
  81 + }
  82 +
  83 + public long getVersion() {
  84 + return version;
  85 + }
  86 +
  87 + public void setVersion(long version) {
  88 + this.version = version;
  89 + }
  90 +
  91 + public Hashtable<String, String> getAttributes() {
  92 + return attributes;
  93 + }
  94 +
  95 + public void setAttributes(Hashtable<String, String> attributes) {
  96 + this.attributes = attributes;
  97 + }
  98 +
  99 + public String getSsrc() {
  100 + return ssrc;
  101 + }
  102 +
  103 + public void setSsrc(String ssrc) {
  104 + this.ssrc = ssrc;
  105 + }
  106 +
  107 + public String getGbMediaDescriptions() {
  108 + return gbMediaDescriptions;
  109 + }
  110 +
  111 + public void setGbMediaDescriptions(String gbMediaDescriptions) {
  112 + this.gbMediaDescriptions = gbMediaDescriptions;
  113 + }
  114 +
  115 + @Override
  116 + public String toString() {
  117 + StringBuilder buf = new StringBuilder();
  118 + buf.append("v=0\r\n");
  119 + buf.append("o=").append(username).append(" ").append(id);
  120 + buf.append(" ").append(version);
  121 + int ipVersion;
  122 + if (ipAddress instanceof Inet4Address) {
  123 + ipVersion = 4;
  124 + } else if (ipAddress instanceof Inet6Address) {
  125 + ipVersion = 6;
  126 + } else {
  127 + throw new RuntimeException("unknown ip version: " + ipAddress);
  128 + }
  129 + buf.append(" IN IP").append(ipVersion).append(" ");
  130 + String hostAddress = ipAddress.getHostAddress();
  131 + buf.append(hostAddress).append("\r\n");
  132 + buf.append("s=").append(name).append("\r\n");
  133 + buf.append("c=IN IP").append(ipVersion).append(" ");
  134 + buf.append(hostAddress).append("\r\n");
  135 + buf.append("t=0 0\r\n");
  136 + if (attributes != null){
  137 + for (String attributeName: attributes.keySet()) {
  138 + String attributeValue = attributes.get(attributeName);
  139 + buf.append("a=").append(attributeName);
  140 + if (attributeValue != null && !"".equals(attributeValue.trim())) {
  141 + buf.append(":");
  142 + buf.append(attributeValue);
  143 + buf.append("\r\n");
  144 + }
  145 + }
  146 + }
  147 + if (mediaDescriptions != null){
  148 + for (MediaDescription mediaDescription: mediaDescriptions) {
  149 + buf.append(mediaDescription.toString());
  150 + }
  151 + }
  152 +
  153 + if (ssrc != null){
  154 + buf.append("y=").append(ssrc).append("\r\n");
  155 + }
  156 + if (gbMediaDescriptions != null){
  157 + buf.append("f=").append(gbMediaDescriptions).append("\r\n");
  158 + }
  159 + return buf.toString();
  160 + }
  161 +
  162 +}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -119,6 +119,9 @@ public class SIPProcessorFactory { @@ -119,6 +119,9 @@ public class SIPProcessorFactory {
119 processor.setRequestEvent(evt); 119 processor.setRequestEvent(evt);
120 processor.setTcpSipProvider(getTcpSipProvider()); 120 processor.setTcpSipProvider(getTcpSipProvider());
121 processor.setUdpSipProvider(getUdpSipProvider()); 121 processor.setUdpSipProvider(getUdpSipProvider());
  122 +
  123 + processor.setCmderFroPlatform(cmderFroPlatform);
  124 + processor.setStorager(storager);
122 return processor; 125 return processor;
123 } else if (Request.REGISTER.equals(method)) { 126 } else if (Request.REGISTER.equals(method)) {
124 RegisterRequestProcessor processor = new RegisterRequestProcessor(); 127 RegisterRequestProcessor processor = new RegisterRequestProcessor();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -70,7 +70,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -70,7 +70,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
70 @Override 70 @Override
71 public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { 71 public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
72 parentPlatform.setExpires("0"); 72 parentPlatform.setExpires("0");
73 - ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getDeviceGBId()); 73 + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
74 if (parentPlatformCatch != null) { 74 if (parentPlatformCatch != null) {
75 parentPlatformCatch.setParentPlatform(parentPlatform); 75 parentPlatformCatch.setParentPlatform(parentPlatform);
76 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); 76 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
@@ -86,11 +86,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -86,11 +86,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
86 86
87 if (www == null ) { 87 if (www == null ) {
88 request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, 1L, null, null); 88 request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, 1L, null, null);
  89 + // 将 callid 写入缓存, 等注册成功可以更新状态
  90 + CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
  91 + redisCatchStorage.updatePlatformRegisterInfo(callIdHeader.getCallId(), parentPlatform.getServerGBId());
  92 +
  93 + sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{
  94 + redisCatchStorage.delPlatformRegisterInfo(callIdHeader.getCallId());
  95 + if (errorEvent != null) {
  96 + errorEvent.response(event);
  97 + }
  98 + });
89 }else { 99 }else {
90 request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, null, null, callId, www); 100 request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, null, null, callId, www);
91 } 101 }
92 102
93 - transmitRequest(parentPlatform, request, errorEvent, okEvent); 103 + transmitRequest(parentPlatform, request, null, okEvent);
94 return true; 104 return true;
95 } catch (ParseException e) { 105 } catch (ParseException e) {
96 e.printStackTrace(); 106 e.printStackTrace();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.request.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
2 2
  3 +import javax.sip.InvalidArgumentException;
3 import javax.sip.RequestEvent; 4 import javax.sip.RequestEvent;
  5 +import javax.sip.SipException;
  6 +import javax.sip.address.SipURI;
  7 +import javax.sip.header.ContentTypeHeader;
  8 +import javax.sip.header.FromHeader;
  9 +import javax.sip.header.SubjectHeader;
  10 +import javax.sip.message.Request;
  11 +import javax.sip.message.Response;
4 12
  13 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  14 +import com.genersoft.iot.vmp.gb28181.sdp.Codec;
  15 +import com.genersoft.iot.vmp.gb28181.sdp.MediaDescription;
  16 +import com.genersoft.iot.vmp.gb28181.sdp.SdpParser;
  17 +import com.genersoft.iot.vmp.gb28181.sdp.SessionDescription;
  18 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  19 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
5 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; 20 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
  21 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  22 +import gov.nist.javax.sip.address.AddressImpl;
  23 +import gov.nist.javax.sip.address.SipUri;
  24 +import org.slf4j.Logger;
  25 +import org.slf4j.LoggerFactory;
  26 +
  27 +import java.io.IOException;
  28 +import java.text.ParseException;
  29 +import java.util.List;
6 30
7 /** 31 /**
8 * @Description:处理INVITE请求 32 * @Description:处理INVITE请求
9 - * @author: swwheihei  
10 - * @date: 2020年5月3日 下午4:43:52 33 + * @author: panll
  34 + * @date: 2021年1月14日
11 */ 35 */
12 public class InviteRequestProcessor extends SIPRequestAbstractProcessor { 36 public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
13 37
  38 + private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
  39 +
  40 + private SIPCommanderFroPlatform cmderFroPlatform;
  41 +
  42 + private IVideoManagerStorager storager;
  43 +
14 /** 44 /**
15 * 处理invite请求 45 * 处理invite请求
16 * 46 *
17 - * @param request 47 + * @param evt
18 * 请求消息 48 * 请求消息
19 */ 49 */
20 @Override 50 @Override
21 public void process(RequestEvent evt) { 51 public void process(RequestEvent evt) {
22 - // TODO 优先级99 Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令  
23 -// Request request = requestEvent.getRequest();  
24 -//  
25 -// try {  
26 -// // 发送100 Trying  
27 -// ServerTransaction serverTransaction = getServerTransaction(requestEvent);  
28 -// // 查询目标地址  
29 -// URI reqUri = request.getRequestURI();  
30 -// URI contactURI = currUser.get(reqUri);  
31 -//  
32 -// System.out.println("processInvite rqStr=" + reqUri + " contact=" + contactURI);  
33 -//  
34 -// // 根据Request uri来路由,后续的响应消息通过VIA来路由  
35 -// Request cliReq = messageFactory.createRequest(request.toString());  
36 -// cliReq.setRequestURI(contactURI);  
37 -//  
38 -// HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();  
39 -// Via callerVia = (Via) request.getHeader(Via.NAME);  
40 -// Via via = (Via) headerFactory.createViaHeader(SIPMain.ip, SIPMain.port, "UDP",  
41 -// callerVia.getBranch() + "sipphone");  
42 -//  
43 -// cliReq.removeHeader(Via.NAME);  
44 -// cliReq.addHeader(via);  
45 -//  
46 -// // 更新contact的地址  
47 -// ContactHeader contactHeader = headerFactory.createContactHeader();  
48 -// Address address = SipFactory.getInstance().createAddressFactory()  
49 -// .createAddress("sip:sipsoft@" + SIPMain.ip + ":" + SIPMain.port);  
50 -// contactHeader.setAddress(address);  
51 -// contactHeader.setExpires(3600);  
52 -// cliReq.setHeader(contactHeader);  
53 -//  
54 -// clientTransactionId = sipProvider.getNewClientTransaction(cliReq);  
55 -// clientTransactionId.sendRequest();  
56 -//  
57 -// System.out.println("processInvite clientTransactionId=" + clientTransactionId.toString());  
58 -//  
59 -// System.out.println("send invite to callee: " + cliReq);  
60 -// } catch (TransactionUnavailableException e1) {  
61 -// e1.printStackTrace();  
62 -// } catch (SipException e) {  
63 -// e.printStackTrace();  
64 -// } catch (ParseException e) {  
65 -// e.printStackTrace();  
66 -// } catch (Exception e) {  
67 -// e.printStackTrace();  
68 -// } 52 + // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
  53 + try {
  54 + Request request = evt.getRequest();
  55 + SipURI sipURI = (SipURI) request.getRequestURI();
  56 + String channelId = sipURI.getUser();
  57 + String platformId = null;
  58 +// SubjectHeader subjectHeader = (SubjectHeader)request.getHeader(SubjectHeader.NAME);
  59 +// // 查询通道是否存在 不存在回复404
  60 +// if (subjectHeader != null) { // 存在则从subjectHeader 获取平台信息
  61 +// String subject = subjectHeader.getSubject();
  62 +// if (subject != null) {
  63 +// String[] info1 = subject.split(",");
  64 +// if (info1 != null && info1 .length == 2) {
  65 +// String[] info2 = info1[1].split(":");
  66 +// if (info2 != null && info2.length == 2) {
  67 +// platformId = info2[0];
  68 +// }
  69 +// }
  70 +// }
  71 +// }
  72 +
  73 + FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
  74 + AddressImpl address = (AddressImpl) fromHeader.getAddress();
  75 + SipUri uri = (SipUri) address.getURI();
  76 + platformId = uri.getUser();
  77 +
  78 +// if (platformId == null) { // 不存在则从fromHeader 获取平台信息
  79 +// FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
  80 +// platformId = fromHeader.getName();
  81 +// }
  82 + if (platformId == null || channelId == null) {
  83 + response400Ack(evt); // 参数不全, 发400,请求错误
  84 + return;
  85 + }
  86 + // 查询平台下是否有该通道
  87 + DeviceChannel channel = storager.queryChannelInParentPlatform(platformId, channelId);
  88 + if (channel == null) {
  89 + response404Ack(evt); // 通道不存在,发404,资源不存在
  90 + return;
  91 + }else {
  92 + response100Ack(evt); // 通道存在,发100,trying
  93 + }
  94 + // 解析sdp消息
  95 + byte[] sdpByteArray = request.getRawContent();
  96 + SdpParser sdpParser = new SdpParser(); // TODO keng
  97 + SessionDescription sdp = sdpParser.parse(sdpByteArray);
  98 + // 获取支持的格式
  99 + List<MediaDescription> mediaDescriptions = sdp.getMediaDescriptions();
  100 + // 查看是否支持PS 负载96
  101 + String ip = null;
  102 + int port = -1;
  103 + for (MediaDescription mediaDescription : mediaDescriptions) {
  104 +
  105 + List<Codec> codecs = mediaDescription.getCodecs();
  106 + for (Codec codec : codecs) {
  107 + if("96".equals(codec.getPayloadType()) || "PS".equals(codec.getName()) || "ps".equals(codec.getName())) {
  108 + ip = mediaDescription.getIpAddress().getHostName();
  109 + port = mediaDescription.getPort();
  110 + break;
  111 + }
  112 + }
  113 + }
  114 + if (ip == null || port == -1) { // TODO 没有合适的视频流格式, 可配置是否使用第一个media信息
  115 + if (mediaDescriptions.size() > 0) {
  116 + ip = mediaDescriptions.get(0).getIpAddress().getHostName();
  117 + port = mediaDescriptions.get(0).getPort();
  118 + }
  119 + }
  120 +
  121 + if (ip == null || port == -1) {
  122 + response488Ack(evt);
  123 + return;
  124 + }
  125 +
  126 +
  127 + String ssrc = sdp.getSsrc();
  128 + // 通知下级推流,
  129 + // 查找合适的端口推流,
  130 + // 发送 200ok
  131 + // 收到ack后调用推流接口
  132 +
  133 +
  134 +
  135 +
  136 + } catch (SipException | InvalidArgumentException | ParseException e) {
  137 + e.printStackTrace();
  138 + } catch (IOException e) {
  139 + logger.warn("sdp解析错误");
  140 + e.printStackTrace();
  141 + }
  142 +
  143 + }
  144 +
  145 + /***
  146 + * 回复100 trying
  147 + * @param evt
  148 + * @throws SipException
  149 + * @throws InvalidArgumentException
  150 + * @throws ParseException
  151 + */
  152 + private void response100Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  153 + Response response = getMessageFactory().createResponse(Response.TRYING, evt.getRequest());
  154 + getServerTransaction(evt).sendResponse(response);
  155 + }
  156 +
  157 + /***
  158 + * 回复404
  159 + * @param evt
  160 + * @throws SipException
  161 + * @throws InvalidArgumentException
  162 + * @throws ParseException
  163 + */
  164 + private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  165 + Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest());
  166 + getServerTransaction(evt).sendResponse(response);
  167 + }
  168 +
  169 + /***
  170 + * 回复400
  171 + * @param evt
  172 + * @throws SipException
  173 + * @throws InvalidArgumentException
  174 + * @throws ParseException
  175 + */
  176 + private void response400Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  177 + Response response = getMessageFactory().createResponse(Response.BAD_REQUEST, evt.getRequest());
  178 + getServerTransaction(evt).sendResponse(response);
69 } 179 }
70 180
  181 + /***
  182 + * 回复488
  183 + * @param evt
  184 + * @throws SipException
  185 + * @throws InvalidArgumentException
  186 + * @throws ParseException
  187 + */
  188 + private void response488Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  189 + Response response = getMessageFactory().createResponse(Response.NOT_ACCEPTABLE_HERE, evt.getRequest());
  190 + getServerTransaction(evt).sendResponse(response);
  191 + }
  192 +
  193 + /***
  194 + * 回复200 OK
  195 + * @param evt
  196 + * @throws SipException
  197 + * @throws InvalidArgumentException
  198 + * @throws ParseException
  199 + */
  200 + private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
  201 + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
  202 + ContentTypeHeader contentTypeHeader = getHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
  203 + response.setContent(sdp, contentTypeHeader);
  204 + getServerTransaction(evt).sendResponse(response);
  205 + }
  206 +
  207 +
  208 +
  209 +
  210 +
  211 +
  212 +
  213 +
  214 +
  215 +
  216 + public SIPCommanderFroPlatform getCmderFroPlatform() {
  217 + return cmderFroPlatform;
  218 + }
  219 +
  220 + public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) {
  221 + this.cmderFroPlatform = cmderFroPlatform;
  222 + }
  223 +
  224 + public IVideoManagerStorager getStorager() {
  225 + return storager;
  226 + }
  227 +
  228 + public void setStorager(IVideoManagerStorager storager) {
  229 + this.storager = storager;
  230 + }
71 } 231 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -15,6 +15,8 @@ import com.genersoft.iot.vmp.gb28181.bean.*; @@ -15,6 +15,8 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
17 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; 17 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
  18 +import gov.nist.javax.sip.address.AddressImpl;
  19 +import gov.nist.javax.sip.address.SipUri;
18 import org.dom4j.Document; 20 import org.dom4j.Document;
19 import org.dom4j.DocumentException; 21 import org.dom4j.DocumentException;
20 import org.dom4j.Element; 22 import org.dom4j.Element;
@@ -166,10 +168,15 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -166,10 +168,15 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
166 Element deviceIdElement = rootElement.element("DeviceID"); 168 Element deviceIdElement = rootElement.element("DeviceID");
167 String deviceId = deviceIdElement.getText(); 169 String deviceId = deviceIdElement.getText();
168 Element deviceListElement = rootElement.element("DeviceList"); 170 Element deviceListElement = rootElement.element("DeviceList");
  171 +
  172 + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
  173 + AddressImpl address = (AddressImpl) fromHeader.getAddress();
  174 + SipUri uri = (SipUri) address.getURI();
  175 + String platformId = uri.getUser();
169 // if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求 176 // if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
170 if (name == "Query") { // 区分是Response——查询响应,还是Query——查询请求 177 if (name == "Query") { // 区分是Response——查询响应,还是Query——查询请求
171 // TODO 后续将代码拆分 178 // TODO 后续将代码拆分
172 - ParentPlatform parentPlatform = storager.queryParentPlatById(deviceId); 179 + ParentPlatform parentPlatform = storager.queryParentPlatById(platformId);
173 if (parentPlatform == null) { 180 if (parentPlatform == null) {
174 response404Ack(evt); 181 response404Ack(evt);
175 return; 182 return;
@@ -179,9 +186,8 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -179,9 +186,8 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
179 186
180 Element snElement = rootElement.element("SN"); 187 Element snElement = rootElement.element("SN");
181 String sn = snElement.getText(); 188 String sn = snElement.getText();
182 - FromHeader fromHeader = (FromHeader)evt.getRequest().getHeader(FromHeader.NAME);  
183 // 准备回复通道信息 189 // 准备回复通道信息
184 - List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getDeviceGBId()); 190 + List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
185 if (channelReduces.size() >0 ) { 191 if (channelReduces.size() >0 ) {
186 for (ChannelReduce channelReduce : channelReduces) { 192 for (ChannelReduce channelReduce : channelReduces) {
187 DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); 193 DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
@@ -499,7 +505,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -499,7 +505,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
499 } 505 }
500 506
501 /*** 507 /***
502 - * 回复200 OK 508 + * 回复404
503 * @param evt 509 * @param evt
504 * @throws SipException 510 * @throws SipException
505 * @throws InvalidArgumentException 511 * @throws InvalidArgumentException
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java
@@ -61,10 +61,14 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor { @@ -61,10 +61,14 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor {
61 public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { 61 public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
62 // TODO Auto-generated method stub 62 // TODO Auto-generated method stub
63 Response response = evt.getResponse(); 63 Response response = evt.getResponse();
64 - ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);  
65 - SipUri uri = (SipUri)toHeader.getAddress().getURI();  
66 - String platformGBId = uri.getAuthority().getUser(); 64 + CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
  65 + String callId = callIdHeader.getCallId();
67 66
  67 + String platformGBId = redisCatchStorage.queryPlatformRegisterInfo(callId);
  68 + if (platformGBId == null) {
  69 + logger.info(String.format("未找到callId: %s 的注册/注销平台id", callId ));
  70 + return;
  71 + }
68 logger.info(String.format("收到 %s 的注册/注销%S响应", platformGBId, response.getStatusCode() )); 72 logger.info(String.format("收到 %s 的注册/注销%S响应", platformGBId, response.getStatusCode() ));
69 73
70 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId); 74 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId);
@@ -80,18 +84,13 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor { @@ -80,18 +84,13 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor {
80 84
81 if (response.getStatusCode() == 401) { 85 if (response.getStatusCode() == 401) {
82 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); 86 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
83 -  
84 -  
85 - CallIdHeader callIdHeader = (CallIdHeader)response.getHeader(CallIdHeader.NAME);  
86 - String callId = callIdHeader.getCallId();  
87 -  
88 sipCommanderForPlatform.register(parentPlatform, callId, www, null, null); 87 sipCommanderForPlatform.register(parentPlatform, callId, www, null, null);
89 }else if (response.getStatusCode() == 200){ 88 }else if (response.getStatusCode() == 200){
90 // 注册成功 89 // 注册成功
91 logger.info(String.format("%s 注册成功", platformGBId )); 90 logger.info(String.format("%s 注册成功", platformGBId ));
  91 + redisCatchStorage.delPlatformRegisterInfo(callId);
92 parentPlatform.setStatus(true); 92 parentPlatform.setStatus(true);
93 storager.updateParentPlatform(parentPlatform); 93 storager.updateParentPlatform(parentPlatform);
94 - //  
95 redisCatchStorage.updatePlatformRegister(parentPlatform); 94 redisCatchStorage.updatePlatformRegister(parentPlatform);
96 95
97 redisCatchStorage.updatePlatformKeepalive(parentPlatform); 96 redisCatchStorage.updatePlatformKeepalive(parentPlatform);
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -73,4 +73,9 @@ public interface IRedisCatchStorage { @@ -73,4 +73,9 @@ public interface IRedisCatchStorage {
73 73
74 void delPlatformRegister(String platformGbId); 74 void delPlatformRegister(String platformGbId);
75 75
  76 + void updatePlatformRegisterInfo(String callId, String platformGbId);
  77 +
  78 + String queryPlatformRegisterInfo(String callId);
  79 +
  80 + void delPlatformRegisterInfo(String callId);
76 } 81 }
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -233,4 +233,5 @@ public interface IVideoManagerStorager { @@ -233,4 +233,5 @@ public interface IVideoManagerStorager {
233 int delChannelForGB(String platformId, List<ChannelReduce> channelReduces); 233 int delChannelForGB(String platformId, List<ChannelReduce> channelReduces);
234 234
235 235
  236 + DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
236 } 237 }
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
@@ -24,7 +24,7 @@ public interface ParentPlatformMapper { @@ -24,7 +24,7 @@ public interface ParentPlatformMapper {
24 @Update("UPDATE parent_platform " + 24 @Update("UPDATE parent_platform " +
25 "SET enable=#{enable}, " + 25 "SET enable=#{enable}, " +
26 "name=#{name}," + 26 "name=#{name}," +
27 - "serverGBId=#{serverGBId}," + 27 + "deviceGBId=#{deviceGBId}," +
28 "serverGBDomain=#{serverGBDomain}, " + 28 "serverGBDomain=#{serverGBDomain}, " +
29 "serverIP=#{serverIP}," + 29 "serverIP=#{serverIP}," +
30 "serverPort=#{serverPort}, " + 30 "serverPort=#{serverPort}, " +
@@ -39,13 +39,13 @@ public interface ParentPlatformMapper { @@ -39,13 +39,13 @@ public interface ParentPlatformMapper {
39 "PTZEnable=#{PTZEnable}, " + 39 "PTZEnable=#{PTZEnable}, " +
40 "rtcp=#{rtcp}, " + 40 "rtcp=#{rtcp}, " +
41 "status=#{status} " + 41 "status=#{status} " +
42 - "WHERE deviceGBId=#{deviceGBId}") 42 + "WHERE serverGBId=#{serverGBId}")
43 int updateParentPlatform(ParentPlatform parentPlatform); 43 int updateParentPlatform(ParentPlatform parentPlatform);
44 44
45 - @Delete("DELETE FROM parent_platform WHERE deviceGBId=#{deviceGBId}") 45 + @Delete("DELETE FROM parent_platform WHERE serverGBId=#{serverGBId}")
46 int delParentPlatform(ParentPlatform parentPlatform); 46 int delParentPlatform(ParentPlatform parentPlatform);
47 47
48 - @Select("SELECT *,( SELECT count(0) FROM platform_gb_channel pc WHERE pc.platformId = pp.deviceGBId) as channelCount FROM parent_platform pp ") 48 + @Select("SELECT *,( SELECT count(0) FROM platform_gb_channel pc WHERE pc.platformId = pp.serverGBId) as channelCount FROM parent_platform pp ")
49 List<ParentPlatform> getParentPlatformList(); 49 List<ParentPlatform> getParentPlatformList();
50 50
51 @Select("SELECT * FROM parent_platform WHERE enable=#{enable}") 51 @Select("SELECT * FROM parent_platform WHERE enable=#{enable}")
src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java
1 package com.genersoft.iot.vmp.storager.dao; 1 package com.genersoft.iot.vmp.storager.dao;
2 2
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
3 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; 4 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
4 import org.apache.ibatis.annotations.Delete; 5 import org.apache.ibatis.annotations.Delete;
5 import org.apache.ibatis.annotations.Insert; 6 import org.apache.ibatis.annotations.Insert;
@@ -39,4 +40,9 @@ public interface PatformChannelMapper { @@ -39,4 +40,9 @@ public interface PatformChannelMapper {
39 "DELETE FROM platform_gb_channel WHERE platformId='${platformId}'" + 40 "DELETE FROM platform_gb_channel WHERE platformId='${platformId}'" +
40 "</script>") 41 "</script>")
41 int cleanChannelForGB(String platformId); 42 int cleanChannelForGB(String platformId);
  43 +
  44 +
  45 + @Select("SELECT * FROM device_channel WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE " +
  46 + "platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'")
  47 + DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
42 } 48 }
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -169,13 +169,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -169,13 +169,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
169 169
170 @Override 170 @Override
171 public void updatePlatformKeepalive(ParentPlatform parentPlatform) { 171 public void updatePlatformKeepalive(ParentPlatform parentPlatform) {
172 - String key = VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX + parentPlatform.getDeviceGBId(); 172 + String key = VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX + parentPlatform.getServerGBId();
173 redis.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout())); 173 redis.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
174 } 174 }
175 175
176 @Override 176 @Override
177 public void updatePlatformRegister(ParentPlatform parentPlatform) { 177 public void updatePlatformRegister(ParentPlatform parentPlatform) {
178 - String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + parentPlatform.getDeviceGBId(); 178 + String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + parentPlatform.getServerGBId();
179 redis.set(key, "", Integer.parseInt(parentPlatform.getExpires())); 179 redis.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
180 } 180 }
181 181
@@ -198,4 +198,22 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -198,4 +198,22 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
198 public void delPlatformRegister(String platformGbId) { 198 public void delPlatformRegister(String platformGbId) {
199 redis.del(VideoManagerConstants.PLATFORM_REGISTER_PREFIX + platformGbId); 199 redis.del(VideoManagerConstants.PLATFORM_REGISTER_PREFIX + platformGbId);
200 } 200 }
  201 +
  202 +
  203 + @Override
  204 + public void updatePlatformRegisterInfo(String callId, String platformGbId) {
  205 + String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + callId;
  206 + redis.set(key, platformGbId);
  207 + }
  208 +
  209 +
  210 + @Override
  211 + public String queryPlatformRegisterInfo(String callId) {
  212 + return (String)redis.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + callId);
  213 + }
  214 +
  215 + @Override
  216 + public void delPlatformRegisterInfo(String callId) {
  217 + redis.del(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + callId);
  218 + }
201 } 219 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
@@ -254,7 +254,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -254,7 +254,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
254 public boolean deleteParentPlatform(ParentPlatform parentPlatform) { 254 public boolean deleteParentPlatform(ParentPlatform parentPlatform) {
255 int result = platformMapper.delParentPlatform(parentPlatform); 255 int result = platformMapper.delParentPlatform(parentPlatform);
256 // 删除关联的通道 256 // 删除关联的通道
257 - patformChannelMapper.cleanChannelForGB(parentPlatform.getDeviceGBId()); 257 + patformChannelMapper.cleanChannelForGB(parentPlatform.getServerGBId());
258 return result > 0; 258 return result > 0;
259 } 259 }
260 260
@@ -329,4 +329,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -329,4 +329,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
329 329
330 return result; 330 return result;
331 } 331 }
  332 +
  333 + @Override
  334 + public DeviceChannel queryChannelInParentPlatform(String platformId, String channelId) {
  335 + DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId);
  336 + return channel;
  337 + }
332 } 338 }
src/main/java/com/genersoft/iot/vmp/vmanager/platform/PlatformController.java
@@ -110,7 +110,7 @@ public class PlatformController { @@ -110,7 +110,7 @@ public class PlatformController {
110 if (logger.isDebugEnabled()) { 110 if (logger.isDebugEnabled()) {
111 logger.debug("查询所有上级设备API调用"); 111 logger.debug("查询所有上级设备API调用");
112 } 112 }
113 - if (StringUtils.isEmpty(parentPlatform.getDeviceGBId()) 113 + if (StringUtils.isEmpty(parentPlatform.getServerGBId())
114 ){ 114 ){
115 return new ResponseEntity<>("missing parameters", HttpStatus.BAD_REQUEST); 115 return new ResponseEntity<>("missing parameters", HttpStatus.BAD_REQUEST);
116 } 116 }
@@ -118,14 +118,14 @@ public class PlatformController { @@ -118,14 +118,14 @@ public class PlatformController {
118 // 发送离线消息,无论是否成功都删除缓存 118 // 发送离线消息,无论是否成功都删除缓存
119 commanderForPlatform.unregister(parentPlatform, (event -> { 119 commanderForPlatform.unregister(parentPlatform, (event -> {
120 // 清空redis缓存 120 // 清空redis缓存
121 - redisCatchStorage.delPlatformCatchInfo(parentPlatform.getDeviceGBId());  
122 - redisCatchStorage.delPlatformKeepalive(parentPlatform.getDeviceGBId());  
123 - redisCatchStorage.delPlatformRegister(parentPlatform.getDeviceGBId()); 121 + redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
  122 + redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
  123 + redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
124 }), (event -> { 124 }), (event -> {
125 // 清空redis缓存 125 // 清空redis缓存
126 - redisCatchStorage.delPlatformCatchInfo(parentPlatform.getDeviceGBId());  
127 - redisCatchStorage.delPlatformKeepalive(parentPlatform.getDeviceGBId());  
128 - redisCatchStorage.delPlatformRegister(parentPlatform.getDeviceGBId()); 126 + redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
  127 + redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
  128 + redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
129 })); 129 }));
130 130
131 boolean deleteResult = storager.deleteParentPlatform(parentPlatform); 131 boolean deleteResult = storager.deleteParentPlatform(parentPlatform);