public override void HandleMethodCall(MethodCall method_call)
        {
            //object retVal = obj.GetType ().InvokeMember (method_call.Member, BindingFlags.InvokeMethod, null, obj, new object[0]);
            //IDynamicMetaObjectProvider idyn = obj as IDynamicMetaObjectProvider;

            object retVal = null;

            Exception raisedException = null;
            try {
                object[] args = MessageHelper.GetDynamicValues (method_call.message);
                retVal = ops.InvokeMember (obj, method_call.Member, args);
                //retVal = ops.Call (ops.GetMember (obj, method_call.Member), args);
            } catch (Exception e) {
                raisedException = e;
            }

            if (!method_call.message.ReplyExpected)
                return;

            Message msg = method_call.message;
            Message replyMsg = null;

            if (raisedException == null) {
                MethodReturn method_return = new MethodReturn (msg.Header.Serial);
                replyMsg = method_return.message;
                if (retVal != null) {
                    if (retVal.GetType ().FullName == "IronRuby.Builtins.MutableString")
                        retVal = retVal.ToString ();
                    // TODO: Invalid sig handling
                    Signature outSig = Signature.GetSig (retVal.GetType ());
                    MessageWriter retWriter = new MessageWriter ();
                    retWriter.Write (retVal.GetType (), retVal);
                    //retWriter.WriteValueType (retVal, retVal.GetType ());
                    replyMsg.Body = retWriter.ToArray ();
                    replyMsg.Signature = outSig;
                }
            } else {
                Error error = method_call.CreateError (Mapper.GetInterfaceName (raisedException.GetType ()), raisedException.Message);
                replyMsg = error.message;
            }

            if (method_call.Sender != null)
                replyMsg.Header[FieldCode.Destination] = method_call.Sender;

            conn.Send (replyMsg);
        }
Beispiel #2
0
        public object SendMethodCallOld(string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception)
        {
            exception = null;

            //TODO: don't ignore retVal, exception etc.

            Signature inSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr);

            MethodCall method_call = new MethodCall (object_path, iface, member, bus_name, inSig);

            Message callMsg = method_call.message;
            callMsg.Body = writer.ToArray ();

            //Invoke Code::

            //TODO: complete out parameter support
            /*
            Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ());
            Signature outParmSig = Signature.GetSig (outParmTypes);

            if (outParmSig != Signature.Empty)
                throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'");
            */

            Type[] outTypes = new Type[1];
            outTypes[0] = retType;

            //we default to always requiring replies for now, even though unnecessary
            //this is to make sure errors are handled synchronously
            //TODO: don't hard code this
            bool needsReply = true;

            //if (mi.ReturnType == typeof (void))
            //	needsReply = false;

            callMsg.ReplyExpected = needsReply;
            callMsg.Signature = inSig;

            if (!needsReply) {
                conn.Send (callMsg);
                return null;
            }

            #if PROTO_REPLY_SIGNATURE
            if (needsReply) {
                Signature outSig = Signature.GetSig (outTypes);
                callMsg.Header[FieldCode.ReplySignature] = outSig;
            }
            #endif

            Message retMsg = conn.SendWithReplyAndBlock (callMsg);

            object retVal = null;

            //handle the reply message
            switch (retMsg.Header.MessageType) {
                case MessageType.MethodReturn:
                object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes);
                if (retVals.Length != 0)
                    retVal = retVals[retVals.Length - 1];
                break;
                case MessageType.Error:
                //TODO: typed exceptions
                Error error = new Error (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;
        }
Beispiel #3
0
        public void Invoke(MethodBase methodBase, string methodName, object[] inArgs, 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);

            MethodCall method_call;
            Message callMsg;

            //build the outbound method call message
            {
                //this bit is error-prone (no null checking) and will need rewriting when DProxy is replaced
                string iface = null;
                if (mi != null)
                    iface = Mapper.GetInterfaceName (mi);

                //map property accessors
                //TODO: this needs to be done properly, not with simple String.Replace
                //note that IsSpecialName is also for event accessors, but we already handled those and returned
                if (mi != null && mi.IsSpecialName) {
                    methodName = methodName.Replace ("get_", "Get");
                    methodName = methodName.Replace ("set_", "Set");
                }

                method_call = new MethodCall (object_path, iface, methodName, bus_name, inSig);

                callMsg = method_call.message;

                if (inArgs != null && inArgs.Length != 0) {
                    MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
                    writer.connection = conn;

                    for (int i = 0 ; i != inTypes.Length ; i++)
                        writer.Write (inTypes[i], inArgs[i]);

                    callMsg.Body = writer.ToArray ();
                }
            }

            //TODO: complete out parameter support
            /*
            Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ());
            Signature outParmSig = Signature.GetSig (outParmTypes);

            if (outParmSig != Signature.Empty)
                throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'");
            */

            Type[] outTypes = new Type[1];
            outTypes[0] = mi.ReturnType;

            //we default to always requiring replies for now, even though unnecessary
            //this is to make sure errors are handled synchronously
            //TODO: don't hard code this
            bool needsReply = true;

            //if (mi.ReturnType == typeof (void))
            //	needsReply = false;

            callMsg.ReplyExpected = needsReply;
            callMsg.Signature = inSig;

            if (!needsReply) {
                conn.Send (callMsg);
                return;
            }

            #if PROTO_REPLY_SIGNATURE
            if (needsReply) {
                Signature outSig = Signature.GetSig (outTypes);
                callMsg.Header[FieldCode.ReplySignature] = outSig;
            }
            #endif

            Message retMsg = conn.SendWithReplyAndBlock (callMsg);

            //handle the reply message
            switch (retMsg.Header.MessageType) {
                case MessageType.MethodReturn:
                object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes);
                if (retVals.Length != 0)
                    retVal = retVals[retVals.Length - 1];
                break;
                case MessageType.Error:
                //TODO: typed exceptions
                Error error = new Error (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;
        }
