コード例 #1
0
ファイル: CoapResource.cs プロジェクト: malachi-iot/CoAP.Net
 public CoapResource(CoapResourceMetadata metadata)
 {
     Metadata = metadata;
 }
コード例 #2
0
        public static List <CoapResourceMetadata> Parse(string message)
        {
            var state = FormatState.LinkValue;
            var mPos  = 0;

            var result = new List <CoapResourceMetadata>();
            CoapResourceMetadata currentResourceMetadata = null;

            try
            {
                var run = true;
                do
                {
                    if (mPos >= message.Length)
                    {
                        break;
                    }

                    int mSeek;
                    switch (state)
                    {
                    case FormatState.LinkValue:
                        if (message[mPos++] != '<')
                        {
                            throw new ArgumentException($"Expected link-value '<' at pos {mPos}");
                        }
                        mSeek = message.IndexOf('>', mPos);
                        if (currentResourceMetadata != null)
                        {
                            result.Add(currentResourceMetadata);
                        }
                        currentResourceMetadata = new CoapResourceMetadata(message.Substring(mPos, mSeek - mPos));
                        mPos = mSeek + 1;
                        break;

                    case FormatState.LinkParam:
                        if (currentResourceMetadata == null)
                        {
                            throw new InvalidOperationException();
                        }

                        mSeek = message.IndexOf('=', mPos);
                        var param = message.Substring(mPos, mSeek - mPos);

                        mPos  = mSeek + 1;
                        mSeek = message.IndexOfAny(new char[] { ',', ';' }, mPos);
                        if (mSeek == -1)
                        {
                            mSeek = message.Length;
                        }
                        var value = message.Substring(mPos, mSeek - mPos);

                        switch (param)
                        {
                        case "if":
                            value = value.Substring(1, value.Length - 2);
                            foreach (var s in value.Split(' '))
                            {
                                currentResourceMetadata.InterfaceDescription.Add(s);
                            }
                            break;

                        case "rt":
                            value = value.Substring(1, value.Length - 2);
                            foreach (var s in value.Split(' '))
                            {
                                currentResourceMetadata.ResourceTypes.Add(s);
                            }
                            break;

                        case "rel":
                            if (currentResourceMetadata.Rel.Count == 0)
                            {
                                value = value.Substring(1, value.Length - 2);
                                foreach (var s in value.Split(' '))
                                {
                                    currentResourceMetadata.Rel.Add(s);
                                }
                            }
                            break;

                        case "anchor":
                            currentResourceMetadata.Anchor = value.Substring(1, value.Length - 2);
                            break;

                        case "hreflang":
                            // Much easier to let libraries offload language formatting stuff
                            currentResourceMetadata.HrefLang = new System.Globalization.CultureInfo(value).Name.ToLower();
                            break;

                        case "media":
                            if (value[0] == '"')
                            {
                                if (value[value.Length - 1] != '"')
                                {
                                    throw new ArgumentException($"Expected MediaDesc DQUOTE '\"' at pos {mSeek}");
                                }
                                value = value.Substring(1, value.Length - 2);
                            }
                            currentResourceMetadata.Media = value;
                            break;

                        case "title":
                            if (value[0] != '"')
                            {
                                throw new ArgumentException($"Expected QuotedString DQUOTE '\"' at pos {mPos}");
                            }
                            if (value[value.Length - 1] != '"')
                            {
                                throw new ArgumentException($"Expected QuotedString DQUOTE '\"' at pos {mSeek}");
                            }
                            currentResourceMetadata.Title = value.Substring(1, value.Length - 2);
                            break;

                        case "title*":
                            // TODO: No idea what to do here...?
                            var charset = value.Substring(0, value.IndexOf('\''));
                            var lang    = value.Substring(charset.Length + 1, value.IndexOf('\'', charset.Length + 1) - charset.Length - 1);
                            value = value.Substring(charset.Length + lang.Length + 3, value.Length - charset.Length - lang.Length - 4);

                            //System.Diagnostics.Debug.WriteLine("title* = {3}\n\tCharset: {0}\n\tLanguage: {1}\n\tValue: {2}",
                            //    charset, lang, value, Uri.UnescapeDataString(value));

                            currentResourceMetadata.TitleExt = Uri.UnescapeDataString(value);
                            break;

                        case "type":
                            if (value[0] == '"')
                            {
                                if (value[value.Length - 1] != '"')
                                {
                                    throw new ArgumentException($"Expected Type DQUOTE '\"' at pos {mSeek}");
                                }
                                value = value.Substring(1, value.Length - 2);
                            }
                            currentResourceMetadata.Type = value;
                            break;

                        case "sz":
                            if (value[0] == '0' && value.Length != 1)
                            {
                                throw new ArgumentException($"cardinal may not start with '0' unless at pos {mSeek}");
                            }
                            if (!ulong.TryParse(value, out var maxSize))
                            {
                                throw new ArgumentException($"Could not parse cardinal at pos {mSeek}");
                            }
                            currentResourceMetadata.MaxSize = maxSize;
                            break;

                        case "ct":
                            int ct = 0;
                            currentResourceMetadata.SuggestedContentTypes.Clear();

                            if (value[0] == '"')
                            {
                                if (value[value.Length - 1] != '"')
                                {
                                    throw new ArgumentException($"Expected Type DQUOTE '\"' at pos {mSeek}");
                                }

                                foreach (var contentFormatType in value
                                         .Substring(1, value.Length - 2)
                                         .Split(' ')
                                         .Select(s => (Options.ContentFormatType) int.Parse(s)))
                                {
                                    currentResourceMetadata.SuggestedContentTypes.Add(contentFormatType);
                                }
                            }
                            else
                            {
                                if (value[0] == '0' && value.Length != 1)
                                {
                                    throw new ArgumentException($"cardinal may not start with '0' unless at pos {mSeek}");
                                }
                                if (!int.TryParse(value, out ct))
                                {
                                    throw new ArgumentException($"Could not parse cardinal at pos {mSeek}");
                                }

                                currentResourceMetadata.SuggestedContentTypes.Add(ct);
                            }
                            break;

                        default:
                            if (value.Length == 1)
                            {
                                if (!char.IsLetterOrDigit(value[0]) && !new [] { '!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', '-', '.', '/', ':', '<', '=', '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~' }.Contains(value[0]))
                                {
                                    throw new ArgumentException($"PToken contains invalid character '{value[0]}' at pos {mSeek}");
                                }
                                currentResourceMetadata.Extentions.Add(param, value);
                            }
                            else
                            {
                                if (value[0] != '"')
                                {
                                    throw new ArgumentException($"Expected QuotedString DQUOTE '\"' at pos {mPos}");
                                }
                                if (value[value.Length - 1] != '"')
                                {
                                    throw new ArgumentException($"Expected QuotedString DQUOTE '\"' at pos {mSeek}");
                                }
                                currentResourceMetadata.Extentions.Add(param, value.Substring(1, value.Length - 2));
                            }
                            break;
                        }

                        mPos = mSeek;
                        break;

                    default:
                        run = false;
                        break;
                    }
                    if (message[mPos] == ';')
                    {
                        state = FormatState.LinkParam;
                    }
                    else if (message[mPos] == ',')
                    {
                        state = FormatState.LinkValue;
                    }
                    else
                    {
                        throw new ArgumentException($"Invalid character '{message[mPos]}' at pos {mPos}");
                    }
                    mPos++;
                }while (run);
            }
            catch (IndexOutOfRangeException)
            {
                // Moving on...
            }

            if (currentResourceMetadata != null)
            {
                result.Add(currentResourceMetadata);
            }

            return(result);
        }
