1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.libraries.rcs.simpleclient.protocol.sdp; 18 19 import android.text.TextUtils; 20 21 import com.google.auto.value.AutoValue; 22 import com.google.common.base.Splitter; 23 import com.google.common.collect.ImmutableMap; 24 25 import java.text.ParseException; 26 import java.util.List; 27 import java.util.Map; 28 29 /** 30 * The media part of SDP implementation as per RFC 4566. This class supports minimal fields that is 31 * required to represent MSRP session. 32 */ 33 @AutoValue 34 public abstract class SdpMedia { 35 private static final String CRLF = "\r\n"; 36 parseMediaLine(String line)37 public static Builder parseMediaLine(String line) throws ParseException { 38 List<String> elements = Splitter.on(" ").limit(4).splitToList(line); 39 40 // The valid media line should have 4 elements: 41 // m=<name> <port> <protocol> <format> 42 if (elements.size() != 4) { 43 throw new ParseException("Invalid media line", 0); 44 } 45 46 // Parse each field from the media line. 47 Builder builder = SdpMedia.newBuilder(); 48 builder 49 .setName(elements.get(0)) 50 .setPort(Integer.parseInt(elements.get(1))) 51 .setProtocol(elements.get(2)) 52 .setFormat(elements.get(3)); 53 54 return builder; 55 } 56 newBuilder()57 public static Builder newBuilder() { 58 return new AutoValue_SdpMedia.Builder(); 59 } 60 name()61 public abstract String name(); 62 port()63 public abstract int port(); 64 protocol()65 public abstract String protocol(); 66 format()67 public abstract String format(); 68 attributes()69 public abstract ImmutableMap<String, String> attributes(); 70 71 /** Encode the media section as a string. */ encode()72 public String encode() { 73 StringBuilder builder = new StringBuilder(); 74 builder 75 .append("m=") 76 .append(name()) 77 .append(" ") 78 .append(port()) 79 .append(" ") 80 .append(protocol()) 81 .append(" ") 82 .append(format()) 83 .append(CRLF); 84 85 for (Map.Entry<String, String> attribute : attributes().entrySet()) { 86 builder.append("a=").append(attribute.getKey()); 87 if (!TextUtils.isEmpty(attribute.getValue())) { 88 builder.append(":").append(attribute.getValue()); 89 } 90 builder.append(CRLF); 91 } 92 93 return builder.toString(); 94 } 95 96 @AutoValue.Builder 97 public abstract static class Builder { setName(String name)98 public abstract Builder setName(String name); 99 setPort(int port)100 public abstract Builder setPort(int port); 101 setProtocol(String protocol)102 public abstract Builder setProtocol(String protocol); 103 setFormat(String payload)104 public abstract Builder setFormat(String payload); 105 attributesBuilder()106 public abstract ImmutableMap.Builder<String, String> attributesBuilder(); 107 addAttribute(String name, String value)108 public Builder addAttribute(String name, String value) { 109 attributesBuilder().put(name, value); 110 return this; 111 } 112 addAttribute(String name)113 public Builder addAttribute(String name) { 114 return addAttribute(name, ""); 115 } 116 build()117 public abstract SdpMedia build(); 118 } 119 } 120