Not logged in. · Lost password · Register
Forum: MatriX and XmppDotNet RSS
Avatar
johnm60 #1
Member since Jun 2010 · 32 posts
Group memberships: Members
Show profile · Link to this post
Subject: Iq Filters on Iq receive
Hi

I have built a few test applications and I am pretty happy so far. One thing that I do not feel I have a grip on is how to handle Iq's where the application is the service provider. If I send an Iq (as a client or service consumer), I can register a method that gets called when a response is returned.

var diq = new DispatcherIq
{
    Type = Matrix.Xmpp.IqType.get,
    To = item.DestinationJid + "/" + client.Resource,
    Dispatcher = new Dispatcher { SenderMAN = client.Username, RecipientMAN = item.DestinationJid, Filename = item.Filename }
};
client.IqFilter.SendIq(diq, DispatcherResponse);

which then returns a response to:

private void DispatcherResponse(object sender, Matrix.Xmpp.Client.IqEventArgs e)
{
            var iq = e.Iq;
            if (iq.Type == Matrix.Xmpp.IqType.result)
            {
                var dispatcher = iq.Element<Dispatcher>();
                if (dispatcher != null)
                {
                    log("Got a dispatch response " + dispatcher.Filename);
                    //do something interesting
                }
            }
}

At the other end of this, I process an OnIq event, with something like this:

void client_OnIq(object sender, IqEventArgs e)
{
            try  //no parent calling function, so put a try catch block
            {
                if (e.Iq.Type == Matrix.Xmpp.IqType.get && e.Iq.Query is Dispatcher)
                {
                    // this is now acting as a service provider from another client
                    var dispatcher = e.Iq.Query as Dispatcher;
                    //now send response
                    var diq = new DispatcherIq
                    {
                        Id = e.Iq.Id,  //used to correlate with the request !!!
                        To = e.Iq.From,
                        Type = Matrix.Xmpp.IqType.result,
                        Dispatcher = new Dispatcher { Filename = dispatcher.Filename, MessageBody = "success"}
                    };
                    // send the response
                    client.Send(diq);
                }
            }
            catch (Exception ex)
            {
                log("On_Iq error: " + ex.ToString());
            }
}

This is all fine, but if I have a BOT for instance that I want to respond to several types or classes of Iq, I end up with a complicated event handler that switches on the event type. This is OK, but a little unwieldy. I could create a dictionary of event type to method and register each of the event types and then the main Iq handler could then look up the event type and then delegate it the previously registered method. This would keep the OnIq handler tidy and there would then be a handler method for each type of Iq.

I strikes me that this is capability that could be in the Matrix client. Have I overlooked a capability that is already there? Or should I use a mechanism such as I described to manage this myself?

Thanks
John
Avatar
Alex #2
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
there is nothing like that currently in MatriX. I created a class for this for a customer project. I have to cleanup the code a bit and will share it with you here then.

Alex
Avatar
Alex #3
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
here is a small helper class for filtering incoming Iqs and raising the callbacks.

  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using Matrix.Xml;
  5. using Matrix.Xmpp.Client;
  6.  
  7. namespace MiniClient
  8. {
  9.     public class CallbackFilter
  10.     {
  11.         private readonly List<FilterData> filters = new List<FilterData>();
  12.        
  13.         public CallbackFilter(XmppClient xmppClient)
  14.         {
  15.             xmppClient.OnIq += OnIq;    
  16.         }
  17.  
  18.         void OnIq(object sender, IqEventArgs e)
  19.         {
  20.             foreach (FilterData data in filters)
  21.             {
  22.                 var query = e.Iq.Query;
  23.                 if (query != null)
  24.                 {
  25.                     if (query.GetType() == data.Type)
  26.                         data.Callback.Invoke(sender, e);
  27.                 }
  28.             }
  29.         }
  30.        
  31.         public void RegisterCallback<T>(EventHandler<IqEventArgs> del) where T : XmppXElement
  32.         {
  33.             filters.Add(new FilterData {Type = typeof(T), Callback = del});
  34.         }
  35.  
  36.         public void UnregisterCallback<T>() where T : XmppXElement
  37.         {
  38.             var f = filters.FirstOrDefault(fd => fd.Type.Equals(typeof (T)));
  39.             if (f != null)
  40.                 filters.Remove(f);
  41.            
  42.         }
  43.  
  44.         class FilterData
  45.         {
  46.             public Type Type {get;set;}
  47.             public EventHandler<IqEventArgs> Callback { get; set; }
  48.         }
  49.     }
  50. }

here is an example how to use it.

  1. private CallbackFilter cbf;
  2.  
  3. private void RegisterCallbacks())
  4. {
  5.     cbf = new CallbackFilter(xmppClient);
  6.     cbf.RegisterCallback<Matrix.Xmpp.Roster.Roster>(RosterCallback);
  7.     cbf.RegisterCallback<Matrix.Xmpp.Bind.Bind>(BindCallback);  
  8. }
  9.  
  10. private void RosterCallback(object sender, IqEventArgs e)
  11. {
  12. }
  13.  
  14. private void BindCallback(object sender, IqEventArgs e)
  15. {
  16. }
Alex
Avatar
johnm60 #4
Member since Jun 2010 · 32 posts
Group memberships: Members
Show profile · Link to this post
Thanks Alex

I will try this out on Monday in my application.

Regards
John
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters: