Пример #1
0
		public void ToggleSignal (string iface, string member, Delegate dlg, bool adding)
		{
			MatchRule rule = new MatchRule ();
			rule.MessageType = MessageType.Signal;
			rule.Fields.Add (FieldCode.Interface, new MatchTest (iface));
			rule.Fields.Add (FieldCode.Member, new MatchTest (member));
			rule.Fields.Add (FieldCode.Path, new MatchTest (object_path));
			// FIXME: Cause a regression compared to 0.6 as name wasn't matched before
			// the problem arises because busname is not used by DBus daemon and
			// instead it uses the canonical name of the sender (i.e. similar to ':1.13')
			// rule.Fields.Add (FieldCode.Sender, new MatchTest (bus_name));

			if (adding) {
				if (conn.Handlers.ContainsKey (rule))
					conn.Handlers[rule] = Delegate.Combine (conn.Handlers[rule], dlg);
				else {
					conn.Handlers[rule] = dlg;
					conn.AddMatch (rule.ToString ());
				}
			} else if (conn.Handlers.ContainsKey (rule)) {
				conn.Handlers[rule] = Delegate.Remove (conn.Handlers[rule], dlg);
				if (conn.Handlers[rule] == null) {
					conn.RemoveMatch (rule.ToString ());
					conn.Handlers.Remove (rule);
				}
			}
		}
