예제 #1
0
        protected override ObexPacket?OnClientRequest(ObexPacket clientRequestPacket)
        {
            Console.WriteLine("Opcode: " + clientRequestPacket.Opcode);

            if (clientRequestPacket.Opcode == Opcode.Put || clientRequestPacket.Opcode == Opcode.PutAlter)
            {
                string bodyString;
                if (clientRequestPacket.Headers.ContainsKey(HeaderId.EndOfBody))
                {
                    bodyString = ((BodyHeader)clientRequestPacket.Headers[HeaderId.EndOfBody]).Value !;
                }
                else
                {
                    Console.WriteLine("Recieved header dose not contains EndOfBody, abort! ");
                    return(null);
                }

                clientRequestPacket.PrintHeaders();
                Console.WriteLine("Body: " + bodyString);
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(bodyString);
                string handle = doc.SelectSingleNode("/MAP-event-report/event/@handle").Value;
                MessageReceived?.Invoke(this, new MessageReceivedEventArgs(handle));

                return(new ObexPacket(Opcode.Success));
            }

            return(null);
        }
예제 #2
0
        /// <summary>
        /// Retrieve messages listing from MSE
        /// </summary>
        /// <param name="maxListCount">Maximum number of messages listed.</param>
        /// <param name="folderName">The name of the folder.</param>
        /// <returns>message handle list</returns>
        /// TODO: return Messages-Listing objects
        public async Task <List <string> > GetMessageListing(ushort maxListCount, string folderName = "telecom")
        {
            ObexPacket packet = new ObexPacket(
                Opcode.GetAlter
                //, new Int32ValueHeader(HeaderId.SingleResponseMode, 0x01)
                , new AsciiStringValueHeader(HeaderId.Type, "x-bt/MAP-msg-listing")
                , new UnicodeStringValueHeader(HeaderId.Name, folderName)
                , new AppParamHeader(new AppParameter(AppParamTagId.MaxListCount, maxListCount))
                );

            Console.WriteLine($"Sending GetMessageListing request ");
            ObexPacket resp = await RunObexRequest(packet);

            XmlDocument xml = new XmlDocument();

            xml.LoadXml(((Utf8StringValueHeader)resp.Headers[HeaderId.EndOfBody]).Value);
            XmlNodeList   list = xml.SelectNodes("/MAP-msg-listing/msg/@handle");
            List <string> ret  = new List <string>();

            Console.WriteLine("Message handle list: ");
            foreach (XmlNode n in list)
            {
                if (n.Value != null)
                {
                    Console.WriteLine(n.Value);
                    ret.Add(n.Value);
                }
            }

            return(ret);
        }
예제 #3
0
        public async Task <List <string> > GetFolderList()
        {
            ObexPacket packet = new ObexPacket(
                Opcode.GetAlter
                , new AsciiStringValueHeader(HeaderId.Type, "x-obex/folder-listing")
                //, new AppParamHeader(new AppParameter(AppParamTagId.MaxListCount, 100))
                );

            Console.WriteLine("sending GetFolderList request");

            ObexPacket resp = await RunObexRequest(packet);

            XmlDocument xml = new XmlDocument();

            xml.LoadXml(((Utf8StringValueHeader)resp.Headers[HeaderId.EndOfBody]).Value);
            XmlNodeList   list = xml.SelectNodes("/folder-listing/folder/@name");
            List <string> ret  = new List <string>();

            Console.WriteLine("Folder list: ");
            foreach (XmlNode n in list)
            {
                if (n.Value != null)
                {
                    Console.WriteLine(n.Value);
                    ret.Add(n.Value);
                }
            }

            return(ret);
        }
예제 #4
0
        public async Task GetMASInstanceInformation()
        {
            ObexPacket packet = new ObexPacket(
                Opcode.Get
                , new AsciiStringValueHeader(HeaderId.Type, "x-bt/MASInstanceInformation")
                , new AppParamHeader(new AppParameter(AppParamTagId.MASInstanceID, MAS_UUID))
                );

            Console.WriteLine($"Sending GetMASInstanceInformation request ");
            await RunObexRequest(packet);
        }
