1e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh/* 2e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Copyright (C) 2010 The Android Open Source Project 3e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * 4e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 5e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * you may not use this file except in compliance with the License. 6e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * You may obtain a copy of the License at 7e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * 8e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 9e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * 10e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 11e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 12e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * See the License for the specific language governing permissions and 14e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * limitations under the License. 15e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 16e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 17e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yehpackage android.net.sip; 18e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 19e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yehimport java.util.ArrayList; 20e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yehimport java.util.Arrays; 217314532349e402315af9b8f664432dd18292421fJohan Redestigimport java.util.Locale; 22e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 23e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh/** 24e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * An object used to manipulate messages of Session Description Protocol (SDP). 25e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * It is mainly designed for the uses of Session Initiation Protocol (SIP). 26e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Therefore, it only handles connection addresses ("c="), bandwidth limits, 27e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * ("b="), encryption keys ("k="), and attribute fields ("a="). Currently this 28e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * implementation does not support multicast sessions. 29e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * 30e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * <p>Here is an example code to create a session description.</p> 31e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * <pre> 32e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * SimpleSessionDescription description = new SimpleSessionDescription( 33e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * System.currentTimeMillis(), "1.2.3.4"); 34e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Media media = description.newMedia("audio", 56789, 1, "RTP/AVP"); 35e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * media.setRtpPayload(0, "PCMU/8000", null); 36e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * media.setRtpPayload(8, "PCMA/8000", null); 37e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * media.setRtpPayload(127, "telephone-event/8000", "0-15"); 38e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * media.setAttribute("sendrecv", ""); 39e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * </pre> 40e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * <p>Invoking <code>description.encode()</code> will produce a result like the 41e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * one below.</p> 42e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * <pre> 43e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * v=0 44e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * o=- 1284970442706 1284970442709 IN IP4 1.2.3.4 45e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * s=- 46e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * c=IN IP4 1.2.3.4 47e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * t=0 0 48e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * m=audio 56789 RTP/AVP 0 8 127 49e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * a=rtpmap:0 PCMU/8000 50e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * a=rtpmap:8 PCMA/8000 51e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * a=rtpmap:127 telephone-event/8000 52e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * a=fmtp:127 0-15 53e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * a=sendrecv 54e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * </pre> 55e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * @hide 56e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 57e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yehpublic class SimpleSessionDescription { 58e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final Fields mFields = new Fields("voscbtka"); 59e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final ArrayList<Media> mMedia = new ArrayList<Media>(); 60e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 61e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 62e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Creates a minimal session description from the given session ID and 63e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * unicast address. The address is used in the origin field ("o=") and the 64e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * connection field ("c="). See {@link SimpleSessionDescription} for an 65e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * example of its usage. 66e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 67e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public SimpleSessionDescription(long sessionId, String address) { 68e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + address; 69e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.parse("v=0"); 707314532349e402315af9b8f664432dd18292421fJohan Redestig mFields.parse(String.format(Locale.US, "o=- %d %d %s", sessionId, 71e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh System.currentTimeMillis(), address)); 72e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.parse("s=-"); 73e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.parse("t=0 0"); 74e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.parse("c=" + address); 75e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 76e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 77e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 78e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Creates a session description from the given message. 79e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * 80e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * @throws IllegalArgumentException if message is invalid. 81e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 82e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public SimpleSessionDescription(String message) { 83e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String[] lines = message.trim().replaceAll(" +", " ").split("[\r\n]+"); 84e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh Fields fields = mFields; 85e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 86e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (String line : lines) { 87e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh try { 88e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (line.charAt(1) != '=') { 89e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh throw new IllegalArgumentException(); 90e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 91e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (line.charAt(0) == 'm') { 92e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String[] parts = line.substring(2).split(" ", 4); 93e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String[] ports = parts[1].split("/", 2); 94e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh Media media = newMedia(parts[0], Integer.parseInt(ports[0]), 95e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh (ports.length < 2) ? 1 : Integer.parseInt(ports[1]), 96e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh parts[2]); 97e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (String format : parts[3].split(" ")) { 98e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh media.setFormat(format, null); 99e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 100e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh fields = media; 101e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } else { 102e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh fields.parse(line); 103e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 104e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } catch (Exception e) { 105e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh throw new IllegalArgumentException("Invalid SDP: " + line); 106e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 107e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 108e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 109e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 110e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 111e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Creates a new media description in this session description. 112e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * 113e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * @param type The media type, e.g. {@code "audio"}. 114e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * @param port The first transport port used by this media. 115e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * @param portCount The number of contiguous ports used by this media. 116e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * @param protocol The transport protocol, e.g. {@code "RTP/AVP"}. 117e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 118e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public Media newMedia(String type, int port, int portCount, 119e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String protocol) { 120e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh Media media = new Media(type, port, portCount, protocol); 121e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mMedia.add(media); 122e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return media; 123e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 124e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 125e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 126e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns all the media descriptions in this session description. 127e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 128e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public Media[] getMedia() { 129e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mMedia.toArray(new Media[mMedia.size()]); 130e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 131e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 132e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 133e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Encodes the session description and all its media descriptions in a 134e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * string. Note that the result might be incomplete if a required field 135e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * has never been added before. 136e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 137e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String encode() { 138e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh StringBuilder buffer = new StringBuilder(); 139e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.write(buffer); 140e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (Media media : mMedia) { 141e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh media.write(buffer); 142e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 143e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return buffer.toString(); 144e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 145e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 146e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 147e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the connection address or {@code null} if it is not present. 148e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 149e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getAddress() { 150e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getAddress(); 151e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 152e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 153e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 154e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the connection address. The field will be removed if the address 155e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * is {@code null}. 156e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 157e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setAddress(String address) { 158e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.setAddress(address); 159e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 160e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 161e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 162e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the encryption method or {@code null} if it is not present. 163e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 164e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getEncryptionMethod() { 165e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getEncryptionMethod(); 166e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 167e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 168e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 169e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the encryption key or {@code null} if it is not present. 170e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 171e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getEncryptionKey() { 172e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getEncryptionKey(); 173e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 174e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 175e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 176e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the encryption method and the encryption key. The field will be 177e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * removed if the method is {@code null}. 178e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 179e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setEncryption(String method, String key) { 180e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.setEncryption(method, key); 181e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 182e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 183e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 184e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the types of the bandwidth limits. 185e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 186e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String[] getBandwidthTypes() { 187e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getBandwidthTypes(); 188e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 189e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 190e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 191e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the bandwidth limit of the given type or {@code -1} if it is not 192e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * present. 193e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 194e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public int getBandwidth(String type) { 195e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getBandwidth(type); 196e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 197e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 198e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 199e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the bandwith limit for the given type. The field will be removed if 200e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * the value is negative. 201e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 202e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setBandwidth(String type, int value) { 203e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.setBandwidth(type, value); 204e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 205e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 206e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 207e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the names of all the attributes. 208e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 209e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String[] getAttributeNames() { 210e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getAttributeNames(); 211e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 212e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 213e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 214e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the attribute of the given name or {@code null} if it is not 215e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * present. 216e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 217e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getAttribute(String name) { 218e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFields.getAttribute(name); 219e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 220e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 221e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 222e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the attribute for the given name. The field will be removed if 223e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * the value is {@code null}. To set a binary attribute, use an empty 224e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * string as the value. 225e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 226e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setAttribute(String name, String value) { 227e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFields.setAttribute(name, value); 228e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 229e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 230e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 231e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * This class represents a media description of a session description. It 232e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * can only be created by {@link SimpleSessionDescription#newMedia}. Since 233e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * the syntax is more restricted for RTP based protocols, two sets of access 234e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * methods are implemented. See {@link SimpleSessionDescription} for an 235e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * example of its usage. 236e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 237e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public static class Media extends Fields { 238e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final String mType; 239e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final int mPort; 240e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final int mPortCount; 241e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final String mProtocol; 242e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private ArrayList<String> mFormats = new ArrayList<String>(); 243e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 244e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private Media(String type, int port, int portCount, String protocol) { 245e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super("icbka"); 246e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mType = type; 247e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mPort = port; 248e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mPortCount = portCount; 249e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mProtocol = protocol; 250e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 251e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 252e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 253e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the media type. 254e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 255e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getType() { 256e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mType; 257e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 258e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 259e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 260e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the first transport port used by this media. 261e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 262e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public int getPort() { 263e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mPort; 264e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 265e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 266e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 267e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the number of contiguous ports used by this media. 268e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 269e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public int getPortCount() { 270e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mPortCount; 271e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 272e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 273e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 274e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the transport protocol. 275e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 276e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getProtocol() { 277e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mProtocol; 278e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 279e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 280e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 281e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the media formats. 282e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 283e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String[] getFormats() { 284e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return mFormats.toArray(new String[mFormats.size()]); 285e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 286e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 287e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 288e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the {@code fmtp} attribute of the given format or 289e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * {@code null} if it is not present. 290e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 291e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getFmtp(String format) { 292e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return super.get("a=fmtp:" + format, ' '); 293e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 294e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 295e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 296e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets a format and its {@code fmtp} attribute. If the attribute is 297e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * {@code null}, the corresponding field will be removed. 298e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 299e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setFormat(String format, String fmtp) { 300e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFormats.remove(format); 301e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFormats.add(format); 302e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.set("a=rtpmap:" + format, ' ', null); 303e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.set("a=fmtp:" + format, ' ', fmtp); 304e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 305e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 306e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 307e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Removes a format and its {@code fmtp} attribute. 308e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 309e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void removeFormat(String format) { 310e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFormats.remove(format); 311e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.set("a=rtpmap:" + format, ' ', null); 312e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.set("a=fmtp:" + format, ' ', null); 313e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 314e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 315e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 316e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the RTP payload types. 317e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 318e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public int[] getRtpPayloadTypes() { 319e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int[] types = new int[mFormats.size()]; 320e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int length = 0; 321e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (String format : mFormats) { 322e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh try { 323e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh types[length] = Integer.parseInt(format); 324e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh ++length; 325e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } catch (NumberFormatException e) { } 326e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 327e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return Arrays.copyOf(types, length); 328e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 329e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 330e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 331e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the {@code rtpmap} attribute of the given RTP payload type 332e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * or {@code null} if it is not present. 333e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 334e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getRtpmap(int type) { 335e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return super.get("a=rtpmap:" + type, ' '); 336e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 337e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 338e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 339e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the {@code fmtp} attribute of the given RTP payload type or 340e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * {@code null} if it is not present. 341e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 342e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getFmtp(int type) { 343e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return super.get("a=fmtp:" + type, ' '); 344e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 345e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 346e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 3470b7d6de1559a4a78af76ab501e0a15afc396c2b9repo sync * Sets a RTP payload type and its {@code rtpmap} and {@code fmtp} 348e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * attributes. If any of the attributes is {@code null}, the 349e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * corresponding field will be removed. See 350e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * {@link SimpleSessionDescription} for an example of its usage. 351e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 352e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setRtpPayload(int type, String rtpmap, String fmtp) { 353e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String format = String.valueOf(type); 354e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFormats.remove(format); 355e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mFormats.add(format); 356e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.set("a=rtpmap:" + format, ' ', rtpmap); 357e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.set("a=fmtp:" + format, ' ', fmtp); 358e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 359e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 360e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 361e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Removes a RTP payload and its {@code rtpmap} and {@code fmtp} 362e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * attributes. 363e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 364e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void removeRtpPayload(int type) { 365e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh removeFormat(String.valueOf(type)); 366e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 367e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 368e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private void write(StringBuilder buffer) { 369e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh buffer.append("m=").append(mType).append(' ').append(mPort); 370e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (mPortCount != 1) { 371e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh buffer.append('/').append(mPortCount); 372e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 373e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh buffer.append(' ').append(mProtocol); 374e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (String format : mFormats) { 375e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh buffer.append(' ').append(format); 376e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 377e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh buffer.append("\r\n"); 378e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh super.write(buffer); 379e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 380e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 381e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 382e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 383e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * This class acts as a set of fields, and the size of the set is expected 384e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * to be small. Therefore, it uses a simple list instead of maps. Each field 385e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * has three parts: a key, a delimiter, and a value. Delimiters are special 386e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * because they are not included in binary attributes. As a result, the 387e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * private methods, which are the building blocks of this class, all take 388e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * the delimiter as an argument. 389e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 390e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private static class Fields { 391e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final String mOrder; 392e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private final ArrayList<String> mLines = new ArrayList<String>(); 393e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 394e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh Fields(String order) { 395e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mOrder = order; 396e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 397e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 398e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 399e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the connection address or {@code null} if it is not present. 400e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 401e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getAddress() { 402e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String address = get("c", '='); 403e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (address == null) { 404e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return null; 405e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 406e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String[] parts = address.split(" "); 407e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (parts.length != 3) { 408e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return null; 409e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 410e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int slash = parts[2].indexOf('/'); 411e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return (slash < 0) ? parts[2] : parts[2].substring(0, slash); 412e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 413e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 414e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 415e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the connection address. The field will be removed if the address 416e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * is {@code null}. 417e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 418e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setAddress(String address) { 419e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (address != null) { 420e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + 421e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh address; 422e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 423e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh set("c", '=', address); 424e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 425e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 426e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 427e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the encryption method or {@code null} if it is not present. 428e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 429e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getEncryptionMethod() { 430e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String encryption = get("k", '='); 431e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (encryption == null) { 432e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return null; 433e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 434e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int colon = encryption.indexOf(':'); 435e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return (colon == -1) ? encryption : encryption.substring(0, colon); 436e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 437e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 438e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 439e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the encryption key or {@code null} if it is not present. 440e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 441e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getEncryptionKey() { 442e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String encryption = get("k", '='); 443e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (encryption == null) { 444e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return null; 445e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 446e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int colon = encryption.indexOf(':'); 447e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return (colon == -1) ? null : encryption.substring(0, colon + 1); 448e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 449e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 450e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 451e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the encryption method and the encryption key. The field will be 452e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * removed if the method is {@code null}. 453e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 454e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setEncryption(String method, String key) { 455e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh set("k", '=', (method == null || key == null) ? 456e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh method : method + ':' + key); 457e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 458e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 459e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 460e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the types of the bandwidth limits. 461e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 462e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String[] getBandwidthTypes() { 463e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return cut("b=", ':'); 464e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 465e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 466e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 467e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the bandwidth limit of the given type or {@code -1} if it is 468e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * not present. 469e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 470e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public int getBandwidth(String type) { 471e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String value = get("b=" + type, ':'); 472e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (value != null) { 473e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh try { 474e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return Integer.parseInt(value); 475e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } catch (NumberFormatException e) { } 476e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh setBandwidth(type, -1); 477e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 478e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return -1; 479e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 480e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 481e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 482e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the bandwith limit for the given type. The field will be removed 483e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * if the value is negative. 484e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 485e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setBandwidth(String type, int value) { 486e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh set("b=" + type, ':', (value < 0) ? null : String.valueOf(value)); 487e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 488e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 489e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 490e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the names of all the attributes. 491e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 492e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String[] getAttributeNames() { 493e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return cut("a=", ':'); 494e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 495e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 496e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 497e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the attribute of the given name or {@code null} if it is not 498e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * present. 499e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 500e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public String getAttribute(String name) { 501e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return get("a=" + name, ':'); 502e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 503e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 504e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 505e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the attribute for the given name. The field will be removed if 506e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * the value is {@code null}. To set a binary attribute, use an empty 507e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * string as the value. 508e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 509e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh public void setAttribute(String name, String value) { 510e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh set("a=" + name, ':', value); 511e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 512e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 513e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private void write(StringBuilder buffer) { 514e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (int i = 0; i < mOrder.length(); ++i) { 515e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh char type = mOrder.charAt(i); 516e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (String line : mLines) { 517e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (line.charAt(0) == type) { 518e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh buffer.append(line).append("\r\n"); 519e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 520e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 521e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 522e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 523e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 524e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 525e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Invokes {@link #set} after splitting the line into three parts. 526e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 527e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private void parse(String line) { 528e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh char type = line.charAt(0); 529e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (mOrder.indexOf(type) == -1) { 530e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return; 531e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 532e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh char delimiter = '='; 533e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (line.startsWith("a=rtpmap:") || line.startsWith("a=fmtp:")) { 534e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh delimiter = ' '; 535e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } else if (type == 'b' || type == 'a') { 536e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh delimiter = ':'; 537e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 538e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int i = line.indexOf(delimiter); 539e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (i == -1) { 540e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh set(line, delimiter, ""); 541e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } else { 542e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh set(line.substring(0, i), delimiter, line.substring(i + 1)); 543e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 544e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 545e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 546e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 547e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Finds the key with the given prefix and returns its suffix. 548e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 549e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private String[] cut(String prefix, char delimiter) { 550e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String[] names = new String[mLines.size()]; 551e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int length = 0; 552e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (String line : mLines) { 553e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (line.startsWith(prefix)) { 554e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int i = line.indexOf(delimiter); 555e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (i == -1) { 556e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh i = line.length(); 557e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 558e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh names[length] = line.substring(prefix.length(), i); 559e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh ++length; 560e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 561e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 562e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return Arrays.copyOf(names, length); 563e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 564e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 565e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 566e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the index of the key. 567e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 568e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private int find(String key, char delimiter) { 569e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int length = key.length(); 570e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh for (int i = mLines.size() - 1; i >= 0; --i) { 571e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String line = mLines.get(i); 572e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (line.startsWith(key) && (line.length() == length || 573e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh line.charAt(length) == delimiter)) { 574e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return i; 575e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 576e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 577e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return -1; 578e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 579e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 580e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 581e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Sets the key with the value or removes the key if the value is 582e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * {@code null}. 583e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 584e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private void set(String key, char delimiter, String value) { 585e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int index = find(key, delimiter); 586e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (value != null) { 587e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (value.length() != 0) { 588e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh key = key + delimiter + value; 589e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 590e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (index == -1) { 591e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mLines.add(key); 592e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } else { 593e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mLines.set(index, key); 594e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 595e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } else if (index != -1) { 596e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh mLines.remove(index); 597e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 598e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 599e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh 600e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh /** 601e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh * Returns the value of the key. 602e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh */ 603e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh private String get(String key, char delimiter) { 604e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int index = find(key, delimiter); 605e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh if (index == -1) { 606e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return null; 607e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 608e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh String line = mLines.get(index); 609e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh int length = key.length(); 610e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh return (line.length() == length) ? "" : line.substring(length + 1); 611e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 612e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh } 613e6c0c109588771a97aba51d06fdf73557b06dfd3Chia-chi Yeh} 614