17d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh/* 27d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Copyright (C) 2010 The Android Open Source Project 37d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * 47d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 57d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * you may not use this file except in compliance with the License. 67d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * You may obtain a copy of the License at 77d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * 87d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 97d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * 107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * See the License for the specific language governing permissions and 147d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * limitations under the License. 157d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 167d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 177d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yehpackage android.net.sip; 187d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 197d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yehimport java.util.ArrayList; 207d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yehimport java.util.Arrays; 210226eb00cecf82b53e29758c04cd1b39015d2909Johan Redestigimport java.util.Locale; 227d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 237d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh/** 247d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * An object used to manipulate messages of Session Description Protocol (SDP). 257d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * It is mainly designed for the uses of Session Initiation Protocol (SIP). 267d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Therefore, it only handles connection addresses ("c="), bandwidth limits, 277d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * ("b="), encryption keys ("k="), and attribute fields ("a="). Currently this 287d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * implementation does not support multicast sessions. 297d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * 307d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * <p>Here is an example code to create a session description.</p> 317d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * <pre> 327d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * SimpleSessionDescription description = new SimpleSessionDescription( 337d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * System.currentTimeMillis(), "1.2.3.4"); 347d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Media media = description.newMedia("audio", 56789, 1, "RTP/AVP"); 357d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * media.setRtpPayload(0, "PCMU/8000", null); 367d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * media.setRtpPayload(8, "PCMA/8000", null); 377d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * media.setRtpPayload(127, "telephone-event/8000", "0-15"); 387d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * media.setAttribute("sendrecv", ""); 397d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * </pre> 407d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * <p>Invoking <code>description.encode()</code> will produce a result like the 417d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * one below.</p> 427d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * <pre> 437d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * v=0 447d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * o=- 1284970442706 1284970442709 IN IP4 1.2.3.4 457d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * s=- 467d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * c=IN IP4 1.2.3.4 477d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * t=0 0 487d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * m=audio 56789 RTP/AVP 0 8 127 497d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * a=rtpmap:0 PCMU/8000 507d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * a=rtpmap:8 PCMA/8000 517d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * a=rtpmap:127 telephone-event/8000 527d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * a=fmtp:127 0-15 537d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * a=sendrecv 547d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * </pre> 557d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * @hide 567d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 577d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yehpublic class SimpleSessionDescription { 587d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final Fields mFields = new Fields("voscbtka"); 597d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final ArrayList<Media> mMedia = new ArrayList<Media>(); 607d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 617d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 627d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Creates a minimal session description from the given session ID and 637d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * unicast address. The address is used in the origin field ("o=") and the 647d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * connection field ("c="). See {@link SimpleSessionDescription} for an 657d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * example of its usage. 667d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 677d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public SimpleSessionDescription(long sessionId, String address) { 687d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + address; 697d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.parse("v=0"); 700226eb00cecf82b53e29758c04cd1b39015d2909Johan Redestig mFields.parse(String.format(Locale.US, "o=- %d %d %s", sessionId, 717d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh System.currentTimeMillis(), address)); 727d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.parse("s=-"); 737d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.parse("t=0 0"); 747d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.parse("c=" + address); 757d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 767d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 777d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 787d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Creates a session description from the given message. 797d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * 807d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * @throws IllegalArgumentException if message is invalid. 817d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 827d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public SimpleSessionDescription(String message) { 837d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String[] lines = message.trim().replaceAll(" +", " ").split("[\r\n]+"); 847d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh Fields fields = mFields; 857d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 867d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (String line : lines) { 877d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh try { 887d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (line.charAt(1) != '=') { 897d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh throw new IllegalArgumentException(); 907d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 917d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (line.charAt(0) == 'm') { 927d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String[] parts = line.substring(2).split(" ", 4); 937d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String[] ports = parts[1].split("/", 2); 947d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh Media media = newMedia(parts[0], Integer.parseInt(ports[0]), 957d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh (ports.length < 2) ? 1 : Integer.parseInt(ports[1]), 967d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh parts[2]); 977d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (String format : parts[3].split(" ")) { 987d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh media.setFormat(format, null); 997d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1007d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh fields = media; 1017d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } else { 1027d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh fields.parse(line); 1037d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1047d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } catch (Exception e) { 1057d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh throw new IllegalArgumentException("Invalid SDP: " + line); 1067d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1077d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1087d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1097d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Creates a new media description in this session description. 1127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * 1137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * @param type The media type, e.g. {@code "audio"}. 1147d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * @param port The first transport port used by this media. 1157d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * @param portCount The number of contiguous ports used by this media. 1167d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * @param protocol The transport protocol, e.g. {@code "RTP/AVP"}. 1177d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1187d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public Media newMedia(String type, int port, int portCount, 1197d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String protocol) { 1207d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh Media media = new Media(type, port, portCount, protocol); 1217d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mMedia.add(media); 1227d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return media; 1237d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1247d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1257d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1267d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns all the media descriptions in this session description. 1277d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1287d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public Media[] getMedia() { 1297d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mMedia.toArray(new Media[mMedia.size()]); 1307d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1317d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1327d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1337d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Encodes the session description and all its media descriptions in a 1347d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * string. Note that the result might be incomplete if a required field 1357d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * has never been added before. 1367d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1377d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String encode() { 1387d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh StringBuilder buffer = new StringBuilder(); 1397d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.write(buffer); 1407d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (Media media : mMedia) { 1417d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh media.write(buffer); 1427d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1437d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return buffer.toString(); 1447d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1457d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1467d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1477d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the connection address or {@code null} if it is not present. 1487d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1497d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getAddress() { 1507d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getAddress(); 1517d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1527d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1537d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1547d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the connection address. The field will be removed if the address 1557d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * is {@code null}. 1567d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1577d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setAddress(String address) { 1587d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.setAddress(address); 1597d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1607d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1617d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1627d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the encryption method or {@code null} if it is not present. 1637d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1647d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getEncryptionMethod() { 1657d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getEncryptionMethod(); 1667d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1677d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1687d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1697d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the encryption key or {@code null} if it is not present. 1707d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1717d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getEncryptionKey() { 1727d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getEncryptionKey(); 1737d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1747d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1757d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1767d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the encryption method and the encryption key. The field will be 1777d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * removed if the method is {@code null}. 1787d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1797d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setEncryption(String method, String key) { 1807d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.setEncryption(method, key); 1817d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1827d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1837d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1847d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the types of the bandwidth limits. 1857d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1867d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String[] getBandwidthTypes() { 1877d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getBandwidthTypes(); 1887d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1897d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1907d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1917d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the bandwidth limit of the given type or {@code -1} if it is not 1927d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * present. 1937d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 1947d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public int getBandwidth(String type) { 1957d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getBandwidth(type); 1967d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 1977d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 1987d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 1997d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the bandwith limit for the given type. The field will be removed if 2007d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * the value is negative. 2017d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2027d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setBandwidth(String type, int value) { 2037d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.setBandwidth(type, value); 2047d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2057d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2067d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2077d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the names of all the attributes. 2087d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2097d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String[] getAttributeNames() { 2107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getAttributeNames(); 2117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2147d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the attribute of the given name or {@code null} if it is not 2157d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * present. 2167d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2177d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getAttribute(String name) { 2187d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFields.getAttribute(name); 2197d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2207d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2217d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2227d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the attribute for the given name. The field will be removed if 2237d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * the value is {@code null}. To set a binary attribute, use an empty 2247d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * string as the value. 2257d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2267d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setAttribute(String name, String value) { 2277d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFields.setAttribute(name, value); 2287d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2297d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2307d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2317d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * This class represents a media description of a session description. It 2327d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * can only be created by {@link SimpleSessionDescription#newMedia}. Since 2337d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * the syntax is more restricted for RTP based protocols, two sets of access 2347d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * methods are implemented. See {@link SimpleSessionDescription} for an 2357d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * example of its usage. 2367d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2377d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public static class Media extends Fields { 2387d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final String mType; 2397d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final int mPort; 2407d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final int mPortCount; 2417d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final String mProtocol; 2427d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private ArrayList<String> mFormats = new ArrayList<String>(); 2437d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2447d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private Media(String type, int port, int portCount, String protocol) { 2457d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super("icbka"); 2467d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mType = type; 2477d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mPort = port; 2487d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mPortCount = portCount; 2497d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mProtocol = protocol; 2507d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2517d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2527d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2537d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the media type. 2547d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2557d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getType() { 2567d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mType; 2577d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2587d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2597d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2607d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the first transport port used by this media. 2617d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2627d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public int getPort() { 2637d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mPort; 2647d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2657d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2667d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2677d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the number of contiguous ports used by this media. 2687d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2697d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public int getPortCount() { 2707d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mPortCount; 2717d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2727d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2737d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2747d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the transport protocol. 2757d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2767d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getProtocol() { 2777d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mProtocol; 2787d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2797d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2807d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2817d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the media formats. 2827d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2837d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String[] getFormats() { 2847d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return mFormats.toArray(new String[mFormats.size()]); 2857d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2867d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2877d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2887d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the {@code fmtp} attribute of the given format or 2897d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * {@code null} if it is not present. 2907d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2917d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getFmtp(String format) { 2927d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return super.get("a=fmtp:" + format, ' '); 2937d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 2947d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 2957d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 2967d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets a format and its {@code fmtp} attribute. If the attribute is 2977d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * {@code null}, the corresponding field will be removed. 2987d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 2997d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setFormat(String format, String fmtp) { 3007d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFormats.remove(format); 3017d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFormats.add(format); 3027d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.set("a=rtpmap:" + format, ' ', null); 3037d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.set("a=fmtp:" + format, ' ', fmtp); 3047d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3057d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3067d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3077d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Removes a format and its {@code fmtp} attribute. 3087d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3097d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void removeFormat(String format) { 3107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFormats.remove(format); 3117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.set("a=rtpmap:" + format, ' ', null); 3127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.set("a=fmtp:" + format, ' ', null); 3137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3147d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3157d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3167d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the RTP payload types. 3177d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3187d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public int[] getRtpPayloadTypes() { 3197d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int[] types = new int[mFormats.size()]; 3207d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int length = 0; 3217d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (String format : mFormats) { 3227d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh try { 3237d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh types[length] = Integer.parseInt(format); 3247d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh ++length; 3257d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } catch (NumberFormatException e) { } 3267d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3277d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return Arrays.copyOf(types, length); 3287d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3297d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3307d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3317d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the {@code rtpmap} attribute of the given RTP payload type 3327d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * or {@code null} if it is not present. 3337d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3347d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getRtpmap(int type) { 3357d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return super.get("a=rtpmap:" + type, ' '); 3367d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3377d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3387d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3397d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the {@code fmtp} attribute of the given RTP payload type or 3407d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * {@code null} if it is not present. 3417d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3427d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getFmtp(int type) { 3437d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return super.get("a=fmtp:" + type, ' '); 3447d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3457d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3467d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 347129cdb5fa30ddc244d0a2dd3b0bc651611b39b8crepo sync * Sets a RTP payload type and its {@code rtpmap} and {@code fmtp} 3487d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * attributes. If any of the attributes is {@code null}, the 3497d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * corresponding field will be removed. See 3507d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * {@link SimpleSessionDescription} for an example of its usage. 3517d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3527d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setRtpPayload(int type, String rtpmap, String fmtp) { 3537d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String format = String.valueOf(type); 3547d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFormats.remove(format); 3557d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mFormats.add(format); 3567d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.set("a=rtpmap:" + format, ' ', rtpmap); 3577d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.set("a=fmtp:" + format, ' ', fmtp); 3587d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3597d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3607d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3617d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Removes a RTP payload and its {@code rtpmap} and {@code fmtp} 3627d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * attributes. 3637d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3647d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void removeRtpPayload(int type) { 3657d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh removeFormat(String.valueOf(type)); 3667d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3677d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3687d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private void write(StringBuilder buffer) { 3697d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh buffer.append("m=").append(mType).append(' ').append(mPort); 3707d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (mPortCount != 1) { 3717d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh buffer.append('/').append(mPortCount); 3727d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3737d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh buffer.append(' ').append(mProtocol); 3747d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (String format : mFormats) { 3757d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh buffer.append(' ').append(format); 3767d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3777d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh buffer.append("\r\n"); 3787d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh super.write(buffer); 3797d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3807d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3817d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3827d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3837d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * This class acts as a set of fields, and the size of the set is expected 3847d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * to be small. Therefore, it uses a simple list instead of maps. Each field 3857d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * has three parts: a key, a delimiter, and a value. Delimiters are special 3867d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * because they are not included in binary attributes. As a result, the 3877d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * private methods, which are the building blocks of this class, all take 3887d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * the delimiter as an argument. 3897d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 3907d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private static class Fields { 3917d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final String mOrder; 3927d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private final ArrayList<String> mLines = new ArrayList<String>(); 3937d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3947d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh Fields(String order) { 3957d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mOrder = order; 3967d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 3977d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 3987d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 3997d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the connection address or {@code null} if it is not present. 4007d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4017d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getAddress() { 4027d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String address = get("c", '='); 4037d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (address == null) { 4047d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return null; 4057d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4067d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String[] parts = address.split(" "); 4077d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (parts.length != 3) { 4087d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return null; 4097d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int slash = parts[2].indexOf('/'); 4117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return (slash < 0) ? parts[2] : parts[2].substring(0, slash); 4127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4147d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4157d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the connection address. The field will be removed if the address 4167d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * is {@code null}. 4177d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4187d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setAddress(String address) { 4197d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (address != null) { 4207d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + 4217d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh address; 4227d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4237d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh set("c", '=', address); 4247d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4257d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4267d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4277d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the encryption method or {@code null} if it is not present. 4287d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4297d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getEncryptionMethod() { 4307d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String encryption = get("k", '='); 4317d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (encryption == null) { 4327d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return null; 4337d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4347d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int colon = encryption.indexOf(':'); 4357d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return (colon == -1) ? encryption : encryption.substring(0, colon); 4367d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4377d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4387d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4397d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the encryption key or {@code null} if it is not present. 4407d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4417d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getEncryptionKey() { 4427d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String encryption = get("k", '='); 4437d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (encryption == null) { 4447d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return null; 4457d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4467d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int colon = encryption.indexOf(':'); 4477d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return (colon == -1) ? null : encryption.substring(0, colon + 1); 4487d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4497d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4507d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4517d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the encryption method and the encryption key. The field will be 4527d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * removed if the method is {@code null}. 4537d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4547d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setEncryption(String method, String key) { 4557d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh set("k", '=', (method == null || key == null) ? 4567d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh method : method + ':' + key); 4577d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4587d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4597d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4607d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the types of the bandwidth limits. 4617d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4627d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String[] getBandwidthTypes() { 4637d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return cut("b=", ':'); 4647d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4657d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4667d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4677d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the bandwidth limit of the given type or {@code -1} if it is 4687d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * not present. 4697d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4707d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public int getBandwidth(String type) { 4717d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String value = get("b=" + type, ':'); 4727d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (value != null) { 4737d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh try { 4747d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return Integer.parseInt(value); 4757d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } catch (NumberFormatException e) { } 4767d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh setBandwidth(type, -1); 4777d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4787d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return -1; 4797d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4807d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4817d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4827d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the bandwith limit for the given type. The field will be removed 4837d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * if the value is negative. 4847d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4857d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setBandwidth(String type, int value) { 4867d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh set("b=" + type, ':', (value < 0) ? null : String.valueOf(value)); 4877d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4887d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4897d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4907d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the names of all the attributes. 4917d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 4927d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String[] getAttributeNames() { 4937d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return cut("a=", ':'); 4947d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 4957d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 4967d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 4977d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the attribute of the given name or {@code null} if it is not 4987d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * present. 4997d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 5007d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public String getAttribute(String name) { 5017d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return get("a=" + name, ':'); 5027d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5037d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 5047d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 5057d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the attribute for the given name. The field will be removed if 5067d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * the value is {@code null}. To set a binary attribute, use an empty 5077d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * string as the value. 5087d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 5097d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh public void setAttribute(String name, String value) { 5107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh set("a=" + name, ':', value); 5117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 5137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private void write(StringBuilder buffer) { 5147d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (int i = 0; i < mOrder.length(); ++i) { 5157d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh char type = mOrder.charAt(i); 5167d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (String line : mLines) { 5177d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (line.charAt(0) == type) { 5187d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh buffer.append(line).append("\r\n"); 5197d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5207d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5217d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5227d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5237d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 5247d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 5257d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Invokes {@link #set} after splitting the line into three parts. 5267d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 5277d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private void parse(String line) { 5287d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh char type = line.charAt(0); 5297d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (mOrder.indexOf(type) == -1) { 5307d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return; 5317d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5327d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh char delimiter = '='; 5337d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (line.startsWith("a=rtpmap:") || line.startsWith("a=fmtp:")) { 5347d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh delimiter = ' '; 5357d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } else if (type == 'b' || type == 'a') { 5367d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh delimiter = ':'; 5377d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5387d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int i = line.indexOf(delimiter); 5397d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (i == -1) { 5407d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh set(line, delimiter, ""); 5417d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } else { 5427d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh set(line.substring(0, i), delimiter, line.substring(i + 1)); 5437d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5447d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5457d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 5467d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 5477d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Finds the key with the given prefix and returns its suffix. 5487d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 5497d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private String[] cut(String prefix, char delimiter) { 5507d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String[] names = new String[mLines.size()]; 5517d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int length = 0; 5527d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (String line : mLines) { 5537d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (line.startsWith(prefix)) { 5547d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int i = line.indexOf(delimiter); 5557d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (i == -1) { 5567d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh i = line.length(); 5577d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5587d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh names[length] = line.substring(prefix.length(), i); 5597d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh ++length; 5607d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5617d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5627d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return Arrays.copyOf(names, length); 5637d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5647d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 5657d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 5667d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the index of the key. 5677d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 5687d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private int find(String key, char delimiter) { 5697d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int length = key.length(); 5707d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh for (int i = mLines.size() - 1; i >= 0; --i) { 5717d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String line = mLines.get(i); 5727d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (line.startsWith(key) && (line.length() == length || 5737d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh line.charAt(length) == delimiter)) { 5747d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return i; 5757d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5767d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5777d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return -1; 5787d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5797d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 5807d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 5817d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Sets the key with the value or removes the key if the value is 5827d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * {@code null}. 5837d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 5847d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private void set(String key, char delimiter, String value) { 5857d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int index = find(key, delimiter); 5867d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (value != null) { 5877d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (value.length() != 0) { 5887d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh key = key + delimiter + value; 5897d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5907d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (index == -1) { 5917d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mLines.add(key); 5927d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } else { 5937d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mLines.set(index, key); 5947d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5957d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } else if (index != -1) { 5967d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh mLines.remove(index); 5977d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5987d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 5997d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh 6007d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh /** 6017d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh * Returns the value of the key. 6027d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh */ 6037d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh private String get(String key, char delimiter) { 6047d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int index = find(key, delimiter); 6057d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh if (index == -1) { 6067d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return null; 6077d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 6087d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh String line = mLines.get(index); 6097d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh int length = key.length(); 6107d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh return (line.length() == length) ? "" : line.substring(length + 1); 6117d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 6127d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh } 6137d51a25fe714d14df79cf71d06cf83d88b479759Chia-chi Yeh} 614