XMPP and WCF .Net – Connecting a XMPP client to Openfire
With Openfire installed (http://www.johandekoning.nl/index.php/2009/11/30/xmpp-and-wcf-net-installation-of-openfire/) it is time to create some users and connect with a XMPP client to the server.
User management
Because of the simple installation, users created on the Openfire server are stored inside the embedded database. To add new users, make sure that the server runs and open the administration console (default address http://localhost:9090).
Note: I already mentioned this in my previous blog. Within my Vista environment I had to make sure that I start the Openfire server as administrator
Within the Administration Console, you will find the Users/Groups section at the top of the page. When you open this section you will get an overview of the users created on the Openfire server
Click on the Create New User option on the left, to create a new user. The Create User page needs some information for the new user. Provide this information and click create user to add the user. Or choose Create & Create another if you want to create another user after this user account is added.
I create two users which are called user1 and user2. I gave the the same password as their username. The overview shows the following user list.
One of the core extensions of the XMPP protocol is the ability to have a user list which is stored on the server (which is called a Roster). Within the Administration Console you can manage those lists, to make it possible that user1 has user2 as a contact and visa versa. This is off course also possible from within a XMPP client where you can add new users.
To manage a contacts list (roster) for a user, click on the username (of the user you want to manage) from the overview. You will get the User Properties screen, with some basic information.
At the left you will find a Roster option. When you click that option, you get an overview of the roster items. These items can be other users, or groups of users. Click the Add New Item (at the right of the screen) to add user 2 to the roster items of user 1.
When added, the user roster overview will show user 2. Perform the same action for user 2 but this time add user 1 to the roster list.
When both users are on both list, the user configuration part is finished. I know it is very basic, but this is jus for development. When can now use a XMPP client to make a connection with our server.
Using Psi (XMPP Client)
There are a lot of XMPP clients available on the Internet. I use Psi because it has a nice XML logging feature, to make the XMPP stream visible. I can use this sample stream for development of a XMPP client in .Net without the use of WCF. You can download the Psi client at http://psi-im.org/download/
When you start the client for the first time, it will show you a message that you need to set up an account. Click on the Use existing account option, because our test accounts are already available on the server.
On the first tab (Account) fill in the Jabber ID (JID) and password. The jabber ids for our users are user1@localfire and user2@localfire . The password are user1 and user2.
At the connection tab, we need to specify our server location. This is localhost when it runs on the same machine where you installed this client. For testing purposes we will not use an encrypt connection (Never).
Click save to store the account information. The main screen of Psi will be visible whereby the user status is set to Offline.
Before we connect to our Openfire server, I want to enable the XML console to get an idea of the stream which is send between client and server. Right click on the first item of the list (openfire) and select Open XML Console… Within the XML Console, mark the enable checbox at the bottem left. To get the client connected, select from the dropdownlist at the bottom of the main screen, the Online status. The client will connect to the server and the stream will be made visible in the XML Console dialog.
The XMPP stream
I connected another client to the server as user 2. Between both users i send a message with the text “Hello” (User 1 -> User 2) and “Goodbye” (User 2 -> User 1). The presence of user 1 will be set to Offline and the application will be closed. Below you find the captured XMPP stream.
What’s next?
This blog post explained how to set up the connecting between a XMPP client and server. The captured stream will be used for further analysis. The next step will be the development of a simple XMPP client which will echo back received messages in reverse order. This client will not be written with Windows Communication Foundation to get some feeling how a .Net client with the TcpClient class will work.
If you have questions after reading this post, or have other feedback? Please send in a comment.
<!--client--> <?xml version="1.0"?> <stream:stream xmlns:stream="http://etherx.jabber.org/streams" version="1.0" xmlns="jabber:client" to="localfire" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace" > <!--server--> <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="localfire" id="c035b19c" xml:lang="en" version="1.0"> <stream:features> <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/> <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"> <mechanism>DIGEST-MD5</mechanism> <mechanism>PLAIN</mechanism> <mechanism>ANONYMOUS</mechanism> <mechanism>CRAM-MD5</mechanism> </mechanisms> <compression xmlns="http://jabber.org/features/compress"> <method>zlib</method> </compression> <auth xmlns="http://jabber.org/features/iq-auth"/> <register xmlns="http://jabber.org/features/iq-register"/> </stream:features> <!--client--> <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="DIGEST-MD5" /> <!--server--> <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09ImxvY2FsZmlyZSIsbm9uY2U9IitaQVRkeUZNeWJjV1ZveHJHTXNIV2dxNVR1QWhNUkFoQ08wVWlp VzciLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=</challenge> <!--client--> <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dXNlcm5hbWU9InVzZXIxIixyZWFsbT0ibG9jYWxmaXJlIixub25jZT0iK1pBVGR5Rk15YmNXVm94ckdNc0hXZ3E1 VHVBaE1SQWhDTzBVaWlXNyIsY25vbmNlPSJhM0dMY21ra3VFUjEwaVBTMlJzQnpRZWlBY2pzSnIzNVNyTzRkTFNzM 2FnPSIsbmM9MDAwMDAwMDEsZGlnZXN0LXVyaT0ieG1wcC9sb2NhbGZpcmUiLHFvcD1hdXRoLHJlc3BvbnNlPWM1N TlhMjBhMmFkZGVjYmJjOTFkZTZkNDYwODYyODU5LGNoYXJzZXQ9dXRmLTg=</response> <!--server--> <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD04NjMxMTIzNDZlM2MxOTUxMGZlNzFmNTA5N2E0MWViMg==</success> <!--client--> <?xml version="1.0"?> <stream:stream xmlns:stream="http://etherx.jabber.org/streams" version="1.0" xmlns="jabber:client" to="localfire" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace" > <!--server--> <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="localfire" id="c035b19c" xml:lang="en" version="1.0"> <stream:features> <compression xmlns="http://jabber.org/features/compress"> <method>zlib</method> </compression> <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/> <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/> </stream:features> <!--client--> <iq type="set" id="bind_1" > <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"> <resource>Home</resource> </bind> </iq> <!--server--> <iq xmlns="jabber:client" type="result" id="bind_1" to="localfire/c035b19c" > <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"> <jid>user1@localfire/Home</jid> </bind> </iq> <!--client--> <iq type="set" id="aab7a" > <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/> </iq> <!--server--> <iq type="result" id="aab7a" to="user1@localfire/Home" > <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/> </iq> <!--client--> <iq type="get" id="aab8a" > <query xmlns="jabber:iq:roster"/> </iq> <!--server--> <iq type="result" id="aab8a" to="user1@localfire/Home" > <query xmlns="jabber:iq:roster"> <item subscription="both" jid="user2@localfire" /> </query> </iq> <!--client--> <presence> <priority>5</priority> <c xmlns="http://jabber.org/protocol/caps" node="http://psi-im.org/caps" ver="0.13-dev-rev2" ext="ca cs ep-notify html" /> </presence> <iq type="get" to="user1@localfire/Home" id="aabaa" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://psi-im.org/caps#ca" /> </iq> <iq type="get" id="aabba" > <query xmlns="jabber:iq:private"> <storage xmlns="storage:bookmarks"/> </query> </iq> <iq type="get" to="user1@localfire" id="aabca" > <vCard xmlns="vcard-temp" version="2.0" prodid="-//HandGen//NONSGML vGen v1.0//EN" /> </iq> <iq type="get" to="localfire" id="aabda" > <query xmlns="http://jabber.org/protocol/disco#info"/> </iq> <!--server--> <presence from="user2@localfire/Work" to="user1@localfire/Home" > <c xmlns="http://jabber.org/protocol/caps" node="http://exodus.jabberstudio.org/caps" ext="xhtml-im" ver="0.10.0.0" /> <priority>1</priority> </presence> <!--client--> <iq type="get" to="user2@localfire/Work" id="aabea" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://exodus.jabberstudio.org/caps#0.10.0.0" /> </iq> <iq type="get" to="user2@localfire/Work" id="aabfa" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://exodus.jabberstudio.org/caps#xhtml-im" /> </iq> <!--server--> <iq from="user1@localfire/Home" type="get" to="user1@localfire/Home" id="aabaa" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://psi-im.org/caps#ca" /> </iq> <!--client--> <iq type="result" to="user1@localfire/Home" id="aabaa" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://psi-im.org/caps#ca" > <identity category="client" type="pc" name="Psi" /> <feature var="urn:xmpp:jingle:1" /> <feature var="urn:xmpp:jingle:transports:ice-udp:1" /> <feature var="urn:xmpp:jingle:apps:rtp:1" /> <feature var="urn:xmpp:jingle:apps:rtp:audio" /> </query> </iq> <!--server--> <iq type="result" id="aabba" to="user1@localfire/Home" > <query xmlns="jabber:iq:private"> <storage xmlns="storage:bookmarks"/> </query> </iq> <iq from="user1@localfire" type="result" id="aabca" to="user1@localfire/Home" > <vCard xmlns="vcard-temp" version="2.0" prodid="-//HandGen//NONSGML vGen v1.0//EN" > <FN>User 1</FN> </vCard> </iq> <iq from="localfire" type="result" id="aabda" to="user1@localfire/Home" > <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="server" type="im" name="Openfire Server" /> <identity category="pubsub" type="pep" /> <feature var="http://jabber.org/protocol/pubsub#manage-subscriptions" /> <feature var="http://jabber.org/protocol/pubsub#modify-affiliations" /> <feature var="http://jabber.org/protocol/pubsub#retrieve-default" /> <feature var="http://jabber.org/protocol/pubsub#collections" /> <feature var="jabber:iq:private" /> <feature var="http://jabber.org/protocol/disco#items" /> <feature var="vcard-temp" /> <feature var="http://jabber.org/protocol/pubsub#publish" /> <feature var="http://jabber.org/protocol/pubsub#subscribe" /> <feature var="http://jabber.org/protocol/pubsub#retract-items" /> <feature var="http://jabber.org/protocol/offline" /> <feature var="http://jabber.org/protocol/pubsub#meta-data" /> <feature var="jabber:iq:register" /> <feature var="http://jabber.org/protocol/pubsub#retrieve-subscriptions" /> <feature var="http://jabber.org/protocol/pubsub#default_access_model_open" /> <feature var="jabber:iq:roster" /> <feature var="http://jabber.org/protocol/pubsub#config-node" /> <feature var="http://jabber.org/protocol/address" /> <feature var="http://jabber.org/protocol/pubsub#publisher-affiliation" /> <feature var="http://jabber.org/protocol/pubsub#item-ids" /> <feature var="http://jabber.org/protocol/pubsub#instant-nodes" /> <feature var="http://jabber.org/protocol/commands" /> <feature var="http://jabber.org/protocol/pubsub#multi-subscribe" /> <feature var="http://jabber.org/protocol/pubsub#outcast-affiliation" /> <feature var="http://jabber.org/protocol/pubsub#get-pending" /> <feature var="google:jingleinfo" /> <feature var="jabber:iq:privacy" /> <feature var="http://jabber.org/protocol/pubsub#subscription-options" /> <feature var="jabber:iq:last" /> <feature var="http://jabber.org/protocol/pubsub#create-and-configure" /> <feature var="urn:xmpp:ping" /> <feature var="http://jabber.org/protocol/pubsub#retrieve-items" /> <feature var="jabber:iq:time" /> <feature var="http://jabber.org/protocol/pubsub#create-nodes" /> <feature var="http://jabber.org/protocol/pubsub#persistent-items" /> <feature var="jabber:iq:version" /> <feature var="http://jabber.org/protocol/pubsub#presence-notifications" /> <feature var="http://jabber.org/protocol/pubsub" /> <feature var="http://jabber.org/protocol/pubsub#retrieve-affiliations" /> <feature var="http://jabber.org/protocol/pubsub#delete-nodes" /> <feature var="http://jabber.org/protocol/pubsub#purge-nodes" /> <feature var="http://jabber.org/protocol/disco#info" /> <feature var="http://jabber.org/protocol/rsm" /> </query> </iq> <iq from="user2@localfire/Work" type="result" id="aabea" to="user1@localfire/Home" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://exodus.jabberstudio.org/caps#0.10.0.0" > <feature var="jabber:iq:agents" /> <feature var="jabber:iq:oob" /> <feature var="jabber:iq:browse" /> <feature var="jabber:iq:time" /> <feature var="jabber:iq:version" /> <feature var="jabber:iq:last" /> <feature var="http://jabber.org/protocol/disco#items" /> <feature var="http://jabber.org/protocol/disco#info" /> <feature var="storage:bookmarks" /> <feature var="jabber:x:data" /> <feature var="jabber:x:conference" /> <feature var="jabber:x:event" /> <feature var="http://jabber.org/protocol/muc" /> <feature var="http://jabber.org/protocol/muc#user" /> <feature var="http://jabber.org/protocol/muc#owner" /> <feature var="http://jabber.org/protocol/si" /> <feature var="http://jabber.org/protocol/si/profile/file-transfer" /> <feature var="http://jabber.org/protocol/bytestreams" /> </query> </iq> <iq from="user2@localfire/Work" type="result" id="aabfa" to="user1@localfire/Home" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://exodus.jabberstudio.org/caps#xhtml-im" > <feature var="http://jabber.org/protocol/xhtml-im" /> </query> </iq> <iq from="user1@localfire/Home" type="result" to="user1@localfire/Home" id="aabaa" > <query xmlns="http://jabber.org/protocol/disco#info" node="http://psi-im.org/caps#ca" > <identity category="client" type="pc" name="Psi" /> <feature var="urn:xmpp:jingle:1" /> <feature var="urn:xmpp:jingle:transports:ice-udp:1" /> <feature var="urn:xmpp:jingle:apps:rtp:1" /> <feature var="urn:xmpp:jingle:apps:rtp:audio" /> </query> </iq> <!--client--> <message type="chat" to="user2@localfire" id="aac0a" > <body>Hello</body> <active xmlns="http://jabber.org/protocol/chatstates"/> </message> <!--server--> <message from="user2@localfire/Work" type="chat" id="jcl_13" to="user1@localfire/Home" > <body>Goodbye</body> <x xmlns="jabber:x:event"> <composing/> </x> <html xmlns="http://jabber.org/protocol/xhtml-im"> <body xmlns="http://www.w3.org/1999/xhtml"> <p style="font-size:small;font-family:Arial;color:#000000" >Goodbye</p> </body> </html> </message> <!--client--> <presence type="unavailable" > <status>Logged out</status> </presence> </stream:stream> <!--server--> </stream:stream>
Read more from the Uncategorized category. If you would like to leave a comment, click here: Comment. or stay up to date with this post via RSS, or you can
Trackback from your site.
In my previous blogpost, I talked about my goal to make an XMPP implementation within .Net based on Windows Communication Foundation. Before I can start, I had to find out how a normal XMPP stream would be send/retrieved between client and server. In this blogitem, I will explain the steps I took to install the OpenFire server. http://www.igniterealtime.org/projects/openfire/index.jsp Within my other blog I used a seperate environment which is mostly based on Ubuntu. This time I install the OpenFire server within Windows Vista. The reason for this is that it is also the environment of my .Net development tools. First download the installation file of OpenFire from the website. I use Openfire 3.6.4 http://www.igniterealtime.org/downloads/index.jsp The installation wizard is quite straight forward and more like next-next-finish. On the last step, mark the Run Openfire option (which is marked by default) to launch the Openfire server. This makes it possible to continue the installation from the Admin Console (which runs inside the browser). To finalize the installation, some setup steps will be shown within the Admin Console. Select the prefered language in the first step You can keep the server settings values the default. Because I will only use the Openfire server locally (or within my own netwerk) it is not important that the right domain is set. The clients will connect to localhost or the ipaddress of the computer. Because I want to keep the installation as simple as possible, I choose for an Embedded database. The performance penalty with the embedded database is for test purposes not an issue. I will create the test users from within the Admin console. This means that I don’t need Active Directory/LDAP or Clearspace integration. I choose for the Default option to store users inside the server database. To access the admin console after these setup steps, it is important to setup an Administration account. The username of this account will be “admin”
This completes the openfire setup process. You can now login to the real admin console Note: I had some trouble to log in to the Admin Console on my Vista enviroment. The admin user was not valid. I found out that I had to restart the Openfire server by stopping the server, quit the status dialog and start the Openfire server again for the start menu. It is important to start the Openfire server as administrator (right click on the shortcut and select Run as administrator) otherwise you are still not able to login.
As a mentioned the installation of Openfire, with the (default) settings I chose, is easy and straight forward. The next step will be to configure some users and to connect a XMPP client to the server. In the meantime I really like to have you feedback on this blogpost (did you like the images to explain the installation) or on my other blogposts. Read more from the Uncategorized category. If you would like to leave a comment, click here: 1 Comment. or stay up to date with this post via RSS, or you can
Trackback from your site.
XMPP and WCF .Net – Installation of OpenFire
Installation wizard
Admin console installation/configuration
What’s next?



























