/// <exclude/>
        protected virtual int CreateAttrId(ushort attrId, byte[] buf, int offset)
        {
            ServiceElement dummyElement
                = new ServiceElement(
                      ElementType.UInt16, unchecked (attrId));

            return(CreateElement(dummyElement, buf, offset));
        }
        private void WriteInt32(ServiceElement element, int value, byte[] buf, ref int offset, out int totalLength)
        {
            int host32 = value;
            int net32  = IPAddress.HostToNetworkOrder(host32);

            byte[] valueBytes = BitConverter.GetBytes(net32);
            WriteFixedLength(element, valueBytes, buf, ref offset, out totalLength);
        }
        private void WriteInt64(ServiceElement element, long value, byte[] buf, ref int offset, out int totalLength)
        {
            long host64 = value;
            long net64  = IPAddress.HostToNetworkOrder(host64);

            byte[] valueBytes = BitConverter.GetBytes(net64);
            WriteFixedLength(element, valueBytes, buf, ref offset, out totalLength);
        }
        private void WriteInt16(ServiceElement element, short value, byte[] buf, ref int offset, out int totalLength)
        {
            short host16 = value;
            short net16  = IPAddress.HostToNetworkOrder(host16);

            byte[] valueBytes = BitConverter.GetBytes(net16);
            WriteFixedLength(element, valueBytes, buf, ref offset, out totalLength);
        }
        protected virtual void WriteFixedLength(ServiceElement element, byte[] valueBytes, byte[] buf, ref int offset, out int totalLength)
        {
            int headerLen = WriteHeaderFixedLength(element.ElementTypeDescriptor, valueBytes.Length, buf, offset, out totalLength);

            offset += headerLen;
            VerifyWriteSpaceRemaining(valueBytes.Length, buf, offset);
            valueBytes.CopyTo(buf, offset);
            System.Diagnostics.Debug.Assert(totalLength == headerLen + valueBytes.Length);
        }
        /// <summary>
        /// Reads the RFCOMM Channel Number value from the service record,
        /// or returns -1 if the element is not present.
        /// </summary>
        /// -
        /// <param name="record">The <see cref="ServiceRecord"/>
        /// to search for the element.
        /// </param>
        /// -
        /// <returns>The Channel Number as an unsigned byte cast to an Int32,
        /// or -1 if at the <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList"/>
        /// attribute is missing or contains invalid elements.
        /// </returns>
        public static int GetRfcommChannelNumber(ServiceRecord record)
        {
            ServiceElement channelElement = GetRfcommChannelElement(record);

            if (channelElement == null)
            {
                return(-1);
            }
            return(GetRfcommChannelNumber(channelElement));
        }
        protected virtual void WriteVariableLength(ServiceElement element, byte[] valueBytes, byte[] buf, ref int offset, out int totalLength)
        {
            int curLen;

            curLen  = MakeVariableLengthHeader(buf, offset, element.ElementTypeDescriptor, out HeaderWriteState headerState);
            offset += curLen;
            VerifyWriteSpaceRemaining(valueBytes.Length, buf, offset);
            valueBytes.CopyTo(buf, offset);//write
            offset += valueBytes.Length;
            CompleteHeaderWrite(headerState, buf, offset, out totalLength);
        }
        /// <summary>
        /// Sets the RFCOMM Channel Number value in the service record.
        /// </summary>
        /// -
        /// <param name="record">The <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/>
        /// in which to set the RFCOMM Channel number.
        /// </param>
        /// <param name="channelNumber">The Channel number to set in the record.
        /// </param>
        /// -
        /// <exception cref="T:System.InvalidOperationException">The
        /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList"/>
        /// attribute is missing or contains invalid elements.
        /// </exception>
        public static void SetRfcommChannelNumber(ServiceRecord record, byte channelNumber)
        {
            ServiceElement channelElement = GetRfcommChannelElement(record);

            if (channelElement == null)
            {
                throw new InvalidOperationException("ProtocolDescriptorList element does not exist or is not in the RFCOMM format.");
            }
            System.Diagnostics.Debug.Assert(channelElement.ElementType == ElementType.UInt8);
            channelElement.SetValue(channelNumber);
        }
        public string GetMultiLanguageStringAttributeById(ushort id, LanguageBaseItem language)
        {
            if (language == null)
            {
                throw new ArgumentNullException("language");
            }
            ushort           actualId = CreateLanguageBasedAttributeId(id, language.AttributeIdBase);
            ServiceAttribute attr     = GetAttributeById(actualId);
            ServiceElement   element  = attr.Value;
            // (No need to check that element is of type TextString, that's handled inside the following).
            string str = element.GetValueAsString(language);

            return(str);
        }
