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