public Task <MessageTransaction> CallMethodAsync(Message msg, bool checkConnected, bool checkReplyType) { msg.Header.ReplyExpected = true; var serial = GenerateSerial(); msg.Header.Serial = serial; var pending = new PendingMethodCont(msg, MethodCallTimeout); pending.Timer.Interval = Timeout.TotalMilliseconds; var pendingMethods = _pendingMethods; lock (_gate) { if (checkConnected || pendingMethods == null) { ThrowIfNotConnected(); } pendingMethods[msg.Header.Serial] = pending; pending.Transaction.RequestSendTime = DateTime.Now; pending.Timer.Start(); } // Chained (rather than async await) to preserve AsyncState SendMessageAsync(msg) .ContinueWith(r => { if (r.IsFaulted || r.IsCanceled) { pending.DisposeTimer(); pendingMethods = _pendingMethods; lock (_gate) { pendingMethods.Remove(msg.Header.Serial); } pending.Transaction.RequestSendTime = null; if (r.IsFaulted) { var ex = (r.Exception.InnerExceptions.Count == 1) ? r.Exception.InnerExceptions[0] : r.Exception; pending.Reply.SetException(ex); } else { pending.Reply.SetCanceled(); } } }); return(pending.Reply.Task); }
void MethodCallTimeout(PendingMethodCont cont) { var serialValue = cont.Request.Header.Serial; var pendingMethods = _pendingMethods; cont.DisposeTimer(); if (pendingMethods == null) { return; } bool setException; lock (_gate) { setException = pendingMethods.Remove(serialValue); } if (setException) { cont.Reply.TrySetException(new DBusException(DBusErrors.Timeout, "Did not receive a reply in time")); } }
private void HandleMessage(Message msg, IMessageStream peer) { uint?serial = msg.Header.ReplySerial; PendingMethodCont pending = null; var pendingMethods = _pendingMethods; if (pendingMethods == null) { return; // Disposed } var receiveTime = DateTime.Now; if (serial != null) { uint serialValue = serial.Value; lock (_gate) { if (pendingMethods.TryGetValue(serialValue, out pending)) { pending.DisposeTimer(); pendingMethods.Remove(serialValue); } } if (pending != null) { pending.Transaction.ReplyReceivedTime = receiveTime; pending.Transaction.Reply = msg; Exception ex = null; switch (msg.Header.MessageType) { case MessageType.MethodReturn: pending.Reply.TrySetResult(pending.Transaction); break; case MessageType.Error: string errMsg = string.Empty; if (msg.Header.Signature.Value.Value.StartsWith("s", StringComparison.Ordinal)) { errMsg = new MessageReader(msg).ReadString(); } ex = new DBusException(msg.Header.ErrorName, errMsg); break; case MessageType.Invalid: default: ex = new ProtocolException("Invalid message received: MessageType='" + msg.Header.MessageType + "'"); break; } if (ex != null) { pending.Reply.TrySetException(ex); } } else { serial = null; // Drop quietly //throw new ProtocolException("Unexpected reply message received: MessageType = '" + msg.Header.MessageType + "', ReplySerial = " + serialValue); } } var hook = MessageReceivedHook; if (hook != null) { var transaction = (pending != null) ? pending.Transaction : new MessageTransaction { Reply = msg, ReplyReceivedTime = receiveTime }; hook.Invoke(transaction); } if (serial != null) { return; } switch (msg.Header.MessageType) { case MessageType.MethodCall: HandleMethodCall(msg, peer); break; case MessageType.Signal: HandleSignal(msg); break; case MessageType.Error: string errMsg = string.Empty; if (msg.Header.Signature.Value.Value.StartsWith("s", StringComparison.Ordinal)) { errMsg = new MessageReader(msg).ReadString(); } //throw new DBusException(msg.Header.ErrorName, errMsg); break; case MessageType.Invalid: default: //throw new ProtocolException("Invalid message received: MessageType='" + msg.Header.MessageType + "'"); break; } }