Пример #2
0
        public static MatchRule Parse(string text)
        {
            if (text.Length > Protocol.MaxMatchRuleLength)
                throw new Exception ("Match rule length exceeds maximum " + Protocol.MaxMatchRuleLength + " characters");

            MatchRule r = new MatchRule ();

            // TODO: Stricter validation. Tighten up the regex.
            // It currently succeeds and silently drops malformed test parts.

            for (Match m = matchRuleRegex.Match (text) ; m.Success ; m = m.NextMatch ()) {
                string key = m.Groups[1].Value;
                string value = m.Groups[2].Value;
                // This unescaping may not be perfect..
                value = value.Replace (@"\\", @"\");
                value = value.Replace (@"\'", @"'");

                if (key.StartsWith ("arg")) {
                    Match mArg = argNRegex.Match (key);
                    if (!mArg.Success)
                        return null;
                    int argNum = (int)UInt32.Parse (mArg.Groups[1].Value);

                    if (argNum < 0 || argNum >= Protocol.MaxMatchRuleArgs)
                        throw new Exception ("arg match must be between 0 and " + (Protocol.MaxMatchRuleArgs - 1) + " inclusive");

                    //if (r.Args.ContainsKey (argNum))
                    //	return null;

                    string argType = mArg.Groups[2].Value;

                    if (argType == "path")
                        r.Args.Add (new ArgMatchTest (argNum, new ObjectPath (value)));
                    else
                        r.Args.Add (new ArgMatchTest (argNum, value));

                    continue;
                }

                //TODO: more consistent error handling
                switch (key) {
                    case "type":
                        if (r.MessageType != null)
                            return null;
                        r.MessageType = MessageFilter.StringToMessageType (value);
                        break;
                    case "interface":
                        r.Fields[FieldCode.Interface] = new MatchTest (value);
                        break;
                    case "member":
                        r.Fields[FieldCode.Member] = new MatchTest (value);
                        break;
                    case "path":
                        r.Fields[FieldCode.Path] = new MatchTest (new ObjectPath (value));
                        break;
                    case "sender":
                        r.Fields[FieldCode.Sender] = new MatchTest (value);
                        break;
                    case "destination":
                        r.Fields[FieldCode.Destination] = new MatchTest (value);
                        break;
                    default:
                        if (Protocol.Verbose)
                            Console.Error.WriteLine ("Warning: Unrecognized match rule key: " + key);
                        break;
                }
            }

            return r;
        }
Пример #3
0
        internal void HandleMessage(Message msg)
        {
            if (msg == null)
            {
                return;
            }

            //List<Connection> recipients = new List<Connection> ();
            HashSet <Connection> recipients = new HashSet <Connection> ();
            //HashSet<Connection> recipientsAll = new HashSet<Connection> (Connections);

            object fieldValue = msg.Header[FieldCode.Destination];

            if (fieldValue != null)
            {
                string     destination = (string)fieldValue;
                Connection destConn;
                if (Names.TryGetValue(destination, out destConn))
                {
                    recipients.Add(destConn);
                }
                else if (destination != DBusBusName && !destination.StartsWith(":") && (msg.Header.Flags & HeaderFlag.NoAutoStart) != HeaderFlag.NoAutoStart)
                {
                    // Attempt activation
                    StartProcessNamed(destination);
                    //Thread.Sleep (5000);
                    // TODO: Route the message to the newly activated service!
                    activationMessages[destination] = msg;
                    //if (Names.TryGetValue (destination, out destConn))
                    //	recipients.Add (destConn);
                    //else
                    //	Console.Error.WriteLine ("Couldn't route message to activated service");
                }
                else if (destination != DBusBusName)
                {
                    // Send an error when there's no hope of getting the requested reply
                    if (msg.ReplyExpected)
                    {
                        // Error org.freedesktop.DBus.Error.ServiceUnknown: The name {0} was not provided by any .service files
                        Message rmsg = MessageHelper.CreateUnknownMethodError(new MethodCall(msg));
                        if (rmsg != null)
                        {
                            //Caller.Send (rmsg);
                            Caller.SendReal(rmsg);
                            return;
                        }
                    }
                }
            }

            HashSet <Connection> recipientsMatchingHeader = new HashSet <Connection> ();

            HashSet <ArgMatchTest> a = new HashSet <ArgMatchTest> ();

            foreach (KeyValuePair <MatchRule, List <Connection> > pair in Rules)
            {
                if (recipients.IsSupersetOf(pair.Value))
                {
                    continue;
                }
                if (pair.Key.MatchesHeader(msg))
                {
                    a.UnionWith(pair.Key.Args);
                    recipientsMatchingHeader.UnionWith(pair.Value);
                }
            }

            MatchRule.Test(a, msg);

            foreach (KeyValuePair <MatchRule, List <Connection> > pair in Rules)
            {
                if (recipients.IsSupersetOf(pair.Value))
                {
                    continue;
                }
                if (!recipientsMatchingHeader.IsSupersetOf(pair.Value))
                {
                    continue;
                }
                if (a.IsSupersetOf(pair.Key.Args))
                {
                    recipients.UnionWith(pair.Value);
                }
            }

            foreach (Connection conn in recipients)
            {
                // TODO: rewrite/don't header fields
                //conn.Send (msg);
                // TODO: Zero the Serial or not?
                //msg.Header.Serial = 0;
                ((ServerConnection)conn).SendReal(msg);
            }
        }
Пример #4
0
        public void ToggleSignal(string iface, string member, Delegate dlg, bool adding)
        {
            MatchRule rule = new MatchRule ();
            rule.MessageType = MessageType.Signal;
            rule.Fields.Add (FieldCode.Interface, new MatchTest (iface));
            rule.Fields.Add (FieldCode.Member, new MatchTest (member));
            rule.Fields.Add (FieldCode.Path, new MatchTest (object_path));
            rule.Fields.Add (FieldCode.Sender, new MatchTest (alt_bus_name ?? bus_name));

            if (adding) {
                if (conn.Handlers.ContainsKey (rule))
                    conn.Handlers[rule] = Delegate.Combine (conn.Handlers[rule], dlg);
                else {
                    conn.Handlers[rule] = dlg;
                    conn.AddMatch (rule.ToString ());
                }
            } else if (conn.Handlers.ContainsKey (rule)) {
                conn.Handlers[rule] = Delegate.Remove (conn.Handlers[rule], dlg);
                if (conn.Handlers[rule] == null) {
                    conn.RemoveMatch (rule.ToString ());
                    conn.Handlers.Remove (rule);
                }
            }
        }
Пример #5
0
        public static MatchRule Parse(string text)
        {
            if (text.Length > Protocol.MaxMatchRuleLength)
            {
                throw new Exception("Match rule length exceeds maximum " + Protocol.MaxMatchRuleLength + " characters");
            }

            MatchRule r = new MatchRule();

            // TODO: Stricter validation. Tighten up the regex.
            // It currently succeeds and silently drops malformed test parts.

            for (Match m = matchRuleRegex.Match(text); m.Success; m = m.NextMatch())
            {
                string key   = m.Groups[1].Value;
                string value = m.Groups[2].Value;
                // This unescaping may not be perfect..
                value = value.Replace(@"\\", @"\");
                value = value.Replace(@"\'", @"'");

                if (key.StartsWith("arg"))
                {
                    Match mArg = argNRegex.Match(key);
                    if (!mArg.Success)
                    {
                        return(null);
                    }
                    int argNum = (int)UInt32.Parse(mArg.Groups[1].Value);

                    if (argNum < 0 || argNum >= Protocol.MaxMatchRuleArgs)
                    {
                        throw new Exception("arg match must be between 0 and " + (Protocol.MaxMatchRuleArgs - 1) + " inclusive");
                    }

                    //if (r.Args.ContainsKey (argNum))
                    //	return null;

                    string argType = mArg.Groups[2].Value;

                    if (argType == "path")
                    {
                        r.Args.Add(new ArgMatchTest(argNum, new ObjectPath(value)));
                    }
                    else
                    {
                        r.Args.Add(new ArgMatchTest(argNum, value));
                    }

                    continue;
                }

                //TODO: more consistent error handling
                switch (key)
                {
                case "type":
                    if (r.MessageType != null)
                    {
                        return(null);
                    }
                    r.MessageType = MessageFilter.StringToMessageType(value);
                    break;

                case "interface":
                    r.Fields[FieldCode.Interface] = new MatchTest(value);
                    break;

                case "member":
                    r.Fields[FieldCode.Member] = new MatchTest(value);
                    break;

                case "path":
                    r.Fields[FieldCode.Path] = new MatchTest(new ObjectPath(value));
                    break;

                case "sender":
                    r.Fields[FieldCode.Sender] = new MatchTest(value);
                    break;

                case "destination":
                    r.Fields[FieldCode.Destination] = new MatchTest(value);
                    break;

                default:
                    if (Protocol.Verbose)
                    {
                        Console.Error.WriteLine("Warning: Unrecognized match rule key: " + key);
                    }
                    break;
                }
            }

            return(r);
        }
Пример #6
0
        //this might need reworking with MulticastDelegate
        internal void HandleSignal(Message msg)
        {
            var signal = MessageContainer.FromMessage(msg);

            //TODO: this is a hack, not necessary when MatchRule is complete
            MatchRule[] rules = new MatchRule[2];
            rules[0]             = new MatchRule();
            rules[0].MessageType = MessageType.Signal;
            rules[0].Fields.Add(FieldCode.Interface, new MatchTest(signal.Interface));
            rules[0].Fields.Add(FieldCode.Member, new MatchTest(signal.Member));
            //rules[0].Fields.Add (FieldCode.Sender, new MatchTest (signal.Sender));
            rules[0].Fields.Add(FieldCode.Path, new MatchTest(signal.Path));
            rules[1]             = new MatchRule();
            rules[1].MessageType = MessageType.Signal;
            rules[1].Fields.Add(FieldCode.Interface, new MatchTest(signal.Interface));
            rules[1].Fields.Add(FieldCode.Member, new MatchTest(signal.Member));
            rules[1].Fields.Add(FieldCode.Sender, new MatchTest(signal.Sender));
            rules[1].Fields.Add(FieldCode.Path, new MatchTest(signal.Path));

            bool handlerFound = false;

            foreach (var rule in rules)
            {
                Delegate dlg;
                if (Handlers.TryGetValue(rule, out dlg) && dlg != null)
                {
                    MethodInfo mi = dlg.GetType().GetMethod("Invoke");

                    bool      compatible = false;
                    Signature inSig, outSig;
                    bool      hasDisposableList;

                    if (TypeImplementer.SigsForMethod(mi, out inSig, out outSig, out hasDisposableList))
                    {
                        if (outSig == Signature.Empty && inSig == msg.Signature && !hasDisposableList)
                        {
                            compatible = true;
                        }
                    }

                    if (!compatible)
                    {
                        if (ProtocolInformation.Verbose)
                        {
                            Console.Error.WriteLine("Signal argument mismatch: " + signal.Interface + '.' + signal.Member);
                        }
                        return;
                    }

                    //signals have no return value
                    dlg.DynamicInvoke(MessageHelper.GetDynamicValues(msg, mi.GetParameters()));
                    handlerFound = true;
                }
            }
            if (!handlerFound)
            {
                //TODO: how should we handle this condition? sending an Error may not be appropriate in this case
                if (ProtocolInformation.Verbose)
                {
                    Console.Error.WriteLine("Warning: No signal handler for " + signal.Member);
                }
            }
        }