예제 #5
0
        public void StartServer()
        {
            Task.Run(async() =>
            {
                while (true)
                {
                    _cts.Token.ThrowIfCancellationRequested();

                    ObexPacket packet = await ObexPacket.ReadFromStream(_reader, new ObexConnectPacket());
                    if (packet.Opcode == Opcode.Connect)
                    {
                        if (packet.Headers.ContainsKey(HeaderId.Target))
                        {
                            BytesHeader targetHeader = (BytesHeader)packet.Headers[HeaderId.Target];
                            if (targetHeader.Value != null)
                            {
                                if (Enumerable.SequenceEqual(targetHeader.Value, _serviceUuid.Value))
                                {
                                    packet.Opcode = Opcode.Success;
                                    _writer.WriteBuffer(packet.ToBuffer());
                                    await _writer.StoreAsync();
                                    break;
                                }
                            }
                        }
                    }

                    Console.WriteLine("Not support operation code: " + packet.Opcode);
                    Console.WriteLine("MSE should send Connect request first");
                    packet = new ObexPacket(Opcode.OBEX_UNAVAILABLE);
                    _writer.WriteBuffer(packet.ToBuffer());
                }

                while (true)
                {
                    _cts.Token.ThrowIfCancellationRequested();

                    ObexPacket packet = await ObexPacket.ReadFromStream(_reader);

                    ObexPacket?response = OnClientRequest(packet);
                    if (response != null)
                    {
                        _writer.WriteBuffer(response.ToBuffer());
                        await _writer.StoreAsync();
                    }
                    else
                    {
                        _writer.WriteByte(0xC6); // Not Acceptable
                        _writer.WriteUInt16(3);
                        await _writer.StoreAsync();
                    }
                }
            }, _cts.Token);
        }
예제 #6
0
        /// <summary>
        /// Retrieves an phone book object from the object exchange server.
        /// </summary>
        /// <param name="phoneBookObjectPath">
        /// Absolute path in the virtual folders architecture of the PSE,
        /// appended with the name of the file representation of one of the Phone Book Objects.
        /// Example: telecom/pb.vcf or SIM1/telecom/pb.vcf for the main phone book objects
        /// </param>
        /// <returns>phone book object string</returns>
        public async Task <string> PullPhoneBook(string phoneBookObjectPath)
        {
            ObexPacket request = new ObexPacket(Opcode.GetAlter);

            request.Headers[HeaderId.Name] = new UnicodeStringValueHeader(HeaderId.Name, phoneBookObjectPath);
            request.Headers[HeaderId.Type] = new AsciiStringValueHeader(HeaderId.Type, "x-bt/phonebook");
            request.Headers[HeaderId.ApplicationParameters] = new AppParamHeader();

            ObexPacket response = await RunObexRequest(request);

            Console.WriteLine(((BodyHeader)response.Headers[HeaderId.Body]).Value);
            return(((BodyHeader)response.Headers[HeaderId.Body]).Value !);
        }
예제 #7
0
        public async Task SetNotificationRegistration(bool enableNotification)
        {
            byte flag = (byte)(enableNotification ? 1 : 0);

            ObexPacket packet = new ObexPacket(
                Opcode.PutAlter
                , new AsciiStringValueHeader(HeaderId.Type, "x-bt/MAP-NotificationRegistration")
                , new AppParamHeader(new AppParameter(AppParamTagId.NotificationStatus, flag))
                , new BytesHeader(HeaderId.EndOfBody, 0x30)
                );

            Console.WriteLine("Sending RemoteNotificationRegister request");
            await RunObexRequest(packet);
        }
예제 #8
0
        public async Task PushMessage()
        {
            ObexPacket packet = new ObexPacket(
                Opcode.PutAlter
                , new AsciiStringValueHeader(HeaderId.Type, "x-bt/message")
                , new AsciiStringValueHeader(HeaderId.Name, "telecom/msg/inbox")
                //, new StringValueHeader(HeaderId.Name, "telecom/msg/inbox")
                //, new BytesHeader(HeaderId.SingleResponseMode, 0x01)
                , new AppParamHeader(new AppParameter(AppParamTagId.Charset, MasConstants.CHARSET_UTF8))
                , new AsciiStringValueHeader(HeaderId.EndOfBody, "test pushing message from MCE")
                );

            Console.WriteLine("sending PushMessage request ");

            await RunObexRequest(packet);
        }
