Exemplo n.º 1
0
        public override string ToString()
        {
            string announcement = "m=" + Media + " " + Port + " " + Transport + " " + GetFormatListToString() + m_CRLF;

            announcement += (Connection == null) ? null : Connection.ToString();

            foreach (string bandwidthAttribute in BandwidthAttributes)
            {
                announcement += "b=" + bandwidthAttribute + m_CRLF;
            }

            announcement += GetFormatListAttributesToString();

            foreach (string extra in ExtraMediaAttributes)
            {
                announcement += string.IsNullOrWhiteSpace(extra) ? null : extra + m_CRLF;
            }

            foreach (SDPSecurityDescription desc in this.SecurityDescriptions)
            {
                announcement += desc.ToString() + m_CRLF;
            }
            if (MediaStreamStatus != MediaStreamStatusEnum.None)
            {
                announcement += MediaStreamStatusType.GetAttributeForMediaStreamStatus(MediaStreamStatus) + m_CRLF;
            }

            return(announcement);
        }
Exemplo n.º 2
0
        public override string ToString()
        {
            string sdp =
                "v=" + SDP_PROTOCOL_VERSION + CRLF +
                "o=" + Owner + CRLF +
                "s=" + SessionName + CRLF +
                ((Connection != null) ? Connection.ToString() : null);

            foreach (string bandwidth in BandwidthAttributes)
            {
                sdp += "b=" + bandwidth + CRLF;
            }

            sdp += "t=" + Timing + CRLF;

            sdp += !string.IsNullOrWhiteSpace(IceUfrag)
                ? "a=" + ICE_UFRAG_ATTRIBUTE_PREFIX + ":" + IceUfrag + CRLF
                : null;
            sdp += !string.IsNullOrWhiteSpace(IcePwd) ? "a=" + ICE_PWD_ATTRIBUTE_PREFIX + ":" + IcePwd + CRLF : null;
            sdp += !string.IsNullOrWhiteSpace(DtlsFingerprint)
                ? "a=" + DTLS_FINGERPRINT_ATTRIBUTE_PREFIX + ":" + DtlsFingerprint + CRLF
                : null;
            sdp += string.IsNullOrWhiteSpace(SessionDescription) ? null : "i=" + SessionDescription + CRLF;
            sdp += string.IsNullOrWhiteSpace(URI) ? null : "u=" + URI + CRLF;

            if (OriginatorEmailAddresses != null && OriginatorEmailAddresses.Length > 0)
            {
                foreach (string originatorAddress in OriginatorEmailAddresses)
                {
                    sdp += string.IsNullOrWhiteSpace(originatorAddress) ? null : "e=" + originatorAddress + CRLF;
                }
            }

            if (OriginatorPhoneNumbers != null && OriginatorPhoneNumbers.Length > 0)
            {
                foreach (string originatorNumber in OriginatorPhoneNumbers)
                {
                    sdp += string.IsNullOrWhiteSpace(originatorNumber) ? null : "p=" + originatorNumber + CRLF;
                }
            }

            sdp += (Group == null) ? null : $"a={GROUP_ATRIBUTE_PREFIX}:{Group}" + CRLF;

            foreach (string extra in ExtraSessionAttributes)
            {
                sdp += string.IsNullOrWhiteSpace(extra) ? null : extra + CRLF;
            }

            if (SessionMediaStreamStatus != MediaStreamStatusEnum.None)
            {
                sdp += MediaStreamStatusType.GetAttributeForMediaStreamStatus(SessionMediaStreamStatus) + CRLF;
            }

            foreach (SDPMediaAnnouncement media in Media)
            {
                sdp += (media == null) ? null : media.ToString();
            }

            return(sdp);
        }
Exemplo n.º 3
0
        public override string ToString()
        {
            string announcement = "m=" + Media + " " + Port + " " + Transport + " " + GetFormatListToString() + m_CRLF;

            announcement += (Connection == null) ? null : Connection.ToString();

            foreach (string bandwidthAttribute in BandwidthAttributes)
            {
                announcement += "b=" + bandwidthAttribute + m_CRLF;
            }

            announcement += !string.IsNullOrWhiteSpace(IceUfrag) ? "a=" + SDP.ICE_UFRAG_ATTRIBUTE_PREFIX + ":" + IceUfrag + m_CRLF : null;
            announcement += !string.IsNullOrWhiteSpace(IcePwd) ? "a=" + SDP.ICE_PWD_ATTRIBUTE_PREFIX + ":" + IcePwd + m_CRLF : null;
            announcement += !string.IsNullOrWhiteSpace(DtlsFingerprint) ? "a=" + SDP.DTLS_FINGERPRINT_ATTRIBUTE_PREFIX + ":" + DtlsFingerprint + m_CRLF : null;

            if (IceCandidates?.Count() > 0)
            {
                foreach (var candidate in IceCandidates)
                {
                    announcement += $"a={SDP.ICE_CANDIDATE_ATTRIBUTE_PREFIX}:{candidate}{m_CRLF}";
                }
            }

            if (IceOptions != null)
            {
                announcement += $"a={SDP.ICE_OPTIONS}:" + IceOptions + m_CRLF;
            }

            if (IceEndOfCandidates)
            {
                announcement += $"a={SDP.END_ICE_CANDIDATES_ATTRIBUTE}" + m_CRLF;
            }

            announcement += !string.IsNullOrWhiteSpace(MediaID) ? "a=" + SDP.MEDIA_ID_ATTRIBUTE_PREFIX + ":" + MediaID + m_CRLF : null;

            announcement += GetFormatListAttributesToString();

            foreach (string extra in ExtraMediaAttributes)
            {
                announcement += string.IsNullOrWhiteSpace(extra) ? null : extra + m_CRLF;
            }

            foreach (SDPSecurityDescription desc in this.SecurityDescriptions)
            {
                announcement += desc.ToString() + m_CRLF;
            }

            if (MediaStreamStatus != MediaStreamStatusEnum.None)
            {
                announcement += MediaStreamStatusType.GetAttributeForMediaStreamStatus(MediaStreamStatus) + m_CRLF;
            }

            return(announcement);
        }
