예제 #1
0
 //--------
 private static void DumpAdditionalProtocolDescriptorLists(TextWriter writer, int depth, ServiceElement element)
 {
     Debug.Assert(element.ElementType == ElementType.ElementSequence);
     //
     // Is a list of PDLs
     foreach (ServiceElement curList in element.GetValueAsElementList())
     {
         DumpProtocolDescriptorList(writer, depth + 1, curList);
     }//foreach
 }
예제 #2
0
        private static void DumpProtocolDescriptorListList(TextWriter writer, int depth, ServiceElement element)
        {
            // The list.
            Debug.Assert(element.ElementType == ElementType.ElementSequence);
            WritePrefix(writer, depth);
            writer.Write("( ");
            bool firstLayer = true;

            foreach (ServiceElement layer in element.GetValueAsElementList())
            {
                ServiceElement[] items = layer.GetValueAsElementArray();
                int used = 0;
                Debug.Assert(items[used].ElementTypeDescriptor == ElementTypeDescriptor.Uuid);
                Guid           protoGuid = items[used].GetValueAsUuid();
                string         protoStr;
                HackProtocolId proto = GuidToHackProtocolId(protoGuid, out protoStr);
                //
                used++;
                writer.Write("{0}( {1}", (firstLayer ? string.Empty : ", "), protoStr);
                if (proto == HackProtocolId.L2Cap)
                {
                    if (used < items.Length)
                    {
                        Debug.Assert(items[used].ElementType == ElementType.UInt16);
                        var u16 = (ushort)items[used].Value;
                        HackProtocolServiceMultiplexer psm = unchecked ((HackProtocolServiceMultiplexer)u16);
                        used++;
                        writer.Write(", PSM={0}", Enum_ToStringNameOrHex(psm));
                    }
                }
                else if (proto == HackProtocolId.Rfcomm)
                {
                    if (used < items.Length)
                    {
                        Debug.Assert(items[used].ElementType == ElementType.UInt8);
                        byte channelNumber = (byte)items[used].Value;
                        used++;
                        writer.Write(", ChannelNumber={0}", channelNumber);
                    }
                }
                // Others include BNEP for instance, which isn't defined in the base SDP spec.
                if (used < items.Length)
                {
                    writer.Write(", ...");
                }
                writer.Write(" )");
                firstLayer = false;
            }//foreach layer
            writer.WriteLine(" )");
        }
예제 #3
0
 private static void DumpProtocolDescriptorList(TextWriter writer, int depth, ServiceElement element)
 {
     Debug.Assert(element.ElementType == ElementType.ElementAlternative ||
                  element.ElementType == ElementType.ElementSequence);
     //
     // If passes a list of alternatives, each a protocol descriptor list,
     // then call ourselves on each list.
     if (element.ElementType == ElementType.ElementAlternative)
     {
         foreach (ServiceElement curStack in element.GetValueAsElementList())
         {
             DumpProtocolDescriptorListList(writer, depth + 1, curStack);
         }//foreach
         return;
     }
     //else
     DumpProtocolDescriptorListList(writer, depth, element);
 }
예제 #4
0
 private static void DumpRawElement(TextWriter writer, int depth, ServiceElement elem)
 {
     WritePrefix(writer, depth);
     if (elem.ElementType == ElementType.ElementSequence ||
         elem.ElementType == ElementType.ElementAlternative)
     {
         writer.WriteLine("{0}", elem.ElementType);
         foreach (ServiceElement element in elem.GetValueAsElementList())
         {
             DumpRawElement(writer, depth + 1, element);
         }
     }
     else if (elem.ElementType == ElementType.Nil)
     {
         writer.WriteLine("Nil:");
     }
     else if (elem.ElementType == ElementType.TextString ||
              elem.ElementType == ElementType.Boolean ||
              elem.ElementType == ElementType.Url)
     {
         // Non-numeric types
         writer.WriteLine("{0}: {1}", elem.ElementType, elem.Value);
     }
     else if (elem.ElementType == ElementType.Uuid128)
     {
         writer.WriteLine("{0}: {1}", elem.ElementType, elem.Value);
     }
     else if (elem.ElementType == ElementType.UInt128 ||
              elem.ElementType == ElementType.Int128)
     {
         string valueText = BitConverter.ToString((byte[])elem.Value);
         writer.WriteLine("{0}: {1}", elem.ElementType, valueText);
     }
     else
     {
         writer.WriteLine("{0}: 0x{1:X}", elem.ElementType, elem.Value);
         //{catch(?FOrmatExptn){
         //   writer.WriteLine("{0}: 0x{1}", elem.Type, elem.Value);
         //}
     }
 }