예제 #10
0
        private static ServiceElement ServiceElementFromUuid(object classRaw)
        {
            ServiceElement tmp = null;

            uint classU32 = 99;
            bool writeIntegral;

            // First check raw type, and also if u16/u32 inside Guid.
            // If Guid write it, otherwise handle all integral value.
            if (classRaw is Guid uuid128)
            {
                if (ServiceRecordUtilities.IsUuid32Value(uuid128))
                {
                    classU32      = ServiceRecordUtilities.GetAsUuid32Value(uuid128);
                    writeIntegral = true;
                }
                else
                {
                    tmp           = new ServiceElement(ElementType.Uuid128, uuid128);
                    writeIntegral = false;
                }
            }
            else
            {
                System.Diagnostics.Debug.Assert(classRaw != null,
                                                "Unexpected ServiceClassId value: null");
                System.Diagnostics.Debug.Assert(classRaw is int,
                                                "Unexpected ServiceClassId type: " + classRaw.GetType().Name);
                int i32 = (int)classRaw;
                classU32      = unchecked ((uint)i32);
                writeIntegral = true;
            }
            if (writeIntegral)
            {
                try
                {
                    ushort u16 = Convert.ToUInt16(classU32);
                    Debug.Assert(classU32 <= ushort.MaxValue, "NOT replace the throw, LTE");
                    tmp = new ServiceElement(ElementType.Uuid16, u16);
                }
                catch (OverflowException)
                {
                    Debug.Assert(classU32 > ushort.MaxValue, "NOT replace the throw, GT");
                    tmp = new ServiceElement(ElementType.Uuid32, classU32);
                }
            }

            return(tmp);
        }
예제 #11
0
        /// <summary>
        /// Add a custom attribute of simple type.
        /// </summary>
        /// -
        /// <remarks>
        /// <para>If the <paramref name="elementType"/> is a numerical type
        /// then this is equivalent to using
        /// <see cref="M:InTheHand.Net.Bluetooth.ServiceElement.CreateNumericalServiceElement(InTheHand.Net.Bluetooth.ElementType,System.Object)"/>
        /// otherwise the value is used directly in creating the
        /// <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/>.
        /// </para>
        /// </remarks>
        /// -
        /// <param name="id">The Attribute Id as a <see cref="T:InTheHand.Net.Bluetooth.ServiceAttributeId"/>.</param>
        /// <param name="elementType">The type of the element as an <see cref="T:InTheHand.Net.Bluetooth.ElementType"/>.</param>
        /// <param name="value">The value for the new element.</param>
        public void AddCustomAttribute(ushort id, ElementType elementType, object value)
        {
            ServiceElement        e;
            ElementTypeDescriptor etd = ServiceRecordParser.GetEtdForType(elementType);

            if ((etd == ElementTypeDescriptor.UnsignedInteger ||
                 etd == ElementTypeDescriptor.TwosComplementInteger))
            {
                e = ServiceElement.CreateNumericalServiceElement(elementType, value);
            }
            else
            {
                e = new ServiceElement(elementType, value);
            }
            AddCustomAttribute(new ServiceAttribute(id, e));
        }
