public SDPMediaAnnouncement(SDPMediaTypesEnum mediaType, SDPConnectionInformation connection, int port, SDPMessageMediaFormat messageMediaFormat)
        {
            Media      = mediaType;
            Port       = port;
            Connection = connection;

            MessageMediaFormat = messageMediaFormat;
        }
 public static SDPConnectionInformation ParseConnectionInformation(string connectionLine)
 {
     SDPConnectionInformation connectionInfo = new SDPConnectionInformation();
     string[] connectionFields = connectionLine.Substring(2).Trim().Split(' ');
     connectionInfo.ConnectionNetworkType = connectionFields[0].Trim();
     connectionInfo.ConnectionAddressType = connectionFields[1].Trim();
     connectionInfo.ConnectionAddress = connectionFields[2].Trim();
     return connectionInfo;
 }
Beispiel #3
0
        public static SDPConnectionInformation ParseConnectionInformation(string connectionLine)
        {
            SDPConnectionInformation connectionInfo = new SDPConnectionInformation();

            string[] connectionFields = connectionLine.Substring(2).Trim().Split(' ');
            connectionInfo.ConnectionNetworkType = connectionFields[0].Trim();
            connectionInfo.ConnectionAddressType = connectionFields[1].Trim();
            connectionInfo.ConnectionAddress     = connectionFields[2].Trim();
            return(connectionInfo);
        }