예제 #5
0
        // TODO GetRfcommChannelElement(ServiceAttribute attr) Could be public -> Tests!
        internal static ServiceElement GetChannelElement(ServiceAttribute attr,
                                                         BluetoothProtocolDescriptorType proto,
                                                         out bool?isSimpleRfcomm)
        {
            if (proto != BluetoothProtocolDescriptorType.L2Cap &&
                proto != BluetoothProtocolDescriptorType.Rfcomm)
            {
                throw new ArgumentException("Can only fetch RFCOMM or L2CAP element.");
            }

            //
            isSimpleRfcomm = true;
            Debug.Assert(attr != null, "attr != null");
            ServiceElement e0 = attr.Value;

            if (e0.ElementType == ElementType.ElementAlternative)
            {
                Trace.WriteLine("Don't support ElementAlternative ProtocolDescriptorList values.");

                goto NotFound;
            }
            else if (e0.ElementType != ElementType.ElementSequence)
            {
                Trace.WriteLine("Bad ProtocolDescriptorList base element.");

                goto NotFound;
            }
            IList <ServiceElement>       protoStack = e0.GetValueAsElementList();
            IEnumerator <ServiceElement> etor       = protoStack.GetEnumerator();
            ServiceElement         layer;
            IList <ServiceElement> layerContent;
            ServiceElement         channelElement;

            // -- L2CAP Layer --
            if (!etor.MoveNext())
            {
                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,
                                              "Protocol stack truncated before {0}.", "L2CAP"));

                goto NotFound;
            }
            layer        = etor.Current; //cast here are for non-Generic version.
            layerContent = layer.GetValueAsElementList();
            if (layerContent[0].GetValueAsUuid() != BluetoothProtocol.L2CapProtocol)
            {
                Trace.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                              "Bad protocol stack, layer {0} is not {1}.", 1, "L2CAP"));
                goto NotFound;
            }
            bool hasPsmEtc = layerContent.Count != 1;

            // Cast for FX1.1 object
            isSimpleRfcomm = (bool)isSimpleRfcomm && !hasPsmEtc;
            if (proto == BluetoothProtocolDescriptorType.L2Cap)
            {
                if (layerContent.Count < 2)
                {
                    Trace.WriteLine("L2CAP PSM element was requested but the L2CAP layer in this case hasn't a second element.");

                    goto NotFound;
                }
                channelElement = (ServiceElement)layerContent[1];
                goto Success;
            }
            //
            // -- RFCOMM Layer --
            if (!etor.MoveNext())
            {
                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,
                                              "Protocol stack truncated before {0}.", "RFCOMM"));

                goto NotFound;
            }
            layer        = etor.Current;
            layerContent = layer.GetValueAsElementList();
            if (layerContent[0].GetValueAsUuid() != BluetoothProtocol.RFCommProtocol)
            {
                Trace.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                              "Bad protocol stack, layer {0} is not {1}.", 2, "RFCOMM"));

                goto NotFound;
            }
            //
            if (layerContent.Count < 2)
            {
                Trace.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                              "Bad protocol stack, layer {0} hasn't a second element.", 2));

                goto NotFound;
            }
            channelElement = (ServiceElement)layerContent[1];
            if (channelElement.ElementType != ElementType.UInt8)
            {
                Trace.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                              "Bad protocol stack, layer {0} is not UInt8.", 2));

                goto NotFound;
            }
            // Success
            //
            // -- Any remaining layer(s) --
            bool extraLayers = etor.MoveNext();

            isSimpleRfcomm = (bool)isSimpleRfcomm && !extraLayers;
Success:
            //
            return(channelElement);

NotFound:
            isSimpleRfcomm = null;
            return(null);
        }