Beispiel #4
0
        public static Message CreateUnknownMethodError(MethodCall method_call)
        {
            if (!method_call.message.ReplyExpected)
                return null;

            string errMsg = String.Format ("Method \"{0}\" with signature \"{1}\" on interface \"{2}\" doesn't exist", method_call.Member, method_call.Signature.Value, method_call.Interface);

            Error error = new Error ("org.freedesktop.DBus.Error.UnknownMethod", method_call.message.Header.Serial);
            error.message.Signature = Signature.StringSig;

            MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
            writer.Write (errMsg);
            error.message.Body = writer.ToArray ();

            //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
            if (method_call.Sender != null)
                error.message.Header[FieldCode.Destination] = method_call.Sender;

            return error.message;
        }
Beispiel #5
0
        public static Message ConstructReply(MethodCall method_call, params object[] vals)
        {
            MethodReturn method_return = new MethodReturn (method_call.message.Header.Serial);
            Message replyMsg = method_return.message;

            Signature inSig = Signature.GetSig (vals);

            if (vals != null && vals.Length != 0) {
                MessageWriter writer = new MessageWriter (Connection.NativeEndianness);

                foreach (object arg in vals)
                    writer.Write (arg.GetType (), arg);

                replyMsg.Body = writer.ToArray ();
            }

            //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
            if (method_call.Sender != null)
                replyMsg.Header[FieldCode.Destination] = method_call.Sender;

            replyMsg.Signature = inSig;

            //replyMsg.WriteHeader ();

            return replyMsg;
        }
Beispiel #6
0
        public static Message ConstructDynamicReply(MethodCall method_call, MethodInfo mi, object retVal, object[] vals)
        {
            Type retType = mi.ReturnType;

            MethodReturn method_return = new MethodReturn (method_call.message.Header.Serial);
            Message replyMsg = method_return.message;

            Signature outSig = Signature.GetSig (retType);
            outSig += Signature.GetSig (Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ()));

            if (outSig != Signature.Empty) {
                MessageWriter writer = new MessageWriter (Connection.NativeEndianness);

                //first write the return value, if any
                if (retType != null && retType != typeof (void))
                    writer.Write (retType, retVal);

                //then write the out args
                WriteDynamicValues (writer, mi.GetParameters (), vals);

                replyMsg.Body = writer.ToArray ();
            }

            //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
            if (method_call.Sender != null)
                replyMsg.Header[FieldCode.Destination] = method_call.Sender;

            replyMsg.Signature = outSig;

            return replyMsg;
        }
Beispiel #7
0
        //this method walks the interface tree in an undefined manner and returns the first match, or if no matches are found, null
        //the logic needs review and cleanup
        //TODO: unify member name mapping as is already done with interfaces and args
        public static MethodInfo GetMethod(Type type, MethodCall method_call)
        {
            foreach (MemberInfo member in Mapper.GetPublicMembers (type)) {
                //this could be made more efficient by using the given interface name earlier and avoiding walking through all public interfaces
                if (method_call.Interface != null)
                    if (GetInterfaceName (member) != method_call.Interface)
                        continue;

                MethodInfo meth = null;
                Type[] inTypes = null;

                if (member is PropertyInfo) {
                    PropertyInfo prop = member as PropertyInfo;

                    MethodInfo getter = prop.GetGetMethod (false);
                    MethodInfo setter = prop.GetSetMethod (false);

                    if (getter != null && "Get" + prop.Name == method_call.Member) {
                        meth = getter;
                        inTypes = Type.EmptyTypes;
                    } else if (setter != null && "Set" + prop.Name == method_call.Member) {
                        meth = setter;
                        inTypes = new Type[] {prop.PropertyType};
                    }
                } else {
                    meth = member as MethodInfo;

                    if (meth == null)
                        continue;

                    if (meth.Name != method_call.Member)
                        continue;

                    inTypes = Mapper.GetTypes (ArgDirection.In, meth.GetParameters ());
                }

                if (meth == null || inTypes == null)
                    continue;

                Signature inSig = Signature.GetSig (inTypes);

                if (inSig != method_call.Signature)
                    continue;

                return meth;
            }

            return null;
        }