Not logged in. · Lost password · Register
Forum: MatriX RSS
Avatar
dutzend #1
Member since Oct 2016 · 3 posts
Group memberships: Members
Show profile · Link to this post
Subject: How to connect after failed registration
Hello,

in our environment, it is not sure whether the user account already exists when the client is launched. The registration process itself works fine, but if the account existed beforehand, it is impossible to connect to it afterwards. The xmppClient.Open() method does nothing, not even logging XML output.

I even created a registerAccount function that gets called before the regular login, using a seperate xmppClient object, also not successful:
  1. public partial class Form1 : Form
  2. {
  3.     static string serverFQDN = "localhost";
  4.     static string thisUname = "testusername"
  5.     static string thisPassword = "VerySecure";
  6.     static string thisJid = thisUname + "@" + serverFQDN;
  7.     static Jid jidThis = new Jid(thisJid);
  8.     static XmppClient xmppClient = new XmppClient();
  9.  
  10.     public Form1()
  11.     {
  12.     InitializeComponent();
  13.     registerClient();
  14.     xmppClient.Password = thisPassword;
  15.     xmppClient.Username = jidThis.User;
  16.     xmppClient.SetXmppDomain(jidThis.Server);
  17.     xmppClient.OnLogin += new EventHandler<Matrix.EventArgs>(XmppClient_OnLogin);
  18.     xmppClient.OnAuthError += new EventHandler<Matrix.Xmpp.Sasl.SaslEventArgs>(XmppClient_OnAuthError);
  19.     xmppClient.OnReceiveXml += new EventHandler<TextEventArgs>(XmppClientOnReceiveXml);
  20.     xmppClient.OnSendXml += new EventHandler<TextEventArgs>(XmppClientOnSendXml);
  21.     xmppClient.OnError += new EventHandler<Matrix.ExceptionEventArgs>(XmppClient_OnError);
  22.     xmppClient.Open();
  23.  
  24.     private static void registerClient()
  25.     {
  26.         XmppClient regXmppClient = new XmppClient();
  27.         regXmppClient.Password = thisPassword;
  28.         regXmppClient.Username = jidThis.User;
  29.         regXmppClient.SetXmppDomain(jidThis.Server);
  30.         regXmppClient.RegisterNewAccount = true;
  31.         regXmppClient.OnReceiveXml += new EventHandler<TextEventArgs>(RegXmppClientOnReceiveXml);
  32.         regXmppClient.OnSendXml += new EventHandler<TextEventArgs>(RegXmppClientOnSendXml);
  33.         regXmppClient.OnRegister += new EventHandler<Matrix.EventArgs> (xmppClient_OnRegister);
  34.         regXmppClient.OnRegisterError += new EventHandler<Matrix.Xmpp.Client.IqEventArgs> (xmppClient_OnRegisterError);
  35.         regXmppClient.OnRegisterInformation += new EventHandler<Matrix.Xmpp.Register.RegisterEventArgs>(xmppClient_OnRegisterInformation);
  36.         try
  37.         {
  38.             regXmppClient.Open();
  39.             regXmppClient.Close();
  40.             regXmppClient.Dispose();
  41.         }
  42.     }
  43.     private static void xmppClient_OnRegister(object sender, Matrix.EventArgs e)
  44.     {
  45.         //Registration success
  46.         writeLogEntry("Registration success", "xmppClient_OnRegister");
  47.     }
  48.  
  49.     private static void xmppClient_OnRegisterError(object sender, IqEventArgs e)
  50.     {
  51.         //This gets called if the registration fails (e.g. account already exists)
  52.         writeLogEntry(e.Iq.Error.ToString(), "xmppClient_OnRegisterError");
  53.     }
  54.     private static void xmppClient_OnRegisterInformation(object sender, Matrix.Xmpp.Register.RegisterEventArgs e)
  55.     {
  56.         writeLogEntry("Setting registration information", "xmppClient_OnRegisterInformation");
  57.         e.Register.XData.RemoveAll();
  58.         e.Register.XData.Remove();
  59.         e.Register.Password = thisPassword;
  60.         e.Register.Username = jidThis.User;
  61.     }
  62.     private static void writeLog(String fname, String msg, String type)
  63.     {
  64.         DateTime dt = DateTime.Now;
  65.         String timeStamp = dt.ToString("yyyyMMdd_HHmmss");
  66.         String fileName = fname+"_" + dt.ToString("yyyyMMdd");
  67.         String filePath = System.IO.Path.GetTempPath();
  68.         String fullPath = filePath + @"\" + fileName + ".log";
  69.         String text = "[" + timeStamp + " " + type + "] " + msg + Environment.NewLine;
  70.         if (File.Exists(fullPath))
  71.         {
  72.             File.AppendAllText(fullPath, text);
  73.         }
  74.         else
  75.         {
  76.             File.WriteAllText(fullPath, text);
  77.         }
  78.     }
  79.     private static void writeLogEntry(String msg, String type)
  80.     {
  81.         writeLog("client",msg,type);
  82.     }
  83.     private static void writeLogXml(String msg)
  84.     {
  85.         writeLog("clientxml", msg, "");
  86.     }
  87.     private static void writeLogRegXml(String msg)
  88.     {
  89.         writeLog("clientregxml", msg, "");
  90.     }
  91.     private static void XmppClientOnSendXml(object sender, TextEventArgs e)
  92.     {
  93.         writeLogXml("SEND: " + e.Text);
  94.     }
  95.     private static void XmppClientOnReceiveXml(object sender, TextEventArgs e)
  96.     {
  97.         writeLogXml("RECV: " + e.Text);
  98.     }
  99.     private static void RegXmppClientOnSendXml(object sender, TextEventArgs e)
  100.     {
  101.         writeLogRegXml("SEND: " + e.Text);
  102.     }
  103.  
  104.     private static void RegXmppClientOnReceiveXml(object sender, TextEventArgs e)
  105.     {
  106.         writeLogRegXml("RECV: " + e.Text);
  107.     }
  108. }}