예제 #6
0
        private static XElement GetAttributeValue(ServiceElement value)
        {
            // There isn't much formal documentation on the BlueZ SDP XML format.
            // The actual serialization is implemented in the convert_raw_data_to_xml
            // function at https://github.com/bluez/bluez/blob/9be85f867856195e16c9b94b605f65f6389eda33/src/sdp-xml.c#L637
            switch (value.ElementType)
            {
            case ElementType.Nil:
                return(new XElement("nil"));

            case ElementType.Boolean:
                var boolean = new XElement("boolean");
                boolean.SetAttributeValue("value", (bool)value.Value ? "true" : "false");
                return(boolean);

            case ElementType.UInt8:
                var uint8 = new XElement("uint8");
                uint8.SetAttributeValue("value", $"0x{value.Value:x2}");
                return(uint8);

            case ElementType.UInt16:
                var uint16 = new XElement("uint16");
                uint16.SetAttributeValue("value", $"0x{value.Value:x4}");
                return(uint16);

            case ElementType.UInt32:
                var uint32 = new XElement("uint32");
                uint32.SetAttributeValue("value", $"0x{value.Value:x8}");
                return(uint32);

            case ElementType.UInt64:
                var uint64 = new XElement("uint64");
                uint64.SetAttributeValue("value", $"0x{value.Value:x16}");
                return(uint64);

            case ElementType.Int8:
                var int8 = new XElement("int8");
                int8.SetAttributeValue("value", $"{value.Value:d}");
                return(int8);

            case ElementType.Int16:
                var int16 = new XElement("int16");
                int16.SetAttributeValue("value", $"{value.Value:d}");
                return(int16);

            case ElementType.Int32:
                var int32 = new XElement("int32");
                int32.SetAttributeValue("value", $"{value.Value:d}");
                return(int32);

            case ElementType.Int64:
                var int64 = new XElement("int64");
                int64.SetAttributeValue("value", $"{value.Value:d}");
                return(int64);

            case ElementType.Uuid16:
                var uuid16 = new XElement("uuid");
                uuid16.SetAttributeValue("value", $"0x{value.Value:x4}");
                return(uuid16);

            case ElementType.Uuid32:
                var uuid32 = new XElement("uuid");
                uuid32.SetAttributeValue("value", $"0x{value.Value:x8}");
                return(uuid32);

            case ElementType.Uuid128:
                var uuid128 = new XElement("uuid");
                uuid128.SetAttributeValue("value", $"0x{value.Value:D}");
                return(uuid128);

            case ElementType.TextString:
                var textString = new XElement("text");

                if (value.Value is byte[])
                {
                    textString.SetAttributeValue("encoding", "hex");
                    textString.SetAttributeValue("value", GetHexString((byte[])value.Value));
                }
                else
                {
                    textString.SetAttributeValue("value", (string)value.Value);
                }

                return(textString);

            case ElementType.Url:
                var url = new XElement("url");
                url.SetAttributeValue("value", value.Value);
                return(url);

            case ElementType.ElementSequence:
                var sequence = new XElement("sequence");

                foreach (var child in value.GetValueAsElementList())
                {
                    sequence.Add(GetAttributeValue(child));
                }

                return(sequence);

            case ElementType.ElementAlternative:
                var alternate = new XElement("alternate");

                foreach (var child in value.GetValueAsElementList())
                {
                    alternate.Add(GetAttributeValue(child));
                }

                return(alternate);

            default:
                throw new ArgumentOutOfRangeException(nameof(value));
            }
        }
