Esempio n. 1
0
		//TODO: make use of Locked
		/*
		protected bool locked = false;
		public bool Locked
		{
			get {
				return locked;
			}
		}
		*/

		public void SetHeaderData (byte[] data)
		{
			EndianFlag endianness = (EndianFlag)data[0];
			MessageReader reader = new MessageReader (endianness, data);

			Header = (Header)reader.ReadStruct (typeof (Header));
		}
Esempio n. 2
0
		public void ParseHeader ()
		{
			//GetValue (stream, typeof (Header), out Header);

			EndianFlag endianness = (EndianFlag)HeaderData[0];
			MessageReader reader = new MessageReader (endianness, HeaderData);

			object valT;
			reader.GetValueStruct (typeof (Header), out valT);
			Header = (Header)valT;

			/*
			//foreach (HeaderField field in HeaderFields)
			foreach (KeyValuePair<FieldCode,object> field in Header.Fields)
			{
				//Console.WriteLine (field.Key + " = " + field.Value);
				switch (field.Key)
				{
					case FieldCode.Invalid:
						break;
					case FieldCode.Path:
						Path = (ObjectPath)field.Value;
						break;
					case FieldCode.Interface:
						Interface = (string)field.Value;
						break;
					case FieldCode.Member:
						Member = (string)field.Value;
						break;
					case FieldCode.ErrorName:
						ErrorName = (string)field.Value;
						break;
					case FieldCode.ReplySerial:
						ReplySerial = (uint)field.Value;
						break;
					case FieldCode.Destination:
						Destination = (string)field.Value;
						break;
					case FieldCode.Sender:
						Sender = (string)field.Value;
						break;
					case FieldCode.Signature:
						Signature = (Signature)field.Value;
						break;
				}
			}
			*/
		}
        public virtual void HandleMethodCall(MethodCall method_call)
        {
            Type type = obj.GetType ();

            //object retObj = type.InvokeMember (msg.Member, BindingFlags.InvokeMethod, null, obj, MessageHelper.GetDynamicValues (msg));

            //TODO: there is no member name mapping for properties etc. yet

            // FIXME: Inefficient to do this on every call
            MethodInfo mi = Mapper.GetMethod (type, method_call);

            if (mi == null) {
                conn.MaybeSendUnknownMethodError (method_call);
                return;
            }

            MethodCaller2 mCaller;
            if (!mCallers.TryGetValue (mi, out mCaller)) {
                //mCaller = TypeImplementer.GenCaller (mi, obj);
                mCaller = TypeImplementer.GenCaller2 (mi);
                mCallers[mi] = mCaller;
            }

            Signature inSig, outSig;
            TypeImplementer.SigsForMethod (mi, out inSig, out outSig);

            Message msg = method_call.message;
            MessageReader msgReader = new MessageReader (method_call.message);
            MessageWriter retWriter = new MessageWriter ();

            /*
            MessageWriter retWriter = null;
            if (msg.ReplyExpected)
                retWriter = new MessageWriter ();
            */

            Exception raisedException = null;
            try {
                //mCaller (msgReader, method_call.message, retWriter);
                mCaller (obj, msgReader, method_call.message, retWriter);
            } catch (Exception e) {
                raisedException = e;
            }

            if (!msg.ReplyExpected)
                return;

            Message replyMsg;

            if (raisedException == null) {
                MethodReturn method_return = new MethodReturn (msg.Header.Serial);
                replyMsg = method_return.message;
                replyMsg.Body = retWriter.ToArray ();
                replyMsg.Signature = outSig;
            } else {
                Error error;
                // BusException allows precisely formatted Error messages.
                BusException busException = raisedException as BusException;
                if (busException != null)
                    error = 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)) {
                        error = method_call.CreateError ("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine ());
                    }
                } else
                    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);
        }
