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); }
/// <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); }
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); }
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); }
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); }
/// <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 !); }
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); }
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); }
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); }
/// <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); }
/// <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; }
/// <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); }
/// <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); }