SdpParser.java 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. This file is part of Peers, a java SIP softphone.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. Copyright 2007, 2008, 2009, 2010 Yohann Martineau
  14. */
  15. package com.genersoft.iot.vmp.gb28181.sdp;
  16. import java.io.BufferedReader;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.IOException;
  19. import java.io.InputStreamReader;
  20. import java.net.InetAddress;
  21. import java.util.ArrayList;
  22. import java.util.Hashtable;
  23. import java.util.List;
  24. public class SdpParser {
  25. public SessionDescription parse(byte[] body) throws IOException {
  26. if (body == null || body.length == 0) {
  27. return null;
  28. }
  29. ByteArrayInputStream in = new ByteArrayInputStream(body);
  30. InputStreamReader inputStreamReader = new InputStreamReader(in);
  31. BufferedReader reader = new BufferedReader(inputStreamReader);
  32. SessionDescription sessionDescription = new SessionDescription();
  33. //version
  34. String line = reader.readLine();
  35. if (line.length() < 3) {
  36. return null;
  37. }
  38. if (line.charAt(0) != RFC4566_28181.TYPE_VERSION
  39. || line.charAt(1) != RFC4566_28181.SEPARATOR
  40. || line.charAt(2) != RFC4566_28181.VERSION) {
  41. return null;
  42. }
  43. //origin
  44. line = reader.readLine();
  45. if (line.length() < 3) {
  46. return null;
  47. }
  48. if (line.charAt(0) != RFC4566_28181.TYPE_ORIGIN
  49. || line.charAt(1) != RFC4566_28181.SEPARATOR) {
  50. return null;
  51. }
  52. line = line.substring(2);
  53. String[] originArr = line.split(" ");
  54. if (originArr == null || originArr.length != 6) {
  55. return null;
  56. }
  57. sessionDescription.setUsername(originArr[0]);
  58. sessionDescription.setId(Long.parseLong(originArr[1]));
  59. sessionDescription.setVersion(Long.parseLong(originArr[2]));
  60. sessionDescription.setIpAddress(InetAddress.getByName(originArr[5]));
  61. //name
  62. line = reader.readLine();
  63. if (line.length() < 3) {
  64. return null;
  65. }
  66. if (line.charAt(0) != RFC4566_28181.TYPE_SUBJECT
  67. || line.charAt(1) != RFC4566_28181.SEPARATOR) {
  68. return null;
  69. }
  70. sessionDescription.setName(line.substring(2));
  71. //session connection and attributes
  72. Hashtable<String, String> sessionAttributes = new Hashtable<String, String>();
  73. sessionDescription.setAttributes(sessionAttributes);
  74. while ((line = reader.readLine()) != null
  75. && line.charAt(0) != RFC4566_28181.TYPE_MEDIA) {
  76. if (line.length() > 3
  77. && line.charAt(0) == RFC4566_28181.TYPE_CONNECTION
  78. && line.charAt(1) == RFC4566_28181.SEPARATOR) {
  79. String connection = parseConnection(line.substring(2));
  80. if (connection == null) {
  81. continue;
  82. }
  83. sessionDescription.setIpAddress(InetAddress.getByName(connection));
  84. } else if (line.length() > 3
  85. && line.charAt(0) == RFC4566_28181.TYPE_ATTRIBUTE
  86. && line.charAt(1) == RFC4566_28181.SEPARATOR) {
  87. String value = line.substring(2);
  88. int pos = value.indexOf(RFC4566_28181.ATTR_SEPARATOR);
  89. if (pos > -1) {
  90. sessionAttributes.put(value.substring(0, pos),
  91. value.substring(pos + 1));
  92. } else {
  93. sessionAttributes.put(value, "");
  94. }
  95. }
  96. }
  97. if (line == null) {
  98. return null;
  99. }
  100. //we are at the first media line
  101. ArrayList<SdpLine> mediaLines = new ArrayList<SdpLine>();
  102. do {
  103. if (line.length() < 2) {
  104. return null;
  105. }
  106. if (line.charAt(1) != RFC4566_28181.SEPARATOR) {
  107. return null;
  108. }
  109. if (line.charAt(0) == RFC4566_28181.TYPE_SSRC) {
  110. sessionDescription.setSsrc(line.length() >=2 ?line.substring(2):"");
  111. }else if (line.charAt(0) == RFC4566_28181.TYPE_MEDIA_DES) {
  112. sessionDescription.setGbMediaDescriptions(line.length() >=2 ?line.substring(2):"");
  113. }else {
  114. SdpLine mediaLine = new SdpLine();
  115. mediaLine.setType(line.charAt(0));
  116. mediaLine.setValue(line.substring(2));
  117. mediaLines.add(mediaLine);
  118. }
  119. }
  120. while ((line = reader.readLine()) != null );
  121. ArrayList<MediaDescription> mediaDescriptions = new ArrayList<MediaDescription>();
  122. sessionDescription.setMediaDescriptions(mediaDescriptions);
  123. for (SdpLine sdpLine : mediaLines) {
  124. MediaDescription mediaDescription;
  125. if (sdpLine.getType() == RFC4566_28181.TYPE_MEDIA) {
  126. String[] mediaArr = sdpLine.getValue().split(" ");
  127. if (mediaArr == null || mediaArr.length < 4) {
  128. return null;
  129. }
  130. mediaDescription = new MediaDescription();
  131. mediaDescription.setType(mediaArr[0]);
  132. //TODO manage port range
  133. mediaDescription.setPort(Integer.parseInt(mediaArr[1]));
  134. mediaDescription.setAttributes(new Hashtable<String, String>());
  135. List<Codec> codecs = new ArrayList<Codec>();
  136. for (int i = 3; i < mediaArr.length; ++i) {
  137. int payloadType = Integer.parseInt(mediaArr[i]);
  138. Codec codec = new Codec();
  139. codec.setPayloadType(payloadType);
  140. codec.setName("unsupported");
  141. codecs.add(codec);
  142. }
  143. mediaDescription.setCodecs(codecs);
  144. mediaDescriptions.add(mediaDescription);
  145. } else {
  146. mediaDescription = mediaDescriptions.get(mediaDescriptions.size() - 1);
  147. String sdpLineValue = sdpLine.getValue();
  148. if (sdpLine.getType() == RFC4566_28181.TYPE_CONNECTION) {
  149. String ipAddress = parseConnection(sdpLineValue);
  150. mediaDescription.setIpAddress(InetAddress.getByName(ipAddress));
  151. } else if (sdpLine.getType() == RFC4566_28181.TYPE_ATTRIBUTE) {
  152. Hashtable<String, String> attributes = mediaDescription.getAttributes();
  153. int pos = sdpLineValue.indexOf(RFC4566_28181.ATTR_SEPARATOR);
  154. if (pos > -1) {
  155. String name = sdpLineValue.substring(0, pos);
  156. String value = sdpLineValue.substring(pos + 1);
  157. pos = value.indexOf(" ");
  158. if (pos > -1) {
  159. int payloadType;
  160. try {
  161. payloadType = Integer.parseInt(value.substring(0, pos));
  162. List<Codec> codecs = mediaDescription.getCodecs();
  163. for (Codec codec: codecs) {
  164. if (codec.getPayloadType() == payloadType) {
  165. value = value.substring(pos + 1);
  166. pos = value.indexOf("/");
  167. if (pos > -1) {
  168. value = value.substring(0, pos);
  169. codec.setName(value);
  170. }
  171. break;
  172. }
  173. }
  174. } catch (NumberFormatException e) {
  175. attributes.put(name, value);
  176. }
  177. } else {
  178. attributes.put(name, value);
  179. }
  180. } else {
  181. attributes.put(sdpLineValue, "");
  182. }
  183. }
  184. }
  185. }
  186. sessionDescription.setMediaDescriptions(mediaDescriptions);
  187. for (MediaDescription description : mediaDescriptions) {
  188. if (description.getIpAddress() == null) {
  189. InetAddress sessionAddress = sessionDescription.getIpAddress();
  190. if (sessionAddress == null) {
  191. return null;
  192. }
  193. description.setIpAddress(sessionAddress);
  194. }
  195. }
  196. return sessionDescription;
  197. }
  198. private String parseConnection(String line) {
  199. String[] connectionArr = line.split(" ");
  200. if (connectionArr == null || connectionArr.length != 3) {
  201. return null;
  202. }
  203. return connectionArr[2];
  204. }
  205. }