Exemple #1
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;
        }
Exemple #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;
        }
Exemple #3
0
        public MessageReader SendMethodCall(string iface, string member, string inSigStr, MessageWriter writer, Type retType, 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);

            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;
        }
Exemple #4
0
        internal virtual void HandleMessage(Message msg)
        {
            if (msg == null)
            {
                return;
            }

            //TODO: support disconnection situations properly and move this check elsewhere
            if (msg == null)
            {
                throw new ArgumentNullException("msg", "Cannot handle a null message; maybe the bus was disconnected");
            }

            bool cleanupFDs = true;

            try {
                //TODO: Restrict messages to Local ObjectPath?

                {
                    object field_value = msg.Header[FieldCode.ReplySerial];
                    if (field_value != null)
                    {
                        uint        reply_serial = (uint)field_value;
                        PendingCall pending;

                        lock (pendingCalls) {
                            if (pendingCalls.TryGetValue(reply_serial, out pending))
                            {
                                if (pendingCalls.Remove(reply_serial))
                                {
                                    pending.Reply = msg;
                                    if (pending.KeepFDs)
                                    {
                                        cleanupFDs = false;                                         // caller is responsible for closing FDs
                                    }
                                }

                                return;
                            }
                        }

                        //we discard reply messages with no corresponding PendingCall
                        if (ProtocolInformation.Verbose)
                        {
                            Console.Error.WriteLine("Unexpected reply message received: MessageType='" + msg.Header.MessageType + "', ReplySerial=" + reply_serial);
                        }

                        return;
                    }
                }

                switch (msg.Header.MessageType)
                {
                case MessageType.MethodCall:
                    MessageContainer method_call = MessageContainer.FromMessage(msg);
                    HandleMethodCall(method_call);
                    break;

                case MessageType.Signal:
                    //HandleSignal (msg);
                    lock (inbound)
                        inbound.Enqueue(msg);
                    cleanupFDs = false;                             // FDs are closed after signal is handled
                    break;

                case MessageType.Error:
                    //TODO: better exception handling
                    MessageContainer error  = MessageContainer.FromMessage(msg);
                    string           errMsg = String.Empty;
                    if (msg.Signature.Value.StartsWith("s"))
                    {
                        MessageReader reader = new MessageReader(msg);
                        errMsg = reader.ReadString();
                    }
                    Console.Error.WriteLine("Remote Error: Signature='" + msg.Signature.Value + "' " + error.ErrorName + ": " + errMsg);
                    break;

                case MessageType.Invalid:
                default:
                    throw new Exception("Invalid message received: MessageType='" + msg.Header.MessageType + "'");
                }
            } finally {
                if (cleanupFDs)
                {
                    msg.Dispose();
                }
            }
        }
Exemple #5
0
        public MessageReader SendMethodCall(string iface, string member, string inSigStr, MessageWriter writer, Type retType, 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);

            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);
        }
Exemple #6
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;
        }
Exemple #7
0
        public MessageReader SendMethodCall(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);

            MessageReader retVal = null;

            //handle the reply message
            switch (retMsg.Header.MessageType)
            {
            case MessageType.MethodReturn:
                if ((string)retMsg.Header[FieldCode.Sender] != bus_name)
                {
                    alt_bus_name = (string)retMsg.Header[FieldCode.Sender];
                }
                retVal = new MessageReader(retMsg);
                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);
        }