예제 #7
0
        /// <summary>
        /// Create the element in the buffer starting at offset, and return its totalLength.
        /// </summary>
        /// <param name="element">The element to create.
        /// </param>
        /// <param name="buf">The byte array to write the encoded element to.
        /// </param>
        /// <param name="offset">The place to start writing in <paramref name="buf"/>.
        /// </param>
        ///
        /// <returns>The total length of the encoded element written to the buffer
        /// </returns>
        protected virtual int CreateElement(ServiceElement element, byte[] buf, int offset)
        {
            int totalLength;

            //
            if (element.ElementTypeDescriptor == ElementTypeDescriptor.ElementSequence ||
                element.ElementTypeDescriptor == ElementTypeDescriptor.ElementAlternative)
            {
                HeaderWriteState headerState;
                int curLen;
                curLen  = MakeVariableLengthHeader(buf, offset, element.ElementTypeDescriptor, out headerState);
                offset += curLen;
                foreach (ServiceElement childElement in element.GetValueAsElementList())
                {
                    curLen  = CreateElement(childElement, buf, offset);
                    offset += curLen;
                }//for
                CompleteHeaderWrite(headerState, buf, offset, out totalLength);
                //----------------
            }
            else if (element.ElementTypeDescriptor == ElementTypeDescriptor.UnsignedInteger ||
                     element.ElementTypeDescriptor == ElementTypeDescriptor.TwosComplementInteger)
            {
                switch (element.ElementType)
                {
                case ElementType.UInt8:
                    WriteByte(element, (Byte)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.Int8:
                    WriteSByte(element, (SByte)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.UInt16:
                    WriteUInt16(element, (UInt16)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.Int16:
                    WriteInt16(element, (Int16)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.UInt32:
                    WriteUInt32(element, (UInt32)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.Int32:
                    WriteInt32(element, (Int32)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.UInt64:
                    WriteUInt64(element, (UInt64)element.Value, buf, ref offset, out totalLength);
                    break;

                case ElementType.Int64:
                    WriteInt64(element, (Int64)element.Value, buf, ref offset, out totalLength);
                    break;

                default:
                    System.Diagnostics.Debug.Fail(String.Format(System.Globalization.CultureInfo.InvariantCulture,
                                                                "Unexpected integral type '{0}'.", element.ElementType));
                    totalLength = 0;
                    break;
                }//switch
                 //----------------
            }
            else if (element.ElementTypeDescriptor == ElementTypeDescriptor.Uuid)
            {
                if (element.ElementType == ElementType.Uuid16)
                {
                    WriteUInt16(element, (UInt16)element.Value, buf, ref offset, out totalLength);
                }
                else if (element.ElementType == ElementType.Uuid32)
                {
                    WriteUInt32(element, (UInt32)element.Value, buf, ref offset, out totalLength);
                }
                else
                {
                    //TODO If the 'Guid' holds a 'Bluetooth-based' UUID, then should we write the short form?
                    byte[] bytes;
                    System.Diagnostics.Debug.Assert(element.ElementType == ElementType.Uuid128);
                    Guid hostGuid = (Guid)element.Value;
                    Guid netGuid  = BluetoothAddress.HostToNetworkOrder(hostGuid);
                    bytes = netGuid.ToByteArray();
                    WriteFixedLength(element, bytes, buf, ref offset, out totalLength);
                }
                //----------------
            }
            else if (element.ElementTypeDescriptor == ElementTypeDescriptor.Url)
            {
                Uri    uri        = element.GetValueAsUri();
                String uriString  = uri.ToString();
                byte[] valueBytes = System.Text.Encoding.ASCII.GetBytes(uriString);
                WriteVariableLength(element, valueBytes, buf, ref offset, out totalLength);
                //----------------
            }
            else if (element.ElementTypeDescriptor == ElementTypeDescriptor.TextString)
            {
                byte[] valueBytes;
                String valueString = element.Value as String;
                if (valueString != null)
                {
                    valueBytes = System.Text.Encoding.UTF8.GetBytes(valueString);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(element.Value is byte[]);
                    valueBytes = (byte[])element.Value;
                }
                WriteVariableLength(element, valueBytes, buf, ref offset, out totalLength);
                //----------------
            }
            else if (element.ElementTypeDescriptor == ElementTypeDescriptor.Nil)
            {
                WriteFixedLength(element, new byte[0], buf, ref offset, out totalLength);
                //----------------
            }
            else if (element.ElementTypeDescriptor == ElementTypeDescriptor.Boolean)
            {
                bool   value      = (bool)element.Value;
                byte[] valueBytes = new byte[1];
                valueBytes[0] = value ? (byte)1 : (byte)0;
                WriteFixedLength(element, valueBytes, buf, ref offset, out totalLength);
                //----------------
            }
            else
            {
                totalLength = 0;
            }
            //
            if (totalLength == 0)
            {
                throw new NotSupportedException(String.Format(System.Globalization.CultureInfo.InvariantCulture,
                                                              "Creation of element type '{0}' not implemented.", element.ElementType));
            }
            return(totalLength);
        }
예제 #8
0
 private static void DumpElement(TextWriter writer, int depth, ServiceElement elem)
 {
     WritePrefix(writer, depth);
     if (elem.ElementType == ElementType.ElementSequence || elem.ElementType == ElementType.ElementAlternative)
     {
         writer.WriteLine("{0}", elem.ElementType);
         foreach (ServiceElement element in elem.GetValueAsElementList())
         {
             DumpElement(writer, depth + 1, element);
         }//for
     }
     else if (elem.ElementType == ElementType.Nil)
     {
         writer.WriteLine("Nil:");
     }
     else if (elem.ElementType == ElementType.TextString)
     {
         DumpString(writer, depth, elem, null);
     }
     else if (elem.ElementType == ElementType.Boolean ||
              elem.ElementType == ElementType.Url)
     {
         // Non-numeric types
         writer.WriteLine("{0}: {1}", elem.ElementType, elem.Value);
     }
     else
     {
         string name      = null;
         string valueText = null;
         if (elem.ElementTypeDescriptor == ElementTypeDescriptor.Uuid)
         {
             if (elem.ElementType == ElementType.Uuid16)
             {
                 name = BluetoothService.GetName((ushort)elem.Value);
             }
             else if (elem.ElementType == ElementType.Uuid32)
             {
                 name = BluetoothService.GetName((uint)elem.Value);
             }
             else
             {
                 Debug.Assert(elem.ElementType == ElementType.Uuid128);
                 name      = BluetoothService.GetName((Guid)elem.Value);
                 valueText = ((Guid)elem.Value).ToString();
             }
         }//if UUID
         if (valueText == null)
         {
             if (elem.ElementTypeDescriptor == ElementTypeDescriptor.Unknown)
             {
                 valueText = "unknown";
             }
             else if (elem.ElementType == ElementType.UInt128 ||
                      elem.ElementType == ElementType.Int128)
             {
                 valueText = BitConverter.ToString((byte[])elem.Value);
             }
             else
             {
                 valueText = string.Format(System.Globalization.CultureInfo.InvariantCulture, "0x{0:X}", elem.Value);
             }
         }
         if (name == null)
         {
             writer.WriteLine("{0}: {1}", elem.ElementType, valueText);
         }
         else
         {
             writer.WriteLine("{0}: {1} -- {2}", elem.ElementType, valueText, name);
         }
     }//else
 }