Пример #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.Fields[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;
        }
Пример #2
0
        public object 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.Fields[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);
        }
Пример #3
0
        public 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");
            }

            //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;

                    if (pendingCalls.TryGetValue(reply_serial, out pending))
                    {
                        if (pendingCalls.Remove(reply_serial))
                        {
                            pending.Reply = msg;
                        }

                        return;
                    }

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

                    return;
                }
            }

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

            case MessageType.Signal:
                //HandleSignal (msg);
                lock (Inbound)
                    Inbound.Enqueue(msg);
                break;

            case MessageType.Error:
                //TODO: better exception handling
                Error  error  = new Error(msg);
                string errMsg = String.Empty;
                if (msg.Signature.Value.StartsWith("s"))
                {
                    MessageReader reader = new MessageReader(msg);
                    errMsg = reader.ReadString();
                }
                //throw new Exception ("Remote Error: Signature='" + msg.Signature.Value + "' " + error.ErrorName + ": " + errMsg);
                //if (Protocol.Verbose)
                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 + "'");
            }
        }
Пример #4
0
		public object 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.Fields[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;
		}
Пример #5
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.Fields[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;
		}
Пример #6
0
		private void FetchUiaDbusNames ()
		{
			var busNames = new List<string> ();

			IBus ibus = Bus.Session.GetObject<IBus> (DBusName,
			                                         new ObjectPath (DBusPath));
			// Look for buses that contain DCI.IApplication
			foreach (string busName in ibus.ListNames ()) {
				// Reading introspection data hangs on some buses
				// for unknown reasons, so we call Introspect
				// asynchronously.  Note that we are using
				// internal dbus-sharp classes.  The old
				// behavior was to spin off threads, but this
				// triggers a Mono bug on Fedora
				// (BNC#628639/632133)
				ObjectPath op = new ObjectPath (DC.Constants.ApplicationPath);
				MethodCall methodCall = new MethodCall (op,
					"org.freedesktop.DBus.Introspectable",
					"Introspect", busName, Signature.Empty);
				PendingCall pendingCall = Bus.Session.SendWithReply (methodCall.message);
				pendingCall.Completed +=  (message) => {
					MessageReader reader = new MessageReader (message);
					string data = reader.ReadString ();
					if (data.Contains (DC.Constants.ApplicationInterfaceName))
						busNames.Add ((string)message.Header [FieldCode.Sender]);
				};
			}
			Thread.Sleep (1000);

			lock (uiaDbusNamesLock)
				uiaDbusNames = busNames;
		}