예제 #9
0
        public async Task <BMessage> GetMessage(string messageHandle)
        {
            ObexPacket packet = new ObexPacket(
                Opcode.GetAlter,
                new AsciiStringValueHeader(HeaderId.Type, "x-bt/message"),
                new UnicodeStringValueHeader(HeaderId.Name, messageHandle),
                new AppParamHeader(
                    new AppParameter(AppParamTagId.Attachment, MasConstants.ATTACHMENT_ON),
                    new AppParameter(AppParamTagId.Charset, MasConstants.CHARSET_UTF8)
                    )
                );

            Console.WriteLine("Sending GetMessage request ");

            ObexPacket resp = await RunObexRequest(packet);

            // "EndOfBody" has been copied to "Body" by ObexClient
            string bMsgStr = ((BodyHeader)resp.Headers[HeaderId.Body]).Value !;

            BMessage bMsg;

            try
            {
                BMessageNode bMsgNode = BMessageNode.Parse(bMsgStr);
                bMsg = new BMessage(
                    status: bMsgNode.Attributes["STATUS"] == "UNREAD" ? MessageStatus.UNREAD : MessageStatus.READ,
                    type: bMsgNode.Attributes["TYPE"],
                    folder: bMsgNode.Attributes["FOLDER"],
                    charset: bMsgNode.ChildrenNode["BENV"].ChildrenNode["BBODY"].Attributes["CHARSET"],
                    length: int.Parse(bMsgNode.ChildrenNode["BENV"].ChildrenNode["BBODY"].Attributes["LENGTH"]),
                    body: bMsgNode.ChildrenNode["BENV"].ChildrenNode["BBODY"].ChildrenNode["MSG"].Value !,
                    sender: MixERP.Net.VCards.Deserializer.GetVCard(bMsgNode.ChildrenNode["VCARD"].ToString())
                    );
            }
            catch (BMessageException ex)
            {
                throw new ObexRequestException($"Failed to get message (handle: {messageHandle}) from MSE. The MSE send back a invalid response", ex);
            }

            return(bMsg);
        }
예제 #10
0
        /// <summary>
        /// Read and parse OBEX packet from DataReader
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="packet">Optional, if this parameter is not null, the data will be read into this parameter</param>
        /// <returns>Loaded OBEX packet</returns>
        public async static Task <ObexPacket> ReadFromStream(DataReader reader, ObexPacket?packet = null)
        {
            uint loaded = await reader.LoadAsync(1);

            if (loaded != 1)
            {
                throw new ObexRequestException("The underlying socket was closed before we were able to read the whole data.");
            }

            Opcode opcode = (Opcode)reader.ReadByte();

            if (packet == null)
            {
                packet = new ObexPacket(opcode);
            }
            else
            {
                packet.Opcode = opcode;
            }
            Console.WriteLine($"ReadFromStream:: Opcode: {packet.Opcode}");

            loaded = await reader.LoadAsync(sizeof(ushort));

            if (loaded != sizeof(ushort))
            {
                throw new ObexRequestException("The underlying socket was closed before we were able to read the whole data.");
            }

            packet.PacketLength = reader.ReadUInt16();
            Console.WriteLine($"packet length: {packet.PacketLength}");

            uint extraFieldBits = await packet.ReadExtraField(reader);

            uint size = packet.PacketLength - (uint)sizeof(Opcode) - sizeof(ushort) - extraFieldBits;
            await packet.ParseHeader(reader, size);

            return(packet);
        }
예제 #11
0
        /// <summary>
        /// Send OBEX Connect packet to the server.
        /// </summary>
        /// <param name="targetUuid">A 16-length byte array indicates the UUID of the target service.</param>
        /// <exception cref="InvalidOperationException">The Connect method can call only once and it is already called before.</exception>
        /// <exception cref="ObexRequestException">The request failed due to an underlying issue such as connection issue, or the server reply with a invalid response</exception>
        public async Task Connect(ObexServiceUuid targetService)
        {
            if (Conntected)
            {
                throw new InvalidOperationException("ObexClient is already connected to a ObexServer");
            }

            ObexConnectPacket packet = new ObexConnectPacket(targetService);
            var buf = packet.ToBuffer();

            Console.WriteLine("Sending OBEX Connection request to server:");
            Console.WriteLine(BitConverter.ToString(buf.ToArray()));
            Console.WriteLine("Opcode: " + packet.Opcode);

            _writer.WriteBuffer(buf);
            await _writer.StoreAsync();

            Console.WriteLine("Waiting reply packet...");
            ObexPacket response = await ObexPacket.ReadFromStream(_reader, packet);

            var bytes = response.ToBuffer().ToArray();

            Console.WriteLine("Reply packet:");
            Console.WriteLine(BitConverter.ToString(bytes));
            Console.WriteLine($"ResponseCode: {response.Opcode}");
            response.PrintHeaders();

            if (response.Opcode != Opcode.Success && response.Opcode != Opcode.SuccessAlt)
            {
                throw new ObexRequestException($"Unable to connect to the target OBEX service.", response.Opcode);
            }

            if (response.Headers.ContainsKey(HeaderId.ConnectionId))
            {
                _connectionIdHeader = (Int32ValueHeader)response.Headers[HeaderId.ConnectionId];
            }
            Conntected = true;
        }