Exemplo n.º 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;
            }
        }
Exemplo n.º 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;
            }
        }
Exemplo n.º 6
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;
            }
        }
Exemplo n.º 7
0
        public override string ToString()
        {
            string announcement = "m=" + Media + " " + Port + " " + Transport + " " + GetFormatListToString() + m_CRLF;

            announcement += (Connection == null) ? null : Connection.ToString();

            foreach (string bandwidthAttribute in BandwidthAttributes)
            {
                announcement += "b=" + bandwidthAttribute + m_CRLF;
            }

            announcement += !string.IsNullOrWhiteSpace(IceUfrag)
                ? "a=" + SDP.ICE_UFRAG_ATTRIBUTE_PREFIX + ":" + IceUfrag + m_CRLF
                : null;
            announcement += !string.IsNullOrWhiteSpace(IcePwd)
                ? "a=" + SDP.ICE_PWD_ATTRIBUTE_PREFIX + ":" + IcePwd + m_CRLF
                : null;
            announcement += !string.IsNullOrWhiteSpace(DtlsFingerprint)
                ? "a=" + SDP.DTLS_FINGERPRINT_ATTRIBUTE_PREFIX + ":" + DtlsFingerprint + m_CRLF
                : null;

            if (IceCandidates?.Count() > 0)
            {
                foreach (var candidate in IceCandidates)
                {
                    announcement += $"a={SDP.ICE_CANDIDATE_ATTRIBUTE_PREFIX}:{candidate}{m_CRLF}";
                }
            }

            if (IceOptions != null)
            {
                announcement += $"a={SDP.ICE_OPTIONS}:" + IceOptions + m_CRLF;
            }

            if (IceEndOfCandidates)
            {
                announcement += $"a={SDP.END_ICE_CANDIDATES_ATTRIBUTE}" + m_CRLF;
            }

            announcement += !string.IsNullOrWhiteSpace(MediaID)
                ? "a=" + SDP.MEDIA_ID_ATTRIBUTE_PREFIX + ":" + MediaID + m_CRLF
                : null;

            announcement += GetFormatListAttributesToString();

            foreach (string extra in ExtraMediaAttributes)
            {
                announcement += string.IsNullOrWhiteSpace(extra) ? null : extra + m_CRLF;
            }

            foreach (SDPSecurityDescription desc in this.SecurityDescriptions)
            {
                announcement += desc.ToString() + m_CRLF;
            }

            if (MediaStreamStatus != null)
            {
                announcement += MediaStreamStatusType.GetAttributeForMediaStreamStatus(MediaStreamStatus.Value) +
                                m_CRLF;
            }

            if (SsrcGroupID != null && SsrcAttributes.Count > 0)
            {
                announcement += MEDIA_FORMAT_SSRC_GROUP_ATTRIBUE_PREFIX + SsrcGroupID;
                foreach (var ssrcAttr in SsrcAttributes)
                {
                    announcement += $" {ssrcAttr.SSRC}";
                }

                announcement += m_CRLF;
            }

            if (SsrcAttributes.Count > 0)
            {
                foreach (var ssrcAttr in SsrcAttributes)
                {
                    if (!string.IsNullOrWhiteSpace(ssrcAttr.Cname))
                    {
                        announcement +=
                            $"{MEDIA_FORMAT_SSRC_ATTRIBUE_PREFIX}{ssrcAttr.SSRC} {SDPSsrcAttribute.MEDIA_CNAME_ATTRIBUE_PREFIX}:{ssrcAttr.Cname}" +
                            m_CRLF;
                    }
                    else
                    {
                        announcement += $"{MEDIA_FORMAT_SSRC_ATTRIBUE_PREFIX}{ssrcAttr.SSRC}" + m_CRLF;
                    }
                }
            }

            // If the "sctpmap" attribute is set, use it instead of the separate "sctpport" and "max-message-size"
            // attributes. They both contain the same information. The "sctpmap" is the legacy attribute and if
            // an application sets it then it's likely to be for a specific reason.
            if (SctpMap != null)
            {
                announcement += $"{MEDIA_FORMAT_SCTP_MAP_ATTRIBUE_PREFIX}{SctpMap}" + m_CRLF;
            }
            else
            {
                if (SctpPort != null)
                {
                    announcement += $"{MEDIA_FORMAT_SCTP_PORT_ATTRIBUE_PREFIX}{SctpPort}" + m_CRLF;
                }

                if (MaxMessageSize != 0)
                {
                    announcement += $"{MEDIA_FORMAT_MAX_MESSAGE_SIZE_ATTRIBUE_PREFIX}{MaxMessageSize}" + m_CRLF;
                }
            }

            return(announcement);
        }