Is this a bug in MatriX or do I need to rethink my program's logic?

Regards!
This post was edited on 2016-10-06, 11:42 by Alex.
Avatar
Alex #2
Member since Feb 2003 · 4296 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Quote by dutzend:
Is this a bug in MatriX or do I need to rethink my program's logic?

this is no bug. You have to reconsider your logic and also adjust it to your server.
Usually in XMPP there is nothing which tells you whether an account exists or not. This is also for security reasons. Otherwise it would be pretty easy with brute force attacks to find out which users exist on a server.

When you try to login with a non existing account a server usually does not tell you that the account does not exist. The message usually sais wrong credentials. Which could be wrong username, wrong domain or wrong password.

Also this code is wrong:

  1. regXmppClient.Open();
  2. regXmppClient.Close();
  3. regXmppClient.Dispose();

Open is async, which means it returns immediately, but the connection is not Open when it returns. YOu have to watch the events before you can close the connection.
Please study also the MiniClient example from here:
https://gitlab.com/matrix-xmpp/samples/tree/master/csharp/…
Avatar
dutzend #3
Member since Oct 2016 · 3 posts
Group memberships: Members
Show profile · Link to this post
Hi Alex,

thank you for the helpful response. Of course I did look at the sample code, but could not find my specific scenario (autoregistration if account is nonexistent).

I restructured the code to rely on the librarys events and try logging in first, but now I have a problem reopening the connection:
  1. static void XmppClient_OnAuthError(object sender, Matrix.Xmpp.Sasl.SaslEventArgs e)
  2. {
  3.     //This gets called if the login fails (e.g. account not exists)
  4.     writeLogEntry("Triggered", "XmppClient_OnAuthError");
  5.     registerAccount = true;
  6.     xmppClient.Close();
  7. }
  8. private void XmppClient_OnClose(object sender, Matrix.EventArgs e)
  9. {
  10.     //When the connection gets closed, try to reopen it with RegisterNewAccount property enabled
  11.     writeLogEntry("Register account status is: " + Convert.ToString(registerAccount), "XmppClient_OnClose");
  12.     if (registerAccount == true)
  13.     {
  14.         xmppClient.RegisterNewAccount = true;
  15.     }
  16.     else
  17.     {
  18.         xmppClient.RegisterNewAccount = false;
  19.     }
  20.     xmppClient.Open();
  21.     registerAccount = false;
  22. }

Everything is fine up to the point where the xmppClient object is supposed to open the connection again. Sometimes it works (Registration request is sent to the server), most of the time the open() method doesn't send anything in this case.

I suspect some kind of timing issue, when is the OnClose event exactly fired? During or after the stream closure? The documentation simply says "the xmpp session was closed", which would lead me to believe that the connection is already dead at this point...

Thanks again!
This post was edited on 2016-10-06, 15:22 by Alex.
Avatar
Alex #4
Member since Feb 2003 · 4296 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
I do not suggest to Open the connection again directly from the OnClose event. There is still some internal Cleanup to do after this event.
Put a timer there which waits 1-3 seconds an then reopens the connection. Or discard the old XmppClient and recreate a new XmppClient, then you don't have to wait until all resources are cleaned up internal.

Alex
Avatar
dutzend #5
Member since Oct 2016 · 3 posts
Group memberships: Members
Show profile · Link to this post
Okay, I think I found the main issue now. I am not sure whether this has something to do with your library or is a .NET problem.

I was using a timer object from the System.Timers.Timer class. For some reason, the xmppClient.Open() method doesn't do anything in this case. With changing it to a System.Windows.Forms.Timer, the connection works and XmppClient_OnLogin event gets triggered.

By the way, awesome support! Will order the full version soon!

Regards
Avatar
Alex #6
Member since Feb 2003 · 4296 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Quote by dutzend:
I was using a timer object from the System.Timers.Timer class. For some reason, the xmppClient.Open() method doesn't do anything in this case. With changing it to a System.Windows.Forms.Timer, the connection works and XmppClient_OnLogin event gets triggered.

this may be a threading problem. I think in this case you have to disable AutoInvoke and invoke all events on your own when required.

Alex
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:
Forum: MatriX RSS