예제 #12
0
        //--------------------
        //

        /// <summary>
        /// Gets the list of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>
        /// items in the service record.
        /// </summary>
        /// -
        /// <param name="elementSequence">
        /// A <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/> holding the
        /// data from the
        /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList"/>
        /// attribute.
        /// </param>
        /// -
        /// <returns>
        /// An array of <see cref="T:InTheHand.Net.Bluetooth.LanguageBaseItem"/>.
        /// An array length zero is returned if the service record contains no such attribute.
        /// </returns>
        /// -
        /// <exception cref="T:System.ArgumentException">
        /// <paramref name="elementSequence"/> is not of type
        /// <see cref="F:InTheHand.Net.Bluetooth.ElementType.ElementSequence"/>.
        /// </exception>
        /// <exception cref="T:System.Net.ProtocolViolationException">
        /// The element sequence contains incorrectly formatted or invalid content,
        /// for example it contains the wrong element data types, or doesn't contain
        /// the elements in groups of three as required.
        /// </exception>
        public static LanguageBaseItem[] ParseListFromElementSequence(ServiceElement elementSequence)
        {
            if (elementSequence.ElementType != ElementType.ElementSequence)
            {
                throw new ArgumentException(ErrorMsgLangBaseListParseNotSequence);
            }
#if V1
            IList elementList = elementSequence.GetValueAsElementList();
#else
            IList <ServiceElement> elementList = elementSequence.GetValueAsElementList();
#endif
            int       numElements     = elementList.Count;
            const int ElementsPerItem = 3;
            if (numElements == 0 || (numElements % ElementsPerItem) != 0)
            {
                throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseNotInThrees);
            }
            int numItems             = numElements / ElementsPerItem;
            LanguageBaseItem[] items = new LanguageBaseItem[numItems];
            for (int i = 0; i < numItems; ++i)
            {
                // Casts are for the non-Generic version.
                ServiceElement e1Lang   = elementList[i * ElementsPerItem];
                ServiceElement e2EncId  = elementList[i * ElementsPerItem + 1];
                ServiceElement e3BaseId = elementList[i * ElementsPerItem + 2];
                if (e1Lang.ElementType != ElementType.UInt16 || e2EncId.ElementType != ElementType.UInt16 || e3BaseId.ElementType != ElementType.UInt16)
                {
                    throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseNotU16);
                }
                if ((ushort)e3BaseId.Value == 0)
                {
                    throw new System.Net.ProtocolViolationException(ErrorMsgLangBaseListParseBaseInvalid);
                }
                LanguageBaseItem item = new LanguageBaseItem(
                    (ushort)e1Lang.Value, (ushort)e2EncId.Value, (ushort)e3BaseId.Value);
                items[i] = item;
            }
            return(items);
        }
        private void WriteUInt64(ServiceElement element, ulong value, byte[] buf, ref int offset, out int totalLength)
        {
            long valueS = unchecked ((long)value);

            WriteInt64(element, valueS, buf, ref offset, out totalLength);
        }
        private void WriteUInt32(ServiceElement element, uint value, byte[] buf, ref int offset, out int totalLength)
        {
            int valueS = unchecked ((int)value);

            WriteInt32(element, valueS, buf, ref offset, out totalLength);
        }
        private void WriteSByte(ServiceElement element, sbyte value, byte[] buf, ref int offset, out int totalLength)
        {
            byte valueU = unchecked ((byte)value);

            WriteByte(element, valueU, buf, ref offset, out totalLength);
        }
 private void WriteByte(ServiceElement element, byte value, byte[] buf, ref int offset, out int totalLength)
 {
     byte[] valueBytes = new byte[1];
     valueBytes[0] = value;
     WriteFixedLength(element, valueBytes, buf, ref offset, out totalLength);
 }
        //--------------------------------------------
        private void WriteUInt16(ServiceElement element, ushort value, byte[] buf, ref int offset, out int totalLength)
        {
            short valueS = unchecked ((short)value);

            WriteInt16(element, valueS, buf, ref offset, out totalLength);
        }
        /// <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)
            {
                int curLen;
                curLen  = MakeVariableLengthHeader(buf, offset, element.ElementTypeDescriptor, out HeaderWriteState 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, (ushort)element.Value, buf, ref offset, out totalLength);
                    break;

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

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

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

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

                case ElementType.Int64:
                    WriteInt64(element, (long)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, (ushort)element.Value, buf, ref offset, out totalLength);
                }
                else if (element.ElementType == ElementType.Uuid32)
                {
                    WriteUInt32(element, (uint)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  = Sockets.BluetoothListener.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;
                if (element.Value is string valueString)
                {
                    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);
        }