diff options
Diffstat (limited to 'voip/java/android/net/sip/SimpleSessionDescription.java')
-rw-r--r-- | voip/java/android/net/sip/SimpleSessionDescription.java | 613 |
1 files changed, 0 insertions, 613 deletions
diff --git a/voip/java/android/net/sip/SimpleSessionDescription.java b/voip/java/android/net/sip/SimpleSessionDescription.java deleted file mode 100644 index 9fcd21dca256..000000000000 --- a/voip/java/android/net/sip/SimpleSessionDescription.java +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.sip; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; - -/** - * An object used to manipulate messages of Session Description Protocol (SDP). - * It is mainly designed for the uses of Session Initiation Protocol (SIP). - * Therefore, it only handles connection addresses ("c="), bandwidth limits, - * ("b="), encryption keys ("k="), and attribute fields ("a="). Currently this - * implementation does not support multicast sessions. - * - * <p>Here is an example code to create a session description.</p> - * <pre> - * SimpleSessionDescription description = new SimpleSessionDescription( - * System.currentTimeMillis(), "1.2.3.4"); - * Media media = description.newMedia("audio", 56789, 1, "RTP/AVP"); - * media.setRtpPayload(0, "PCMU/8000", null); - * media.setRtpPayload(8, "PCMA/8000", null); - * media.setRtpPayload(127, "telephone-event/8000", "0-15"); - * media.setAttribute("sendrecv", ""); - * </pre> - * <p>Invoking <code>description.encode()</code> will produce a result like the - * one below.</p> - * <pre> - * v=0 - * o=- 1284970442706 1284970442709 IN IP4 1.2.3.4 - * s=- - * c=IN IP4 1.2.3.4 - * t=0 0 - * m=audio 56789 RTP/AVP 0 8 127 - * a=rtpmap:0 PCMU/8000 - * a=rtpmap:8 PCMA/8000 - * a=rtpmap:127 telephone-event/8000 - * a=fmtp:127 0-15 - * a=sendrecv - * </pre> - * @hide - */ -public class SimpleSessionDescription { - private final Fields mFields = new Fields("voscbtka"); - private final ArrayList<Media> mMedia = new ArrayList<Media>(); - - /** - * Creates a minimal session description from the given session ID and - * unicast address. The address is used in the origin field ("o=") and the - * connection field ("c="). See {@link SimpleSessionDescription} for an - * example of its usage. - */ - public SimpleSessionDescription(long sessionId, String address) { - address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + address; - mFields.parse("v=0"); - mFields.parse(String.format(Locale.US, "o=- %d %d %s", sessionId, - System.currentTimeMillis(), address)); - mFields.parse("s=-"); - mFields.parse("t=0 0"); - mFields.parse("c=" + address); - } - - /** - * Creates a session description from the given message. - * - * @throws IllegalArgumentException if message is invalid. - */ - public SimpleSessionDescription(String message) { - String[] lines = message.trim().replaceAll(" +", " ").split("[\r\n]+"); - Fields fields = mFields; - - for (String line : lines) { - try { - if (line.charAt(1) != '=') { - throw new IllegalArgumentException(); - } - if (line.charAt(0) == 'm') { - String[] parts = line.substring(2).split(" ", 4); - String[] ports = parts[1].split("/", 2); - Media media = newMedia(parts[0], Integer.parseInt(ports[0]), - (ports.length < 2) ? 1 : Integer.parseInt(ports[1]), - parts[2]); - for (String format : parts[3].split(" ")) { - media.setFormat(format, null); - } - fields = media; - } else { - fields.parse(line); - } - } catch (Exception e) { - throw new IllegalArgumentException("Invalid SDP: " + line); - } - } - } - - /** - * Creates a new media description in this session description. - * - * @param type The media type, e.g. {@code "audio"}. - * @param port The first transport port used by this media. - * @param portCount The number of contiguous ports used by this media. - * @param protocol The transport protocol, e.g. {@code "RTP/AVP"}. - */ - public Media newMedia(String type, int port, int portCount, - String protocol) { - Media media = new Media(type, port, portCount, protocol); - mMedia.add(media); - return media; - } - - /** - * Returns all the media descriptions in this session description. - */ - public Media[] getMedia() { - return mMedia.toArray(new Media[mMedia.size()]); - } - - /** - * Encodes the session description and all its media descriptions in a - * string. Note that the result might be incomplete if a required field - * has never been added before. - */ - public String encode() { - StringBuilder buffer = new StringBuilder(); - mFields.write(buffer); - for (Media media : mMedia) { - media.write(buffer); - } - return buffer.toString(); - } - - /** - * Returns the connection address or {@code null} if it is not present. - */ - public String getAddress() { - return mFields.getAddress(); - } - - /** - * Sets the connection address. The field will be removed if the address - * is {@code null}. - */ - public void setAddress(String address) { - mFields.setAddress(address); - } - - /** - * Returns the encryption method or {@code null} if it is not present. - */ - public String getEncryptionMethod() { - return mFields.getEncryptionMethod(); - } - - /** - * Returns the encryption key or {@code null} if it is not present. - */ - public String getEncryptionKey() { - return mFields.getEncryptionKey(); - } - - /** - * Sets the encryption method and the encryption key. The field will be - * removed if the method is {@code null}. - */ - public void setEncryption(String method, String key) { - mFields.setEncryption(method, key); - } - - /** - * Returns the types of the bandwidth limits. - */ - public String[] getBandwidthTypes() { - return mFields.getBandwidthTypes(); - } - - /** - * Returns the bandwidth limit of the given type or {@code -1} if it is not - * present. - */ - public int getBandwidth(String type) { - return mFields.getBandwidth(type); - } - - /** - * Sets the bandwith limit for the given type. The field will be removed if - * the value is negative. - */ - public void setBandwidth(String type, int value) { - mFields.setBandwidth(type, value); - } - - /** - * Returns the names of all the attributes. - */ - public String[] getAttributeNames() { - return mFields.getAttributeNames(); - } - - /** - * Returns the attribute of the given name or {@code null} if it is not - * present. - */ - public String getAttribute(String name) { - return mFields.getAttribute(name); - } - - /** - * Sets the attribute for the given name. The field will be removed if - * the value is {@code null}. To set a binary attribute, use an empty - * string as the value. - */ - public void setAttribute(String name, String value) { - mFields.setAttribute(name, value); - } - - /** - * This class represents a media description of a session description. It - * can only be created by {@link SimpleSessionDescription#newMedia}. Since - * the syntax is more restricted for RTP based protocols, two sets of access - * methods are implemented. See {@link SimpleSessionDescription} for an - * example of its usage. - */ - public static class Media extends Fields { - private final String mType; - private final int mPort; - private final int mPortCount; - private final String mProtocol; - private ArrayList<String> mFormats = new ArrayList<String>(); - - private Media(String type, int port, int portCount, String protocol) { - super("icbka"); - mType = type; - mPort = port; - mPortCount = portCount; - mProtocol = protocol; - } - - /** - * Returns the media type. - */ - public String getType() { - return mType; - } - - /** - * Returns the first transport port used by this media. - */ - public int getPort() { - return mPort; - } - - /** - * Returns the number of contiguous ports used by this media. - */ - public int getPortCount() { - return mPortCount; - } - - /** - * Returns the transport protocol. - */ - public String getProtocol() { - return mProtocol; - } - - /** - * Returns the media formats. - */ - public String[] getFormats() { - return mFormats.toArray(new String[mFormats.size()]); - } - - /** - * Returns the {@code fmtp} attribute of the given format or - * {@code null} if it is not present. - */ - public String getFmtp(String format) { - return super.get("a=fmtp:" + format, ' '); - } - - /** - * Sets a format and its {@code fmtp} attribute. If the attribute is - * {@code null}, the corresponding field will be removed. - */ - public void setFormat(String format, String fmtp) { - mFormats.remove(format); - mFormats.add(format); - super.set("a=rtpmap:" + format, ' ', null); - super.set("a=fmtp:" + format, ' ', fmtp); - } - - /** - * Removes a format and its {@code fmtp} attribute. - */ - public void removeFormat(String format) { - mFormats.remove(format); - super.set("a=rtpmap:" + format, ' ', null); - super.set("a=fmtp:" + format, ' ', null); - } - - /** - * Returns the RTP payload types. - */ - public int[] getRtpPayloadTypes() { - int[] types = new int[mFormats.size()]; - int length = 0; - for (String format : mFormats) { - try { - types[length] = Integer.parseInt(format); - ++length; - } catch (NumberFormatException e) { } - } - return Arrays.copyOf(types, length); - } - - /** - * Returns the {@code rtpmap} attribute of the given RTP payload type - * or {@code null} if it is not present. - */ - public String getRtpmap(int type) { - return super.get("a=rtpmap:" + type, ' '); - } - - /** - * Returns the {@code fmtp} attribute of the given RTP payload type or - * {@code null} if it is not present. - */ - public String getFmtp(int type) { - return super.get("a=fmtp:" + type, ' '); - } - - /** - * Sets a RTP payload type and its {@code rtpmap} and {@code fmtp} - * attributes. If any of the attributes is {@code null}, the - * corresponding field will be removed. See - * {@link SimpleSessionDescription} for an example of its usage. - */ - public void setRtpPayload(int type, String rtpmap, String fmtp) { - String format = String.valueOf(type); - mFormats.remove(format); - mFormats.add(format); - super.set("a=rtpmap:" + format, ' ', rtpmap); - super.set("a=fmtp:" + format, ' ', fmtp); - } - - /** - * Removes a RTP payload and its {@code rtpmap} and {@code fmtp} - * attributes. - */ - public void removeRtpPayload(int type) { - removeFormat(String.valueOf(type)); - } - - private void write(StringBuilder buffer) { - buffer.append("m=").append(mType).append(' ').append(mPort); - if (mPortCount != 1) { - buffer.append('/').append(mPortCount); - } - buffer.append(' ').append(mProtocol); - for (String format : mFormats) { - buffer.append(' ').append(format); - } - buffer.append("\r\n"); - super.write(buffer); - } - } - - /** - * This class acts as a set of fields, and the size of the set is expected - * to be small. Therefore, it uses a simple list instead of maps. Each field - * has three parts: a key, a delimiter, and a value. Delimiters are special - * because they are not included in binary attributes. As a result, the - * private methods, which are the building blocks of this class, all take - * the delimiter as an argument. - */ - private static class Fields { - private final String mOrder; - private final ArrayList<String> mLines = new ArrayList<String>(); - - Fields(String order) { - mOrder = order; - } - - /** - * Returns the connection address or {@code null} if it is not present. - */ - public String getAddress() { - String address = get("c", '='); - if (address == null) { - return null; - } - String[] parts = address.split(" "); - if (parts.length != 3) { - return null; - } - int slash = parts[2].indexOf('/'); - return (slash < 0) ? parts[2] : parts[2].substring(0, slash); - } - - /** - * Sets the connection address. The field will be removed if the address - * is {@code null}. - */ - public void setAddress(String address) { - if (address != null) { - address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + - address; - } - set("c", '=', address); - } - - /** - * Returns the encryption method or {@code null} if it is not present. - */ - public String getEncryptionMethod() { - String encryption = get("k", '='); - if (encryption == null) { - return null; - } - int colon = encryption.indexOf(':'); - return (colon == -1) ? encryption : encryption.substring(0, colon); - } - - /** - * Returns the encryption key or {@code null} if it is not present. - */ - public String getEncryptionKey() { - String encryption = get("k", '='); - if (encryption == null) { - return null; - } - int colon = encryption.indexOf(':'); - return (colon == -1) ? null : encryption.substring(0, colon + 1); - } - - /** - * Sets the encryption method and the encryption key. The field will be - * removed if the method is {@code null}. - */ - public void setEncryption(String method, String key) { - set("k", '=', (method == null || key == null) ? - method : method + ':' + key); - } - - /** - * Returns the types of the bandwidth limits. - */ - public String[] getBandwidthTypes() { - return cut("b=", ':'); - } - - /** - * Returns the bandwidth limit of the given type or {@code -1} if it is - * not present. - */ - public int getBandwidth(String type) { - String value = get("b=" + type, ':'); - if (value != null) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { } - setBandwidth(type, -1); - } - return -1; - } - - /** - * Sets the bandwith limit for the given type. The field will be removed - * if the value is negative. - */ - public void setBandwidth(String type, int value) { - set("b=" + type, ':', (value < 0) ? null : String.valueOf(value)); - } - - /** - * Returns the names of all the attributes. - */ - public String[] getAttributeNames() { - return cut("a=", ':'); - } - - /** - * Returns the attribute of the given name or {@code null} if it is not - * present. - */ - public String getAttribute(String name) { - return get("a=" + name, ':'); - } - - /** - * Sets the attribute for the given name. The field will be removed if - * the value is {@code null}. To set a binary attribute, use an empty - * string as the value. - */ - public void setAttribute(String name, String value) { - set("a=" + name, ':', value); - } - - private void write(StringBuilder buffer) { - for (int i = 0; i < mOrder.length(); ++i) { - char type = mOrder.charAt(i); - for (String line : mLines) { - if (line.charAt(0) == type) { - buffer.append(line).append("\r\n"); - } - } - } - } - - /** - * Invokes {@link #set} after splitting the line into three parts. - */ - private void parse(String line) { - char type = line.charAt(0); - if (mOrder.indexOf(type) == -1) { - return; - } - char delimiter = '='; - if (line.startsWith("a=rtpmap:") || line.startsWith("a=fmtp:")) { - delimiter = ' '; - } else if (type == 'b' || type == 'a') { - delimiter = ':'; - } - int i = line.indexOf(delimiter); - if (i == -1) { - set(line, delimiter, ""); - } else { - set(line.substring(0, i), delimiter, line.substring(i + 1)); - } - } - - /** - * Finds the key with the given prefix and returns its suffix. - */ - private String[] cut(String prefix, char delimiter) { - String[] names = new String[mLines.size()]; - int length = 0; - for (String line : mLines) { - if (line.startsWith(prefix)) { - int i = line.indexOf(delimiter); - if (i == -1) { - i = line.length(); - } - names[length] = line.substring(prefix.length(), i); - ++length; - } - } - return Arrays.copyOf(names, length); - } - - /** - * Returns the index of the key. - */ - private int find(String key, char delimiter) { - int length = key.length(); - for (int i = mLines.size() - 1; i >= 0; --i) { - String line = mLines.get(i); - if (line.startsWith(key) && (line.length() == length || - line.charAt(length) == delimiter)) { - return i; - } - } - return -1; - } - - /** - * Sets the key with the value or removes the key if the value is - * {@code null}. - */ - private void set(String key, char delimiter, String value) { - int index = find(key, delimiter); - if (value != null) { - if (value.length() != 0) { - key = key + delimiter + value; - } - if (index == -1) { - mLines.add(key); - } else { - mLines.set(index, key); - } - } else if (index != -1) { - mLines.remove(index); - } - } - - /** - * Returns the value of the key. - */ - private String get(String key, char delimiter) { - int index = find(key, delimiter); - if (index == -1) { - return null; - } - String line = mLines.get(index); - int length = key.length(); - return (line.length() == length) ? "" : line.substring(length + 1); - } - } -} |