net.sourceforge.peers.sdp.SdpParser Maven / Gradle / Ivy
/*
This file is part of Peers, a java SIP softphone.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Copyright 2007, 2008, 2009, 2010 Yohann Martineau
*/
package net.sourceforge.peers.sdp;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import net.sourceforge.peers.rtp.RFC3551;
public class SdpParser {
public SessionDescription parse(byte[] body) throws IOException {
if (body == null || body.length == 0) {
return null;
}
ByteArrayInputStream in = new ByteArrayInputStream(body);
InputStreamReader inputStreamReader = new InputStreamReader(in);
BufferedReader reader = new BufferedReader(inputStreamReader);
SessionDescription sessionDescription = new SessionDescription();
//version
String line = reader.readLine();
if (line.length() < 3) {
return null;
}
if (line.charAt(0) != RFC4566.TYPE_VERSION
|| line.charAt(1) != RFC4566.SEPARATOR
|| line.charAt(2) != RFC4566.VERSION) {
return null;
}
//origin
line = reader.readLine();
if (line.length() < 3) {
return null;
}
if (line.charAt(0) != RFC4566.TYPE_ORIGIN
|| line.charAt(1) != RFC4566.SEPARATOR) {
return null;
}
line = line.substring(2);
String[] originArr = line.split(" ");
if (originArr == null || originArr.length != 6) {
return null;
}
sessionDescription.setUsername(originArr[0]);
sessionDescription.setId(Long.parseLong(originArr[1]));
sessionDescription.setVersion(Long.parseLong(originArr[2]));
sessionDescription.setIpAddress(InetAddress.getByName(originArr[5]));
//name
line = reader.readLine();
if (line.length() < 3) {
return null;
}
if (line.charAt(0) != RFC4566.TYPE_SUBJECT
|| line.charAt(1) != RFC4566.SEPARATOR) {
return null;
}
sessionDescription.setName(line.substring(2));
//session connection and attributes
Hashtable sessionAttributes = new Hashtable();
sessionDescription.setAttributes(sessionAttributes);
while ((line = reader.readLine()) != null
&& line.charAt(0) != RFC4566.TYPE_MEDIA) {
if (line.length() > 3
&& line.charAt(0) == RFC4566.TYPE_CONNECTION
&& line.charAt(1) == RFC4566.SEPARATOR) {
String connection = parseConnection(line.substring(2));
if (connection == null) {
continue;
}
sessionDescription.setIpAddress(InetAddress.getByName(connection));
} else if (line.length() > 3
&& line.charAt(0) == RFC4566.TYPE_ATTRIBUTE
&& line.charAt(1) == RFC4566.SEPARATOR) {
String value = line.substring(2);
int pos = value.indexOf(RFC4566.ATTR_SEPARATOR);
if (pos > -1) {
sessionAttributes.put(value.substring(0, pos),
value.substring(pos + 1));
} else {
sessionAttributes.put(value, "");
}
}
}
if (line == null) {
return null;
}
//we are at the first media line
ArrayList mediaLines = new ArrayList();
do {
if (line.length() < 3) {
return null;
}
if (line.charAt(1) != RFC4566.SEPARATOR) {
return null;
}
SdpLine mediaLine = new SdpLine();
mediaLine.setType(line.charAt(0));
mediaLine.setValue(line.substring(2));
mediaLines.add(mediaLine);
}
while ((line = reader.readLine()) != null);
ArrayList mediaDescriptions = new ArrayList();
sessionDescription.setMediaDescriptions(mediaDescriptions);
for (SdpLine sdpLine : mediaLines) {
MediaDescription mediaDescription;
if (sdpLine.getType() == RFC4566.TYPE_MEDIA) {
String[] mediaArr = sdpLine.getValue().split(" ");
if (mediaArr == null || mediaArr.length < 4) {
return null;
}
mediaDescription = new MediaDescription();
mediaDescription.setType(mediaArr[0]);
//TODO manage port range
mediaDescription.setPort(Integer.parseInt(mediaArr[1]));
mediaDescription.setAttributes(new Hashtable());
List codecs = new ArrayList();
for (int i = 3; i < mediaArr.length; ++i) {
int payloadType = Integer.parseInt(mediaArr[i]);
Codec codec = new Codec();
codec.setPayloadType(payloadType);
String name;
switch (payloadType) {
case RFC3551.PAYLOAD_TYPE_PCMU:
name = RFC3551.PCMU;
break;
case RFC3551.PAYLOAD_TYPE_PCMA:
name = RFC3551.PCMA;
break;
default:
name = "unsupported";
break;
}
codec.setName(name);
codecs.add(codec);
//TODO check that sdp offer without rtpmap works
}
mediaDescription.setCodecs(codecs);
mediaDescriptions.add(mediaDescription);
} else {
mediaDescription = mediaDescriptions.get(mediaDescriptions.size() - 1);
String sdpLineValue = sdpLine.getValue();
if (sdpLine.getType() == RFC4566.TYPE_CONNECTION) {
String ipAddress = parseConnection(sdpLineValue);
mediaDescription.setIpAddress(InetAddress.getByName(ipAddress));
} else if (sdpLine.getType() == RFC4566.TYPE_ATTRIBUTE) {
Hashtable attributes = mediaDescription.getAttributes();
int pos = sdpLineValue.indexOf(RFC4566.ATTR_SEPARATOR);
if (pos > -1) {
String name = sdpLineValue.substring(0, pos);
String value = sdpLineValue.substring(pos + 1);
pos = value.indexOf(" ");
if (pos > -1) {
int payloadType;
try {
payloadType = Integer.parseInt(value.substring(0, pos));
List codecs = mediaDescription.getCodecs();
for (Codec codec: codecs) {
if (codec.getPayloadType() == payloadType) {
value = value.substring(pos + 1);
pos = value.indexOf("/");
if (pos > -1) {
value = value.substring(0, pos);
codec.setName(value);
}
break;
}
}
} catch (NumberFormatException e) {
attributes.put(name, value);
}
} else {
attributes.put(name, value);
}
} else {
attributes.put(sdpLineValue, "");
}
}
}
}
sessionDescription.setMediaDescriptions(mediaDescriptions);
for (MediaDescription description : mediaDescriptions) {
if (description.getIpAddress() == null) {
InetAddress sessionAddress = sessionDescription.getIpAddress();
if (sessionAddress == null) {
return null;
}
description.setIpAddress(sessionAddress);
}
}
return sessionDescription;
}
private String parseConnection(String line) {
String[] connectionArr = line.split(" ");
if (connectionArr == null || connectionArr.length != 3) {
return null;
}
return connectionArr[2];
}
}