public static SDP ParseSDPDescription(string sdpDescription)
{
try
{
if (sdpDescription != null && sdpDescription.Trim().Length > 0)
{
SDP sdp = new SDP();
sdp.m_rawSdp = sdpDescription;
SDPMediaAnnouncement activeAnnouncement = null;
string[] sdpLines = Regex.Split(sdpDescription, CRLF);
foreach (string sdpLine in sdpLines)
{
string sdpLineTrimmed = sdpLine.Trim();
if (sdpLineTrimmed.StartsWith("v="))
{
if (!Decimal.TryParse(sdpLineTrimmed.Substring(2), out sdp.Version))
{
logger.LogWarning("The Version value in an SDP description could not be parsed as a decimal: " + sdpLine + ".");
}
}
else if (sdpLineTrimmed.StartsWith("o="))
{
string[] ownerFields = sdpLineTrimmed.Substring(2).Split(' ');
sdp.Username = ownerFields[0];
sdp.SessionId = ownerFields[1];
Int32.TryParse(ownerFields[2], out sdp.AnnouncementVersion);
sdp.NetworkType = ownerFields[3];
sdp.AddressType = ownerFields[4];
sdp.AddressOrHost = ownerFields[5];
}
else if (sdpLineTrimmed.StartsWith("s="))
{
sdp.SessionName = sdpLineTrimmed.Substring(2);
}
else if (sdpLineTrimmed.StartsWith("c="))
{
if (sdp.Connection == null)
{
sdp.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLineTrimmed);
}
if (activeAnnouncement != null)
{
activeAnnouncement.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLineTrimmed);
}
}
else if (sdpLineTrimmed.StartsWith("b="))
{
if (activeAnnouncement != null)
{
activeAnnouncement.BandwidthAttributes.Add(sdpLineTrimmed.Substring(2));
}
else
{
sdp.BandwidthAttributes.Add(sdpLineTrimmed.Substring(2));
}
}
else if (sdpLineTrimmed.StartsWith("t="))
{
sdp.Timing = sdpLineTrimmed.Substring(2);
}
else if (sdpLineTrimmed.StartsWith("m="))
{
Match mediaMatch = Regex.Match(sdpLineTrimmed.Substring(2), @"(?<type>\w+)\s+(?<port>\d+)\s+(?<transport>\S+)(\s*)(?<formats>.*)$");
if (mediaMatch.Success)
{
SDPMediaAnnouncement announcement = new SDPMediaAnnouncement();
announcement.Media = SDPMediaTypes.GetSDPMediaType(mediaMatch.Result("${type}"));
Int32.TryParse(mediaMatch.Result("${port}"), out announcement.Port);
announcement.Transport = mediaMatch.Result("${transport}");
announcement.ParseMediaFormats(mediaMatch.Result("${formats}"));
sdp.Media.Add(announcement);
activeAnnouncement = announcement;
}
else
{
logger.LogWarning("A media line in SDP was invalid: " + sdpLineTrimmed.Substring(2) + ".");
}
}
else if (sdpLineTrimmed.StartsWith("a=" + ICE_UFRAG_ATTRIBUTE_PREFIX))
{
sdp.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
}
else if (sdpLineTrimmed.StartsWith("a=" + ICE_PWD_ATTRIBUTE_PREFIX))
{
sdp.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
}
else if (sdpLineTrimmed.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_ATTRIBUE_PREFIX))
{
if (activeAnnouncement != null)
{
Match formatAttributeMatch = Regex.Match(sdpLineTrimmed, SDPMediaAnnouncement.MEDIA_FORMAT_ATTRIBUE_PREFIX + @"(?<id>\d+)\s+(?<attribute>.*)$");
if (formatAttributeMatch.Success)
{
int formatID;
if (Int32.TryParse(formatAttributeMatch.Result("${id}"), out formatID))
{
activeAnnouncement.AddFormatAttribute(formatID, formatAttributeMatch.Result("${attribute}"));
}
else
{
logger.LogWarning("Invalid media format attribute in SDP: " + sdpLine);
}
}
else
{
activeAnnouncement.AddExtra(sdpLineTrimmed);
}
}
else
{
logger.LogWarning("There was no active media announcement for a media format attribute, ignoring.");
}
}
else if (sdpLineTrimmed.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_PARAMETERS_ATTRIBUE_PREFIX))
{
if (activeAnnouncement != null)
{
Match formatAttributeMatch = Regex.Match(sdpLineTrimmed, SDPMediaAnnouncement.MEDIA_FORMAT_PARAMETERS_ATTRIBUE_PREFIX + @"(?<id>\d+)\s+(?<attribute>.*)$");
if (formatAttributeMatch.Success)
{
int formatID;
if (Int32.TryParse(formatAttributeMatch.Result("${id}"), out formatID))
{
activeAnnouncement.AddFormatParameterAttribute(formatID, formatAttributeMatch.Result("${attribute}"));
}
else
{
logger.LogWarning("Invalid media format parameter attribute in SDP: " + sdpLine);
}
}
else
{
activeAnnouncement.AddExtra(sdpLineTrimmed);
}
}
else
{
logger.LogWarning("There was no active media announcement for a media format parameter attribute, ignoring.");
}
}
else if (sdpLineTrimmed.StartsWith("a=" + ICE_CANDIDATE_ATTRIBUTE_PREFIX))
{
if (sdp.IceCandidates == null)
{
sdp.IceCandidates = new List <IceCandidate>();
}
sdp.IceCandidates.Add(IceCandidate.Parse(sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1)));
}
//2018-12-21 rj2: add a=crypto
else if (sdpLineTrimmed.StartsWith(SDPSecurityDescription.CRYPTO_ATTRIBUE_PREFIX))
{
if (activeAnnouncement != null)
{
try
{
activeAnnouncement.AddCryptoLine(sdpLineTrimmed);
}
catch (FormatException fex)
{
logger.LogWarning("Error Parsing SDP-Line(a=crypto) " + fex);
}
}
}
else if (MediaStreamStatusType.IsMediaStreamStatusAttribute(sdpLine.Trim(), out var mediaStreamStatus))
{
if (activeAnnouncement != null)
{
activeAnnouncement.MediaStreamStatus = mediaStreamStatus;
}
else
{
sdp.SessionMediaStreamStatus = mediaStreamStatus;
}
}
else
{
if (activeAnnouncement != null)
{
activeAnnouncement.AddExtra(sdpLineTrimmed);
}
else
{
sdp.AddExtra(sdpLineTrimmed);
}
}
}
return(sdp);
}
else
{
return(null);
}
}
catch (Exception excp)
{
logger.LogError("Exception ParseSDPDescription. " + excp.Message);
throw excp;
}
}