My struggles with finding a C# xmpp library continues as I have now been force to rule out using both the Soapbox Studio SDK and aggXmpp / Matrix SDK. I have moved on to Jabber-net one of the few remaining C# libraries available and am thus far unable to connect to my Openfire Server. From what I understand this library like most xmpp libraries I have used thus far executes asynchronously so I am first calling the JabberClients 'Connect method' and bind a method that Logs into the server to the JabberClient's OnConnect handler.
Below is my Connect method that connects to the xmpp sever and binds the jabberClient's OnConnect handler to the Logon method.
public string Connect()
{
try
{
jabberClient = new JabberClient();
jabberClient.Connect();
jabberClient.OnConnect += (o, e) => Logon();
jabberClient.OnAuthError += (o, e) => ThrowError("authError");
jabberClient.OnStreamError += (o, e) => ThrowError("streamError");
return "Connection Succesful";
}
catch (Exception ex)
{
_logger.LogError("SessionManager", "Connect", "Could not connect to Openfire Server", ex.ToString());
return "Could not Connect to Openfire Server: " + ex;
}
}
Which produces the following output SRV found: denjab2.jabber.com:5222, but this throws a first change exception of type 'System.FormatException' when it reaches the jabberClinet's Connect method. It then outputs 'ExecuteConnect'
Below is the Logon Method
private void Logon()
{
JID jid = new JID(OPENFIRE_USER_NAME, OPENFIRE_SERVER, "protoTest");
jabberClient.User = jid.User;
jabberClient.Server = jid.Server;
jabberClient.Password = OPENFIRE_PASSWORD;
jabberClient.AutoLogin = true;
jabberClient.AutoPresence = true;
jabberClient.Login();
}
This method throws no exceptions.
Additionally, The JabberClient's onStreamError handler get called and simply procudes an exception that reads "A Stream Error Occured" and provides no inner exception.
I have tried to research these errors both on the web and through the products documentation but there seem to be no guides to establishing a connection to the server. I have to assume that I am either missing a step, not providing all of the necessary credentials, or am simply executed the steps needed to log on to the server in the wrong order.
After looking into the sample application mentioned in Joe Hildebrand's answer, I modified my 'Connect' method to look like the following.
public void Connect()
{
try
{
jabberClient = new JabberClient();
//Bind the JabberClient events to methods that handle those events.
jabberClient.OnAuthError += (o, e) => ThrowError(ErrorType.AuthError);
jabberClient.OnStreamError += (o, e) => ThrowError(ErrorType.StreamError);
jabberClient.OnError += (o, e) => ThrowError(ErrorType.UnknownError);
jabberClient.OnConnect += (o, e) => ConnectionComplete();
//Set client settings
jabberClient.AutoReconnect = 3f;
JID jid = new JID(OPENFIRE_USER_NAME, OPENFIRE_SERVER, "gec2o");
jabberClient.User = jid.User;
jabberClient.Server = jid.Server;
jabberClient.NetworkHost = null;
jabberClient.Port = OPENFIRE_NOT_ENCRYPTED_PORT;
jabberClient.Resource = jid.Resource;
jabberClient.Password = OPENFIRE_PASSWORD;
jabberClient.AutoStartTLS = false;
jabberClient.AutoPresence = false;
CapsManager cm = new CapsManager();
cm.Stream = jabberClient;
jabberClient.Connect();
}
catch (Exception ex)
{
_log.LogError("ConnectionManager", "Connect", "Could not connect to Openfire Server", ex.ToString());
throw ex;
}
}
However, this seems to result in the same behavior with the additional errors showing up in the console stating 'Sock errno: 10061' and an exception being thrown stating that 'No connection could be made because the target machine actively refused it' which indicates that for some reason the openfire server is rejected my connection request. I found This topic on the Jabber-net Google Group that suggest I use the server's IP address instead of server name due to the error possibly having something to do with the inability to resolve an IPv4 vs IPv6 issue.
Using the full IP addressed got rid of the 'Target Machine Actively Refused' error but presented me with following error
SEND: <iq id="JN_1" type="set" to="192.168.1.182"><bind
xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>rsup</resource></
bind></iq>
RECV: <iq type="error" id="JN_1" from="192.168.1.182" to="infotel/
bf18b431"><bind xmlns="urn:ietf:params:xml:ns:xmpp-
bind"><resource>rsup</resource></bind><error code="400"
type="modify"><bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/
></error></iq>
ERROR: jabber.connection.sasl.AuthenticationFailedException: Error
binding resource: <error code="400" type="modify"
xmlns="jabber:client"><bad-request xmlns="urn:ietf:params:xml:ns:xmpp-
stanzas" /></error>
This error is mention but not fully resolved on this thread of the Jabber-net Google Group
I was able to get rid of this error based on Joe Hildebrand comments by settings AutoStartTLS to true and creating an event handler for OnInvalidCertifcate and binding it to the jabber client.
Here is the revised 'Connect' method
public void Connect()
{
try
{
jabberClient = new JabberClient();
//Bind the JabberClient events to methods that handle those events.
jabberClient.OnAuthError += (o, e) => ThrowError(ErrorType.AuthError);
jabberClient.OnStreamError += (o, e) => ThrowError(ErrorType.StreamError);
jabberClient.OnError += (o, e) => ThrowError(ErrorType.UnknownError);
jabberClient.OnConnect += (o, e) => ConnectionComplete();
jabberClient.OnInvalidCertificate += new System.Net.Security.RemoteCertificateValidationCallback(OnInvalidCertificate);
//Set client settings
jabberClient.AutoReconnect = 3f;
JID jid = new JID(OPENFIRE_USER_NAME, OPENFIRE_SERVER, "gec2o");
jabberClient.User = jid.User;
//jabberClient.Server = jid.Server;
jabberClient.Server = "192.168.97.26";
jabberClient.NetworkHost = null;
jabberClient.Port = OPENFIRE_NOT_ENCRYPTED_PORT;
jabberClient.Resource = jid.Resource;
jabberClient.Password = OPENFIRE_PASSWORD;
jabberClient.AutoStartTLS = true;
jabberClient.AutoPresence = false;
CapsManager cm = new CapsManager();
cm.Stream = jabberClient;
jabberClient.Connect();
}
And here is the OnInvalidCertifcate event handler
bool OnInvalidCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
Console.WriteLine("Invalid certificate ({0}):\n{1}", sslPolicyErrors.ToString(), certificate.ToString(true));
return true;
}
This results in the following exception.
Error binding resource
<error type="modify" code="400"><bad-requestmlns="urn:ietf:params:xml:ns:xmpp-stanzas" /></error>
I should also note that the jabber-net sample Console Application does not work for me either.
This is my command line input when trying to run the app.
ConsoleClient.exe /j 800802@palburtus/gec2o /r 800802 /p 800802 /o 5222 /t true /n null
And this is the output I receive
Connecting
Connected
ERROR: System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it at System.Net.Sockets.Socket.EndConnect(IAsyncResult asy
at bedrock.net.AsyncSocket.ExecuteConnect(IAsyncResult a
.0.710\bedrock\net\AsyncSocket.cs:line 782
Hopefully someone can help explain what I'm doing wrong.