Beispiel #4
0
        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=" + GROUP_ATRIBUTE_PREFIX))
                        {
                            sdp.Group = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                        }
                        else if (sdpLineTrimmed.StartsWith("a=" + ICE_UFRAG_ATTRIBUTE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                        }
                        else if (sdpLineTrimmed.StartsWith("a=" + ICE_PWD_ATTRIBUTE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                        }
                        else if (sdpLineTrimmed.StartsWith("a=" + DTLS_FINGERPRINT_ATTRIBUTE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.DtlsFingerprint =
                                    sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.DtlsFingerprint = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                        }
                        else if (sdpLineTrimmed.StartsWith($"a={END_ICE_CANDIDATES_ATTRIBUTE}"))
                        {
                            // Do nothing.
                        }
                        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 (activeAnnouncement != null)
                            {
                                if (activeAnnouncement.IceCandidates == null)
                                {
                                    activeAnnouncement.IceCandidates = new List <string>();
                                }

                                activeAnnouncement.IceCandidates.Add(
                                    sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1));
                            }
                            else
                            {
                                if (sdp.IceCandidates == null)
                                {
                                    sdp.IceCandidates = new List <string>();
                                }

                                sdp.IceCandidates.Add(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 (sdpLineTrimmed.StartsWith("a=" + MEDIA_ID_ATTRIBUTE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.MediaID = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                logger.LogWarning("A media ID can only be set on a media announcement.");
                            }
                        }
                        else if (sdpLineTrimmed.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SSRC_GROUP_ATTRIBUE_PREFIX)
                                 )
                        {
                            if (activeAnnouncement != null)
                            {
                                string[] fields = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1).Split(' ');

                                // Set the ID.
                                if (fields.Length > 0)
                                {
                                    activeAnnouncement.SsrcGroupID = fields[0];
                                }

                                // Add attributes for each of the SSRC values.
                                for (int i = 1; i < fields.Length; i++)
                                {
                                    if (uint.TryParse(fields[i], out var ssrc))
                                    {
                                        activeAnnouncement.SsrcAttributes.Add(
                                            new SDPSsrcAttribute(ssrc, null, activeAnnouncement.SsrcGroupID));
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("A ssrc-group ID can only be set on a media announcement.");
                            }
                        }
                        else if (sdpLineTrimmed.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SSRC_ATTRIBUE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                string[] ssrcFields = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1)
                                                      .Split(' ');

                                if (ssrcFields.Length > 0 && uint.TryParse(ssrcFields[0], out var ssrc))
                                {
                                    var ssrcAttribute =
                                        activeAnnouncement.SsrcAttributes.FirstOrDefault(x => x.SSRC == ssrc);
                                    if (ssrcAttribute == null)
                                    {
                                        ssrcAttribute = new SDPSsrcAttribute(ssrc, null, null);
                                        activeAnnouncement.SsrcAttributes.Add(ssrcAttribute);
                                    }

                                    if (ssrcFields.Length > 1)
                                    {
                                        if (ssrcFields[1].StartsWith(SDPSsrcAttribute.MEDIA_CNAME_ATTRIBUE_PREFIX))
                                        {
                                            ssrcAttribute.Cname =
                                                ssrcFields[1].Substring(ssrcFields[1].IndexOf(':') + 1);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("A ssrc attribute can only be set on a media announcement.");
                            }
                        }
                        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;
            }
        }
Beispiel #5
0
        public static SDP ParseSDPDescription(string sdpDescription)
        {
            try
            {
                if (sdpDescription != null && sdpDescription.Trim().Length > 0)
                {
                    SDP sdp = new SDP();
                    sdp.m_rawSdp = sdpDescription;
                    int mLineIndex = 0;
                    SDPMediaAnnouncement activeAnnouncement = null;

                    // If a media announcement fmtp atribute is found before the rtpmap it will be stored
                    // in this dictionary. A dynamic media format type cannot be created without an rtpmap.
                    Dictionary <int, string> _pendingFmtp = new Dictionary <int, string>();

                    //string[] sdpLines = Regex.Split(sdpDescription, CRLF);
                    string[] sdpLines = sdpDescription.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (string sdpLine in sdpLines)
                    {
                        string sdpLineTrimmed = sdpLine.Trim();

                        switch (sdpLineTrimmed)
                        {
                        case var l when l.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 + ".");
                            }
                            break;

                        case var l when l.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];
                            break;

                        case var l when l.StartsWith("s="):
                            sdp.SessionName = sdpLineTrimmed.Substring(2);

                            break;

                        case var l when l.StartsWith("i="):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.MediaDescription = sdpLineTrimmed.Substring(2);
                            }
                            else
                            {
                                sdp.SessionDescription = sdpLineTrimmed.Substring(2);
                            }

                            break;

                        case var l when l.StartsWith("c="):

                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLineTrimmed);
                            }
                            else if (sdp.Connection == null)
                            {
                                sdp.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLineTrimmed);
                            }
                            else
                            {
                                logger.LogWarning("The SDP message had a duplicate connection attribute which was ignored.");
                            }

                            break;

                        case var l when l.StartsWith("b="):
                            if (activeAnnouncement != null)
                            {
                                if (l.StartsWith(SDPMediaAnnouncement.TIAS_BANDWIDTH_ATTRIBUE_PREFIX))
                                {
                                    if (uint.TryParse(l.Substring(l.IndexOf(':') + 1), out uint tias))
                                    {
                                        activeAnnouncement.TIASBandwidth = tias;
                                    }
                                }
                                else
                                {
                                    activeAnnouncement.BandwidthAttributes.Add(sdpLineTrimmed.Substring(2));
                                }
                            }
                            else
                            {
                                sdp.BandwidthAttributes.Add(sdpLineTrimmed.Substring(2));
                            }
                            break;

                        case var l when l.StartsWith("t="):
                            sdp.Timing = sdpLineTrimmed.Substring(2);

                            break;

                        case var l when l.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.MLineIndex = mLineIndex;
                                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}"));
                                if (announcement.Media == SDPMediaTypesEnum.audio || announcement.Media == SDPMediaTypesEnum.video)
                                {
                                    announcement.MediaStreamStatus = sdp.SessionMediaStreamStatus != null ? sdp.SessionMediaStreamStatus.Value :
                                                                     MediaStreamStatusEnum.SendRecv;
                                }
                                sdp.Media.Add(announcement);

                                activeAnnouncement = announcement;
                            }
                            else
                            {
                                logger.LogWarning("A media line in SDP was invalid: " + sdpLineTrimmed.Substring(2) + ".");
                            }

                            mLineIndex++;
                            break;

                        case var x when x.StartsWith($"a={GROUP_ATRIBUTE_PREFIX}"):
                            sdp.Group = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                            break;

                        case var x when x.StartsWith($"a={ICE_UFRAG_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            break;

                        case var x when x.StartsWith($"a={ICE_PWD_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            break;

                        case var x when x.StartsWith($"a={ICE_SETUP_ATTRIBUTE_PREFIX}"):
                            int colonIndex = sdpLineTrimmed.IndexOf(':');

                            if (colonIndex != -1 && sdpLineTrimmed.Length > colonIndex)
                            {
                                string iceRoleStr = sdpLineTrimmed.Substring(colonIndex + 1).Trim();
                                if (Enum.TryParse <IceRolesEnum>(iceRoleStr, true, out var iceRole))
                                {
                                    if (activeAnnouncement != null)
                                    {
                                        activeAnnouncement.IceRole = iceRole;
                                    }
                                    else
                                    {
                                        sdp.IceRole = iceRole;
                                    }
                                }
                                else
                                {
                                    logger.LogWarning($"ICE role was not recognised from SDP attribute: {sdpLineTrimmed}.");
                                }
                            }
                            else
                            {
                                logger.LogWarning($"ICE role SDP attribute was missing the mandatory colon: {sdpLineTrimmed}.");
                            }
                            break;

                        case var x when x.StartsWith($"a={DTLS_FINGERPRINT_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.DtlsFingerprint = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.DtlsFingerprint = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            break;

                        case var x when x.StartsWith($"a={ICE_CANDIDATE_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                if (activeAnnouncement.IceCandidates == null)
                                {
                                    activeAnnouncement.IceCandidates = new List <string>();
                                }
                                activeAnnouncement.IceCandidates.Add(sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1));
                            }
                            else
                            {
                                if (sdp.IceCandidates == null)
                                {
                                    sdp.IceCandidates = new List <string>();
                                }
                                sdp.IceCandidates.Add(sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1));
                            }
                            break;

                        case var x when x == $"a={END_ICE_CANDIDATES_ATTRIBUTE}":
                            // TODO: Set a flag.
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                if (activeAnnouncement.Media == SDPMediaTypesEnum.audio || activeAnnouncement.Media == SDPMediaTypesEnum.video)
                                {
                                    // Parse the rtpmap attribute for audio/video announcements.
                                    Match formatAttributeMatch = Regex.Match(sdpLineTrimmed, SDPMediaAnnouncement.MEDIA_FORMAT_ATTRIBUE_PREFIX + @"(?<id>\d+)\s+(?<attribute>.*)$");
                                    if (formatAttributeMatch.Success)
                                    {
                                        string formatID = formatAttributeMatch.Result("${id}");
                                        string rtpmap   = formatAttributeMatch.Result("${attribute}");

                                        if (Int32.TryParse(formatID, out int id))
                                        {
                                            if (activeAnnouncement.MediaFormats.ContainsKey(id))
                                            {
                                                activeAnnouncement.MediaFormats[id] = activeAnnouncement.MediaFormats[id].WithUpdatedRtpmap(rtpmap, activeAnnouncement.MediaFormats[id]);
                                            }
                                            else
                                            {
                                                string fmtp = _pendingFmtp.ContainsKey(id) ? _pendingFmtp[id] : null;
                                                activeAnnouncement.MediaFormats.Add(id, new SDPAudioVideoMediaFormat(activeAnnouncement.Media, id, rtpmap, fmtp));
                                            }
                                        }
                                        else
                                        {
                                            logger.LogWarning("Non-numeric audio/video media format attribute in SDP: " + sdpLine);
                                        }
                                    }
                                    else
                                    {
                                        activeAnnouncement.AddExtra(sdpLineTrimmed);
                                    }
                                }
                                else
                                {
                                    // Parse the rtpmap attribute for NON audio/video announcements.
                                    Match formatAttributeMatch = Regex.Match(sdpLineTrimmed, SDPMediaAnnouncement.MEDIA_FORMAT_ATTRIBUE_PREFIX + @"(?<id>\S+)\s+(?<attribute>.*)$");
                                    if (formatAttributeMatch.Success)
                                    {
                                        string formatID = formatAttributeMatch.Result("${id}");
                                        string rtpmap   = formatAttributeMatch.Result("${attribute}");

                                        if (activeAnnouncement.ApplicationMediaFormats.ContainsKey(formatID))
                                        {
                                            activeAnnouncement.ApplicationMediaFormats[formatID] = activeAnnouncement.ApplicationMediaFormats[formatID].WithUpdatedRtpmap(rtpmap);
                                        }
                                        else
                                        {
                                            activeAnnouncement.ApplicationMediaFormats.Add(formatID, new SDPApplicationMediaFormat(formatID, rtpmap, null));
                                        }
                                    }
                                    else
                                    {
                                        activeAnnouncement.AddExtra(sdpLineTrimmed);
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("There was no active media announcement for a media format attribute, ignoring.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_PARAMETERS_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                if (activeAnnouncement.Media == SDPMediaTypesEnum.audio || activeAnnouncement.Media == SDPMediaTypesEnum.video)
                                {
                                    // Parse the fmtp attribute for audio/video announcements.
                                    Match formatAttributeMatch = Regex.Match(sdpLineTrimmed, SDPMediaAnnouncement.MEDIA_FORMAT_PARAMETERS_ATTRIBUE_PREFIX + @"(?<id>\d+)\s+(?<attribute>.*)$");
                                    if (formatAttributeMatch.Success)
                                    {
                                        string avFormatID = formatAttributeMatch.Result("${id}");
                                        string fmtp       = formatAttributeMatch.Result("${attribute}");

                                        if (Int32.TryParse(avFormatID, out int id))
                                        {
                                            if (activeAnnouncement.MediaFormats.ContainsKey(id))
                                            {
                                                activeAnnouncement.MediaFormats[id] = activeAnnouncement.MediaFormats[id].WithUpdatedFmtp(fmtp, activeAnnouncement.MediaFormats[id]);
                                            }
                                            else
                                            {
                                                // Store the fmtp attribute for use when the rtpmap attribute turns up.
                                                if (_pendingFmtp.ContainsKey(id))
                                                {
                                                    _pendingFmtp.Remove(id);
                                                }
                                                _pendingFmtp.Add(id, fmtp);
                                            }
                                        }
                                        else
                                        {
                                            logger.LogWarning("Invalid media format parameter attribute in SDP: " + sdpLine);
                                        }
                                    }
                                    else
                                    {
                                        activeAnnouncement.AddExtra(sdpLineTrimmed);
                                    }
                                }
                                else
                                {
                                    // Parse the fmtp attribute for NON audio/video announcements.
                                    Match formatAttributeMatch = Regex.Match(sdpLineTrimmed, SDPMediaAnnouncement.MEDIA_FORMAT_PARAMETERS_ATTRIBUE_PREFIX + @"(?<id>\S+)\s+(?<attribute>.*)$");
                                    if (formatAttributeMatch.Success)
                                    {
                                        string formatID = formatAttributeMatch.Result("${id}");
                                        string fmtp     = formatAttributeMatch.Result("${attribute}");

                                        if (activeAnnouncement.ApplicationMediaFormats.ContainsKey(formatID))
                                        {
                                            activeAnnouncement.ApplicationMediaFormats[formatID] = activeAnnouncement.ApplicationMediaFormats[formatID].WithUpdatedFmtp(fmtp);
                                        }
                                        else
                                        {
                                            activeAnnouncement.ApplicationMediaFormats.Add(formatID, new SDPApplicationMediaFormat(formatID, null, fmtp));
                                        }
                                    }
                                    else
                                    {
                                        activeAnnouncement.AddExtra(sdpLineTrimmed);
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("There was no active media announcement for a media format parameter attribute, ignoring.");
                            }
                            break;

                        case var l when l.StartsWith(SDPSecurityDescription.CRYPTO_ATTRIBUE_PREFIX):
                            //2018-12-21 rj2: add a=crypto
                            if (activeAnnouncement != null)
                            {
                                try
                                {
                                    activeAnnouncement.AddCryptoLine(sdpLineTrimmed);
                                }
                                catch (FormatException fex)
                                {
                                    logger.LogWarning("Error Parsing SDP-Line(a=crypto) " + fex);
                                }
                            }
                            break;

                        case var x when x.StartsWith($"a={MEDIA_ID_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.MediaID = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                logger.LogWarning("A media ID can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SSRC_GROUP_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string[] fields = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1).Split(' ');

                                // Set the ID.
                                if (fields.Length > 0)
                                {
                                    activeAnnouncement.SsrcGroupID = fields[0];
                                }

                                // Add attributes for each of the SSRC values.
                                for (int i = 1; i < fields.Length; i++)
                                {
                                    if (uint.TryParse(fields[i], out var ssrc))
                                    {
                                        activeAnnouncement.SsrcAttributes.Add(new SDPSsrcAttribute(ssrc, null, activeAnnouncement.SsrcGroupID));
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("A ssrc-group ID can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SSRC_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string[] ssrcFields = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1).Split(' ');

                                if (ssrcFields.Length > 0 && uint.TryParse(ssrcFields[0], out var ssrc))
                                {
                                    var ssrcAttribute = activeAnnouncement.SsrcAttributes.FirstOrDefault(x => x.SSRC == ssrc);
                                    if (ssrcAttribute == null)
                                    {
                                        ssrcAttribute = new SDPSsrcAttribute(ssrc, null, null);
                                        activeAnnouncement.SsrcAttributes.Add(ssrcAttribute);
                                    }

                                    if (ssrcFields.Length > 1)
                                    {
                                        if (ssrcFields[1].StartsWith(SDPSsrcAttribute.MEDIA_CNAME_ATTRIBUE_PREFIX))
                                        {
                                            ssrcAttribute.Cname = ssrcFields[1].Substring(ssrcFields[1].IndexOf(':') + 1);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("An ssrc attribute can only be set on a media announcement.");
                            }
                            break;

                        case var x when MediaStreamStatusType.IsMediaStreamStatusAttribute(x, out var mediaStreamStatus):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.MediaStreamStatus = mediaStreamStatus;
                            }
                            else
                            {
                                sdp.SessionMediaStreamStatus = mediaStreamStatus;
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SCTP_MAP_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.SctpMap = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                                (var sctpPortStr, _, var maxMessageSizeStr) = activeAnnouncement.SctpMap.Split(' ');

                                if (ushort.TryParse(sctpPortStr, out var sctpPort))
                                {
                                    activeAnnouncement.SctpPort = sctpPort;
                                }
                                else
                                {
                                    logger.LogWarning($"An sctp-port value of {sctpPortStr} was not recognised as a valid port.");
                                }

                                if (!long.TryParse(maxMessageSizeStr, out activeAnnouncement.MaxMessageSize))
                                {
                                    logger.LogWarning($"A max-message-size value of {maxMessageSizeStr} was not recognised as a valid long.");
                                }
                            }
                            else
                            {
                                logger.LogWarning("An sctpmap attribute can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SCTP_PORT_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string sctpPortStr = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                                if (ushort.TryParse(sctpPortStr, out var sctpPort))
                                {
                                    activeAnnouncement.SctpPort = sctpPort;
                                }
                                else
                                {
                                    logger.LogWarning($"An sctp-port value of {sctpPortStr} was not recognised as a valid port.");
                                }
                            }
                            else
                            {
                                logger.LogWarning("An sctp-port attribute can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_MAX_MESSAGE_SIZE_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string maxMessageSizeStr = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                                if (!long.TryParse(maxMessageSizeStr, out activeAnnouncement.MaxMessageSize))
                                {
                                    logger.LogWarning($"A max-message-size value of {maxMessageSizeStr} was not recognised as a valid long.");
                                }
                            }
                            else
                            {
                                logger.LogWarning("A max-message-size attribute can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_PATH_ACCEPT_TYPES_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string acceptTypesStr  = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                                var    acceptTypesList = acceptTypesStr.Trim().Split(' ').ToList();

                                activeAnnouncement.MessageMediaFormat.AcceptTypes = acceptTypesList;
                            }
                            else
                            {
                                logger.LogWarning("A accept-types attribute can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_PATH_MSRP_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string pathStr        = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                                string pathTrimmedStr = pathStr.Substring(pathStr.IndexOf(':') + 3);

                                activeAnnouncement.MessageMediaFormat.IP = pathTrimmedStr.Substring(0, pathTrimmedStr.IndexOf(':'));

                                pathTrimmedStr = pathTrimmedStr.Substring(pathTrimmedStr.IndexOf(':') + 1);
                                activeAnnouncement.MessageMediaFormat.Port = pathTrimmedStr.Substring(0, pathTrimmedStr.IndexOf('/'));

                                pathTrimmedStr = pathTrimmedStr.Substring(pathTrimmedStr.IndexOf('/') + 1);
                                activeAnnouncement.MessageMediaFormat.Endpoint = pathTrimmedStr;
                            }
                            else
                            {
                                logger.LogWarning("A path attribute can only be set on a media announcement.");
                            }
                            break;

                        default:
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.AddExtra(sdpLineTrimmed);
                            }
                            else
                            {
                                sdp.AddExtra(sdpLineTrimmed);
                            }
                            break;
                        }
                    }

                    return(sdp);
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception ParseSDPDescription. " + excp.Message);
                throw;
            }
        }
 public SDPMediaAnnouncement(SDPConnectionInformation connection)
 {
     Connection = connection;
 }
Beispiel #7
0
 public SDPMediaAnnouncement(SDPConnectionInformation connection)
 {
     Connection = connection;
 }
Beispiel #8
0
        public static SDP ParseSDPDescription(string sdpDescription)
        {
            try
            {
                if (sdpDescription != null && sdpDescription.Trim().Length > 0)
                {
                    SDP sdp = new SDP();
                    sdp.m_rawSdp = sdpDescription;
                    int mLineIndex = 0;
                    SDPMediaAnnouncement activeAnnouncement = null;

                    string[] sdpLines = Regex.Split(sdpDescription, CRLF);

                    foreach (string sdpLine in sdpLines)
                    {
                        string sdpLineTrimmed = sdpLine.Trim();

                        switch (sdpLineTrimmed)
                        {
                        case var l when l.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 + ".");
                            }
                            break;

                        case var l when l.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];
                            break;

                        case var l when l.StartsWith("s="):
                            sdp.SessionName = sdpLineTrimmed.Substring(2);

                            break;

                        case var l when l.StartsWith("c="):

                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLineTrimmed);
                            }
                            else if (sdp.Connection == null)
                            {
                                sdp.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLineTrimmed);
                            }
                            else
                            {
                                logger.LogWarning("The SDP message had a duplicate connection attribute which was ignored.");
                            }

                            break;

                        case var l when l.StartsWith("b="):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.BandwidthAttributes.Add(sdpLineTrimmed.Substring(2));
                            }
                            else
                            {
                                sdp.BandwidthAttributes.Add(sdpLineTrimmed.Substring(2));
                            }
                            break;

                        case var l when l.StartsWith("t="):
                            sdp.Timing = sdpLineTrimmed.Substring(2);

                            break;

                        case var l when l.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.MLineIndex = mLineIndex;
                                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}"));
                                announcement.MediaStreamStatus = sdp.SessionMediaStreamStatus != null ? sdp.SessionMediaStreamStatus.Value :
                                                                 MediaStreamStatusEnum.SendRecv;
                                sdp.Media.Add(announcement);

                                activeAnnouncement = announcement;
                            }
                            else
                            {
                                logger.LogWarning("A media line in SDP was invalid: " + sdpLineTrimmed.Substring(2) + ".");
                            }

                            mLineIndex++;
                            break;

                        case var x when x.StartsWith($"a={GROUP_ATRIBUTE_PREFIX}"):
                            sdp.Group = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                            break;

                        case var x when x.StartsWith($"a={ICE_UFRAG_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.IceUfrag = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            break;

                        case var x when x.StartsWith($"a={ICE_PWD_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.IcePwd = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            break;

                        case var x when x.StartsWith($"a={DTLS_FINGERPRINT_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.DtlsFingerprint = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                sdp.DtlsFingerprint = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            break;

                        case var x when x.StartsWith($"a={ICE_CANDIDATE_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                if (activeAnnouncement.IceCandidates == null)
                                {
                                    activeAnnouncement.IceCandidates = new List <string>();
                                }
                                activeAnnouncement.IceCandidates.Add(sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1));
                            }
                            else
                            {
                                if (sdp.IceCandidates == null)
                                {
                                    sdp.IceCandidates = new List <string>();
                                }
                                sdp.IceCandidates.Add(sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1));
                            }
                            break;

                        case var x when x == $"a={END_ICE_CANDIDATES_ATTRIBUTE}":
                            // TODO: Set a flag.
                            break;

                        case var l when l.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)
                                {
                                    string formatID = formatAttributeMatch.Result("${id}");
                                    string rtpmap   = formatAttributeMatch.Result("${attribute}");

                                    if (activeAnnouncement.Media == SDPMediaTypesEnum.application)
                                    {
                                        var appMediaFormat = activeAnnouncement.ApplicationMediaFormats.Where(x => x.ID == formatID).FirstOrDefault();
                                        if (appMediaFormat.ID != null)
                                        {
                                            appMediaFormat.Rtpmap = rtpmap;
                                        }
                                    }
                                    else
                                    {
                                        if (Int32.TryParse(formatID, out int id))
                                        {
                                            if (activeAnnouncement.MediaFormats.ContainsKey(id))
                                            {
                                                activeAnnouncement.MediaFormats[id] = activeAnnouncement.MediaFormats[id].WithUpdatedRtpmap(rtpmap, activeAnnouncement.MediaFormats[id]);
                                            }
                                            else
                                            {
                                                activeAnnouncement.MediaFormats.Add(id, new SDPAudioVideoMediaFormat(activeAnnouncement.Media, id, rtpmap, null));
                                            }
                                        }
                                        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.");
                            }
                            break;

                        case var l when l.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)
                                {
                                    string formatID = formatAttributeMatch.Result("${id}");
                                    string fmtp     = formatAttributeMatch.Result("${attribute}");

                                    if (activeAnnouncement.Media == SDPMediaTypesEnum.application)
                                    {
                                        var appMediaFormat = activeAnnouncement.ApplicationMediaFormats.Where(x => x.ID == formatID).FirstOrDefault();
                                        if (appMediaFormat.ID != null)
                                        {
                                            appMediaFormat.Fmtmp = fmtp;
                                        }
                                    }
                                    else
                                    {
                                        if (Int32.TryParse(formatID, out int id))
                                        {
                                            if (activeAnnouncement.MediaFormats.ContainsKey(id))
                                            {
                                                activeAnnouncement.MediaFormats[id] = activeAnnouncement.MediaFormats[id].WithUpdatedFmtp(fmtp, activeAnnouncement.MediaFormats[id]);
                                            }
                                            else
                                            {
                                                activeAnnouncement.MediaFormats.Add(id, new SDPAudioVideoMediaFormat(activeAnnouncement.Media, id, null, fmtp));
                                            }
                                        }
                                        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.");
                            }
                            break;

                        case var l when l.StartsWith(SDPSecurityDescription.CRYPTO_ATTRIBUE_PREFIX):
                            //2018-12-21 rj2: add a=crypto
                            if (activeAnnouncement != null)
                            {
                                try
                                {
                                    activeAnnouncement.AddCryptoLine(sdpLineTrimmed);
                                }
                                catch (FormatException fex)
                                {
                                    logger.LogWarning("Error Parsing SDP-Line(a=crypto) " + fex);
                                }
                            }
                            break;

                        case var x when x.StartsWith($"a={MEDIA_ID_ATTRIBUTE_PREFIX}"):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.MediaID = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);
                            }
                            else
                            {
                                logger.LogWarning("A media ID can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SSRC_GROUP_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string[] fields = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1).Split(' ');

                                // Set the ID.
                                if (fields.Length > 0)
                                {
                                    activeAnnouncement.SsrcGroupID = fields[0];
                                }

                                // Add attributes for each of the SSRC values.
                                for (int i = 1; i < fields.Length; i++)
                                {
                                    if (uint.TryParse(fields[i], out var ssrc))
                                    {
                                        activeAnnouncement.SsrcAttributes.Add(new SDPSsrcAttribute(ssrc, null, activeAnnouncement.SsrcGroupID));
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("A ssrc-group ID can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SSRC_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string[] ssrcFields = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1).Split(' ');

                                if (ssrcFields.Length > 0 && uint.TryParse(ssrcFields[0], out var ssrc))
                                {
                                    var ssrcAttribute = activeAnnouncement.SsrcAttributes.FirstOrDefault(x => x.SSRC == ssrc);
                                    if (ssrcAttribute == null)
                                    {
                                        ssrcAttribute = new SDPSsrcAttribute(ssrc, null, null);
                                        activeAnnouncement.SsrcAttributes.Add(ssrcAttribute);
                                    }

                                    if (ssrcFields.Length > 1)
                                    {
                                        if (ssrcFields[1].StartsWith(SDPSsrcAttribute.MEDIA_CNAME_ATTRIBUE_PREFIX))
                                        {
                                            ssrcAttribute.Cname = ssrcFields[1].Substring(ssrcFields[1].IndexOf(':') + 1);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                logger.LogWarning("An ssrc attribute can only be set on a media announcement.");
                            }
                            break;

                        case var x when MediaStreamStatusType.IsMediaStreamStatusAttribute(x, out var mediaStreamStatus):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.MediaStreamStatus = mediaStreamStatus;
                            }
                            else
                            {
                                sdp.SessionMediaStreamStatus = mediaStreamStatus;
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SCTP_MAP_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.SctpMap = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                                (var sctpPortStr, _, var maxMessageSizeStr) = activeAnnouncement.SctpMap.Split(' ');

                                if (ushort.TryParse(sctpPortStr, out var sctpPort))
                                {
                                    activeAnnouncement.SctpPort = sctpPort;
                                }
                                else
                                {
                                    logger.LogWarning($"An sctp-port value of {sctpPortStr} was not recognised as a valid port.");
                                }

                                if (!long.TryParse(maxMessageSizeStr, out activeAnnouncement.MaxMessageSize))
                                {
                                    logger.LogWarning($"A max-message-size value of {maxMessageSizeStr} was not recognised as a valid long.");
                                }
                            }
                            else
                            {
                                logger.LogWarning("An sctpmap attribute can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_SCTP_PORT_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string sctpPortStr = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                                if (ushort.TryParse(sctpPortStr, out var sctpPort))
                                {
                                    activeAnnouncement.SctpPort = sctpPort;
                                }
                                else
                                {
                                    logger.LogWarning($"An sctp-port value of {sctpPortStr} was not recognised as a valid port.");
                                }
                            }
                            else
                            {
                                logger.LogWarning("An sctp-port attribute can only be set on a media announcement.");
                            }
                            break;

                        case var l when l.StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_MAX_MESSAGE_SIZE_ATTRIBUE_PREFIX):
                            if (activeAnnouncement != null)
                            {
                                string maxMessageSizeStr = sdpLineTrimmed.Substring(sdpLineTrimmed.IndexOf(':') + 1);

                                if (!long.TryParse(maxMessageSizeStr, out activeAnnouncement.MaxMessageSize))
                                {
                                    logger.LogWarning($"A max-message-size value of {maxMessageSizeStr} was not recognised as a valid long.");
                                }
                            }
                            else
                            {
                                logger.LogWarning("A max-message-size attribute can only be set on a media announcement.");
                            }
                            break;

                        default:
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.AddExtra(sdpLineTrimmed);
                            }
                            else
                            {
                                sdp.AddExtra(sdpLineTrimmed);
                            }
                            break;
                        }
                    }

                    return(sdp);
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception ParseSDPDescription. " + excp.Message);
                throw;
            }
        }
Beispiel #9
0
        public static SDP ParseSDPDescription(string sdpDescription)
        {
            try
            {
                if (sdpDescription != null && sdpDescription.Trim().Length > 0)
                {
                    SDP sdp = new SDP();
                    SDPMediaAnnouncement activeAnnouncement = null;

                    string[] sdpLines = Regex.Split(sdpDescription, CRLF);

                    foreach (string sdpLine in sdpLines)
                    {
                        if (sdpLine.Trim().StartsWith("v="))
                        {
                            if (!Decimal.TryParse(sdpLine.Substring(2), out sdp.Version))
                            {
                                logger.LogWarning("The Version value in an SDP description could not be parsed as a decimal: " + sdpLine + ".");
                            }
                        }
                        else if (sdpLine.Trim().StartsWith("o="))
                        {
                            string[] ownerFields = sdpLine.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.Address     = ownerFields[5];
                        }
                        else if (sdpLine.Trim().StartsWith("s="))
                        {
                            sdp.SessionName = sdpLine.Substring(2);
                        }
                        else if (sdpLine.Trim().StartsWith("c="))
                        {
                            if (sdp.Connection == null)
                            {
                                sdp.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLine);
                            }

                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.Connection = SDPConnectionInformation.ParseConnectionInformation(sdpLine);
                            }
                        }
                        else if (sdpLine.Trim().StartsWith("b="))
                        {
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.BandwidthAttributes.Add(sdpLine.Substring(2));
                            }
                            else
                            {
                                sdp.BandwidthAttributes.Add(sdpLine.Substring(2));
                            }
                        }
                        else if (sdpLine.Trim().StartsWith("t="))
                        {
                            sdp.Timing = sdpLine.Substring(2);
                        }
                        else if (sdpLine.Trim().StartsWith("m="))
                        {
                            Match mediaMatch = Regex.Match(sdpLine.Substring(2).Trim(), @"(?<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: " + sdpLine.Substring(2) + ".");
                            }
                        }
                        else if (sdpLine.Trim().StartsWith("a=" + ICE_UFRAG_ATTRIBUTE_PREFIX))
                        {
                            sdp.IceUfrag = sdpLine.Substring(sdpLine.IndexOf(':') + 1);
                        }
                        else if (sdpLine.Trim().StartsWith("a=" + ICE_PWD_ATTRIBUTE_PREFIX))
                        {
                            sdp.IcePwd = sdpLine.Substring(sdpLine.IndexOf(':') + 1);
                        }
                        else if (sdpLine.Trim().StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_ATTRIBUE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                Match formatAttributeMatch = Regex.Match(sdpLine.Trim(), 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(sdpLine);
                                }
                            }
                            else
                            {
                                logger.LogWarning("There was no active media announcement for a media format attribute, ignoring.");
                            }
                        }
                        else if (sdpLine.Trim().StartsWith(SDPMediaAnnouncement.MEDIA_FORMAT_PARAMETERS_ATTRIBUE_PREFIX))
                        {
                            if (activeAnnouncement != null)
                            {
                                Match formatAttributeMatch = Regex.Match(sdpLine.Trim(), 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(sdpLine);
                                }
                            }
                            else
                            {
                                logger.LogWarning("There was no active media announcement for a media format parameter attribute, ignoring.");
                            }
                        }
                        else if (sdpLine.Trim().StartsWith("a=" + ICE_CANDIDATE_ATTRIBUTE_PREFIX))
                        {
                            if (sdp.IceCandidates == null)
                            {
                                sdp.IceCandidates = new List <IceCandidate>();
                            }

                            sdp.IceCandidates.Add(IceCandidate.Parse(sdpLine.Substring(sdpLine.IndexOf(':') + 1)));
                        }
                        else
                        {
                            if (activeAnnouncement != null)
                            {
                                activeAnnouncement.AddExtra(sdpLine);
                            }
                            else
                            {
                                sdp.AddExtra(sdpLine);
                            }
                        }
                    }

                    return(sdp);
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception ParseSDPDescription. " + excp.Message);
                throw excp;
            }
        }