예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }