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