예제 #12
0
        /// <summary>
        /// Send OBEX request to MSE
        /// </summary>
        /// <param name="req">The request packet</param>
        /// <returns>Response packet. The resposne packet is null if the MSE did not send back any response, or the response is corrupted</returns>
        /// <exception cref="ObexRequestException"> due to an underlying issue such as connection loss, invalid server response</exception>
        public async Task <ObexPacket> RunObexRequest(ObexPacket req)
        {
            if (!Conntected)
            {
                throw new InvalidOperationException("ObexClient is not connected to any ObexServer");
            }

            Opcode     requestOpcode = req.Opcode;
            ObexPacket?response      = null;
            int        c             = 0;

            do
            {
                Console.WriteLine($"Sending request packet: {++c}");
                if (_connectionIdHeader != null)
                {
                    req.Headers[HeaderId.ConnectionId] = _connectionIdHeader;
                }
                var buf = req.ToBuffer();
                Console.WriteLine(BitConverter.ToString(buf.ToArray()));
                Console.WriteLine("Opcode: " + req.Opcode);
                _writer.WriteBuffer(buf);
                await _writer.StoreAsync();

                ObexPacket subResponse;
                subResponse = await ObexPacket.ReadFromStream(_reader);

                var bytes = subResponse.ToBuffer().ToArray();
                Console.WriteLine("Reply packet:");
                Console.WriteLine(BitConverter.ToString(bytes));
                Console.WriteLine($"ResponseCode: {subResponse.Opcode}");

                subResponse.PrintHeaders();
                if (response == null)
                {
                    response = subResponse;
                }

                switch (subResponse.Opcode)
                {
                case Opcode.Success:
                case Opcode.SuccessAlt:
                    if (subResponse.Headers.ContainsKey(HeaderId.EndOfBody))
                    {
                        if (response.Headers.ContainsKey(HeaderId.Body))
                        {
                            ((BodyHeader)response.Headers[HeaderId.Body]).Value += ((BodyHeader)subResponse.Headers[HeaderId.EndOfBody]).Value;
                        }
                        else
                        {
                            response.Headers[HeaderId.Body] = response.Headers[HeaderId.EndOfBody];
                        }
                    }
                    return(response);

                case Opcode.Continue:
                case Opcode.ContinueAlt:
                    if (response != subResponse)
                    {
                        if (response.Headers.ContainsKey(HeaderId.Body))
                        {
                            ((BodyHeader)response.Headers[HeaderId.Body]).Value += ((BodyHeader)subResponse.Headers[HeaderId.Body]).Value;
                        }
                        else
                        {
                            if (subResponse.Headers.ContainsKey(HeaderId.Body))
                            {
                                response.Headers[HeaderId.Body] = subResponse.Headers[HeaderId.Body];
                            }
                        }
                    }
                    break;

                default:
                    throw new ObexRequestException($"The {requestOpcode} request failed with opcode {subResponse.Opcode}");
                }

                req = new ObexPacket(requestOpcode, _connectionIdHeader !);
            } while (true);

            Console.WriteLine("Maultiple GET over 10 times, abort!");
            return(response);
        }
예제 #13
0
 /// <summary>
 /// Handle client request.
 /// </summary>
 /// <remarks>
 /// This method will be called whenever a client request arrived.
 /// </remarks>
 /// <param name="clientRequestPacket"></param>
 /// <returns>
 /// The OBEX response packet. If the server doesn't know how to handle this client request, return null.
 /// </returns>
 protected virtual ObexPacket?OnClientRequest(ObexPacket clientRequestPacket)
 {
     return(null);
 }