Esempio n. 4
0
		public static object[] GetDynamicValues (Message msg, Type[] types)
		{
			//TODO: this validation check should provide better information, eg. message dump or a stack trace, or at least the interface/member
			if (Protocol.Verbose) {
				Signature expected = Signature.GetSig (types);
				Signature actual = msg.Signature;
				if (actual != expected)
					Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler: " + "Expected '" + expected + "', got '" + actual + "'");
			}

			object[] vals = new object[types.Length];

			if (msg.Body != null) {
				MessageReader reader = new MessageReader (msg);

				for (int i = 0 ; i != types.Length ; i++)
					vals[i] = reader.ReadValue (types[i]);
			}

			return vals;
		}
Esempio n. 5
0
		public static object[] GetDynamicValues (Message msg, ParameterInfo[] parms)
		{
			//TODO: this validation check should provide better information, eg. message dump or a stack trace, or at least the interface/member
			/*
			if (Protocol.Verbose) {
				Signature expected = Signature.GetSig (types);
				Signature actual = msg.Signature;
				if (actual != expected)
					Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler: " + "Expected '" + expected + "', got '" + actual + "'");
			}
			*/

			object[] vals = new object[parms.Length];

			if (msg.Body != null) {
				MessageReader reader = new MessageReader (msg);
				foreach (ParameterInfo parm in parms) {
					if (parm.IsOut)
						continue;

					vals[parm.Position] = reader.ReadValue (parm.ParameterType);
				}
			}

			return vals;
		}
Esempio n. 6
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;
		}
Esempio n. 7
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;
		}
Esempio n. 8
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;
		}
Esempio n. 9
0
		public static object[] GetDynamicValues (Message msg, Type[] types)
		{
			//TODO: this validation check should provide better information, eg. message dump or a stack trace
			if (Protocol.Verbose) {
				if (Signature.GetSig (types) != msg.Signature)
					Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler");
			}

			object[] vals = new object[types.Length];

			if (msg.Body != null) {
				MessageReader reader = new MessageReader (msg);

				for (int i = 0 ; i != types.Length ; i++) {
					object arg;
					reader.GetValue (types[i], out arg);
					vals[i] = arg;
				}
			}

			return vals;
		}
        public static void Test(HashSet<ArgMatchTest> a, Message msg)
        {
            List<Signature> sigs = new List<Signature> ();
            sigs.AddRange (msg.Signature.GetParts ());

            if (sigs.Count == 0) {
                a.Clear ();
                return;
            }

            a.RemoveWhere ( delegate (ArgMatchTest t) { return t.ArgNum >= sigs.Count || t.Signature != sigs[t.ArgNum]; } );

            // Sorting the list here is not ideal
            List<ArgMatchTest> tests = new List<ArgMatchTest> (a);
            tests.Sort ( delegate (ArgMatchTest aa, ArgMatchTest bb) { return aa.ArgNum - bb.ArgNum; } );

            if (tests.Count == 0) {
                a.Clear ();
                return;
            }

            MessageReader reader = new MessageReader (msg);

            int argNum = 0;
            foreach (ArgMatchTest test in tests) {
                if (argNum > test.ArgNum) {
                    // This test cannot pass because a previous test already did.
                    // So we already know it will fail without even trying.
                    // This logic will need to be changed to support wildcards.
                    a.Remove (test);
                    continue;
                }

                while (argNum != test.ArgNum) {
                    Signature sig = sigs[argNum];
                    if (!reader.StepOver (sig))
                        throw new Exception ();
                    argNum++;
                }

                // TODO: Avoid re-reading values
                int savedPos = reader.pos;
                if (!reader.ReadValue (test.Signature[0]).Equals (test.Value)) {
                    a.Remove (test);
                    reader.pos = savedPos;
                    continue;
                }

                argNum++;
            }
        }
Esempio n. 11
0
        public void SetHeaderData(byte[] data)
        {
            EndianFlag endianness = (EndianFlag)data[0];
            MessageReader reader = new MessageReader (endianness, data);

            MethodCaller2 mCaller = ExportObject.GetMCaller (hHandler);
            mCaller (this, reader, null, new MessageWriter ());
        }
Esempio n. 12
0
        public object ToType(Type conversionType, IFormatProvider provider)
        {
            Signature typeSig = Signature.GetSig (conversionType);
            if (typeSig != signature)
                throw new InvalidCastException ();

            MessageReader reader = new MessageReader (endianness, data);
            return reader.ReadValue (conversionType);
        }