public virtual void HandleMethodCall(MessageContainer method_call) { MethodInfo mi; if (!methodInfoCache.TryGetValue(method_call.Member, out mi)) { methodInfoCache[method_call.Member] = mi = Mapper.GetMethod(Object.GetType(), method_call); } if (mi == null) { conn.MaybeSendUnknownMethodError(method_call); return; } MethodCaller mCaller; if (!mCallers.TryGetValue(mi, out mCaller)) { mCaller = TypeImplementer.GenCaller(mi); mCallers[mi] = mCaller; } Signature inSig, outSig; bool hasDisposableList; TypeImplementer.SigsForMethod(mi, out inSig, out outSig, out hasDisposableList); Message msg = method_call.Message; MessageReader msgReader = new MessageReader(msg); MessageWriter retWriter = new MessageWriter(); using (var disposableList = new DisposableList()) { Exception raisedException = null; try { mCaller(Object, msgReader, msg, retWriter, disposableList); } catch (Exception e) { raisedException = e; } if (!msg.ReplyExpected) { return; } Message replyMsg; if (raisedException == null) { MessageContainer method_return = new MessageContainer { Type = MessageType.MethodReturn, ReplySerial = msg.Header.Serial }; replyMsg = method_return.Message; replyMsg.AttachBodyTo(retWriter); replyMsg.Signature = outSig; } else { // BusException allows precisely formatted Error messages. BusException busException = raisedException as BusException; if (busException != null) { replyMsg = method_call.CreateError(busException.ErrorName, busException.ErrorMessage); } else if (raisedException is ArgumentException && raisedException.TargetSite.Name == mi.Name) { // Name match trick above is a hack since we don't have the resolved MethodInfo. ArgumentException argException = (ArgumentException)raisedException; using (System.IO.StringReader sr = new System.IO.StringReader(argException.Message)) { replyMsg = method_call.CreateError("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine()); } } else { replyMsg = method_call.CreateError(Mapper.GetInterfaceName(raisedException.GetType()), raisedException.Message); } } if (method_call.Sender != null) { replyMsg.Header[FieldCode.Destination] = method_call.Sender; } conn.Send(replyMsg); } }
public MessageReader SendMethodCall(string iface, string member, string inSigStr, MessageWriter writer, Type retType, DisposableList disposableList, out Exception exception) { if (string.IsNullOrEmpty(bus_name)) { throw new ArgumentNullException("bus_name"); } if (object_path == null) { throw new ArgumentNullException("object_path"); } exception = null; Signature inSig = String.IsNullOrEmpty(inSigStr) ? Signature.Empty : new Signature(inSigStr); MessageContainer method_call = new MessageContainer { Path = object_path, Interface = iface, Member = member, Destination = bus_name, Signature = inSig }; Message callMsg = method_call.Message; callMsg.AttachBodyTo(writer); bool needsReply = true; callMsg.ReplyExpected = needsReply; callMsg.Signature = inSig; if (!needsReply) { conn.Send(callMsg); return(null); } #if PROTO_REPLY_SIGNATURE if (needsReply) { Signature outSig = Signature.GetSig(retType); callMsg.Header[FieldCode.ReplySignature] = outSig; } #endif Message retMsg = conn.SendWithReplyAndBlock(callMsg, disposableList != null); if (disposableList != null && retMsg.UnixFDArray != null) { foreach (var fd in retMsg.UnixFDArray.FDs) { disposableList.Add(fd); } } MessageReader retVal = null; //handle the reply message switch (retMsg.Header.MessageType) { case MessageType.MethodReturn: retVal = new MessageReader(retMsg); break; case MessageType.Error: MessageContainer error = MessageContainer.FromMessage(retMsg); string errMsg = String.Empty; if (retMsg.Signature.Value.StartsWith("s")) { MessageReader reader = new MessageReader(retMsg); errMsg = reader.ReadString(); } exception = new Exception(error.ErrorName + ": " + errMsg); break; default: throw new Exception("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error"); } return(retVal); }
public void Invoke(MethodBase methodBase, string methodName, object[] inArgs, DisposableList disposableList, out object[] outArgs, out object retVal, out Exception exception) { outArgs = new object[0]; retVal = null; exception = null; MethodInfo mi = methodBase as MethodInfo; if (mi != null && mi.IsSpecialName && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) { string[] parts = methodName.Split(new char[] { '_' }, 2); string ename = parts[1]; Delegate dlg = (Delegate)inArgs[0]; ToggleSignal(Mapper.GetInterfaceName(mi), ename, dlg, parts[0] == "add"); return; } Type[] inTypes = Mapper.GetTypes(ArgDirection.In, mi.GetParameters()); Signature inSig = Signature.GetSig(inTypes); string iface = null; if (mi != null) { iface = Mapper.GetInterfaceName(mi); } if (mi != null && mi.IsSpecialName) { methodName = methodName.Replace("get_", "Get"); methodName = methodName.Replace("set_", "Set"); } MessageWriter writer = new MessageWriter(conn); if (inArgs != null && inArgs.Length != 0) { for (int i = 0; i != inTypes.Length; i++) { writer.Write(inTypes[i], inArgs[i]); } } MessageReader reader = SendMethodCall(iface, methodName, inSig.Value, writer, mi.ReturnType, out exception); if (reader == null) { return; } retVal = reader.ReadValue(mi.ReturnType); }
internal void SendSignal(string iface, string member, string inSigStr, MessageWriter writer, Type retType, DisposableList disposableList, out Exception exception) { exception = null; Signature outSig = String.IsNullOrEmpty(inSigStr) ? Signature.Empty : new Signature(inSigStr); MessageContainer signal = new MessageContainer { Type = MessageType.Signal, Path = object_path, Interface = iface, Member = member, Signature = outSig, }; Message signalMsg = signal.Message; signalMsg.AttachBodyTo(writer); conn.Send(signalMsg); }