コード例 #3
0
ファイル: CoapResource.cs プロジェクト: malachi-iot/CoAP.Net
 public CoapResource(Uri uri)
 {
     Metadata = new CoapResourceMetadata(uri);
 }
コード例 #4
0
        public static string ToCoreLinkFormat(CoapResourceMetadata resource, Uri baseUri = null)
        {
            var message = new StringBuilder();

            try
            {
                if (baseUri == null)
                {
                    baseUri = _throwAwayUri;
                }

                var uri = resource.UriReference.IsAbsoluteUri
                    ? resource.UriReference
                    : new Uri(baseUri, resource.UriReference);

                message.Append(CoapUri.Compare(uri, baseUri, UriComponents.HostAndPort, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) == 0
                    ? $"<{uri.AbsolutePath}>"
                    : $"<{uri}>");

                if (resource.InterfaceDescription.Count > 0)
                {
                    message.AppendFormat(";if=\"{0}\"", string.Join(" ", resource.InterfaceDescription));
                }

                if (resource.SuggestedContentTypes.Count == 1)
                {
                    message.Append($";ct={(int)resource.SuggestedContentTypes.First():D}");
                }

                if (resource.SuggestedContentTypes.Count > 1)
                {
                    message.AppendFormat(";ct=\"{0}\"", string.Join(" ", resource.SuggestedContentTypes.Select(ct => ((int)ct).ToString("D"))));
                }

                if (resource.ResourceTypes.Count > 0)
                {
                    message.AppendFormat(";rt=\"{0}\"", string.Join(" ", resource.ResourceTypes));
                }

                if (resource.Rel.Count == 1)
                {
                    message.AppendFormat(";rel={0}", resource.Rel.First());
                }
                if (resource.Rel.Count > 1)
                {
                    message.AppendFormat(";rel=\"{0}\"", string.Join(" ", resource.Rel));
                }

                if (!string.IsNullOrEmpty(resource.Anchor))
                {
                    message.Append($";anchor=\"{resource.Anchor}\"");
                }

                if ((resource.HrefLang ?? string.Empty) != string.Empty)
                {
                    message.Append($";hreflang={resource.HrefLang?.ToLower()}");
                }

                if ((resource.Media ?? string.Empty) != string.Empty)
                {
                    message.Append(resource.Media.Any(c => c == ';' || c == ',')
                        ? $";media=\"{resource.Media}\""
                        : $";media={resource.Media}");
                }

                if ((resource.Title ?? string.Empty) != string.Empty)
                {
                    message.Append($";title=\"{resource.Title}\"");
                }

                //case "title*":
                //    // TODO: No idea what to do here...?
                //    var charset = value.Substring(0, value.IndexOf('\''));
                //    var lang = value.Substring(charset.Length + 1,
                //        value.IndexOf('\'', charset.Length + 1) - charset.Length - 1);
                //    value = value.Substring(charset.Length + lang.Length + 3,
                //        value.Length - charset.Length - lang.Length - 4);

                //    //System.Diagnostics.Debug.WriteLine("title* = {3}\n\tCharset: {0}\n\tLanguage: {1}\n\tValue: {2}",
                //    //    charset, lang, value, Uri.UnescapeDataString(value));

                //    resource.TitleExt = Uri.UnescapeDataString(value);
                //    break;

                if ((resource.Type ?? string.Empty) != string.Empty)
                {
                    message.Append(resource.Type.Contains(" ")
                        ? $";type=\"{resource.Type}\""
                        : $";type={resource.Type}");
                }

                if (resource.MaxSize != 0)
                {
                    message.Append($";sz={resource.MaxSize:D}");
                }


                //default:
                //    if (value.Length == 1)
                //    {
                //        if (!char.IsLetterOrDigit(value[0]) && !new[]
                //        {
                //            '!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', '-', '.', '/', ':',
                //            '<', '=', '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~'
                //        }.Contains(value[0]))
                //            throw new ArgumentException(
                //                $"PToken contains invalid character '{value[0]}' at pos {mSeek}");
                //        resource.Extentions.Add(param, value);
                //    }
                //    else
                //    {
                //        if (value[0] != '"')
                //            throw new ArgumentException(
                //                $"Expected QuotedString DQUOTE '\"' at pos {mPos}");
                //        if (value[value.Length - 1] != '"')
                //            throw new ArgumentException(
                //                $"Expected QuotedString DQUOTE '\"' at pos {mSeek}");
                //        resource.Extentions.Add(param,
                //            value.Substring(1, value.Length - 2));
                //    }
                //    break;
            }
            catch (IndexOutOfRangeException)
            {
                // Moving on...
            }
            return(message.ToString());
        }