Getting Started with the XMPP Component
Requirements: IPWorks
The Extensible Messaging and Presence Protocol (XMPP), originally known as Jabber, is an open standard for instant messaging and presence. The XMPP component in IPWorks implements the core instant messaging and presence functionality of XMPP in an easy-to-use, event-driven interface. Incoming messages and presence notifications arrive in events, and messages and other actions are sent using the component's methods. This article covers the basics of building an XMPP client, including logging in, managing the roster (buddy list), tracking presence, and sending and receiving messages.
Contents
- Connecting and Logging In
- Registering a New Account
- The Roster
- Presence
- Sending Messages
- Receiving Messages
- Adding and Removing Buddies
- Subscription Requests
- Sending Custom XML
Connecting and Logging In
To connect to an XMPP server, set the IMServer property to the server's host name, and call the ConnectTo method with the user's Jabber ID and password. Alternatively, set the User and Password properties, and call the Connect method. The component performs the entire login process, including connecting to the server, authenticating, and initializing the session.
TLS is supported directly by the XMPP component. By default, the SSLStartMode property is set to sslAutomatic, so the connection is secured whenever the server supports it. The SSLServerAuthentication event fires when the server's certificate is received, and can be used to accept a certificate that is not trusted by the system.
XMPP xmpp = new XMPP();
xmpp.IMServer = "xmpp.example.com";
xmpp.ConnectTo("user@example.com", "PASSWORD");
The XMPP component is event-driven, so events such as MessageIn and Presence fire while the component is processing incoming data. In a console application or service, call the DoEvents method in a loop to process incoming data.
while (xmpp.Connected) {
xmpp.DoEvents();
}
To log out, call the Disconnect method.
In desktop applications, note that events may fire on a different thread than the user interface thread. Since user interface controls can only be accessed from the user interface thread, use the framework's standard mechanism (e.g., Control.Invoke in Windows Forms) to update the user interface from event handlers.
Registering a New Account
Many XMPP servers allow new accounts to be registered by the client. Registration is a two-step process:
- Call the QueryRegister method to ask the server which fields are required to create an account. The required fields are placed in the UserInfo collection, with empty values.
- Set the value of each field, and call the Register method to create the account.
// Query the server for the required registration fields.
xmpp.QueryRegister("xmpp.example.com");
foreach (var field in xmpp.UserInfo.Keys) {
Console.WriteLine("Required field: " + field);
}
// Set the values of the required fields, and register the account.
xmpp.UserInfo["username"].Value = "newuser";
xmpp.UserInfo["password"].Value = "NEW_PASSWORD";
xmpp.Register("xmpp.example.com");
Common registration fields defined by the XMPP specification include username, password, name, and email. The SetUserInputFieldName method can also be used to set a field's value, and adds the field if the server did not request it. If the component is not connected when QueryRegister or Register is called, it connects to the server, performs the request, and then disconnects.
The Roster
The roster (also known as the buddy list) is the list of contacts associated with the user's account. After logging in, the component automatically retrieves the roster from the server, and the Sync event fires once the Buddies collection has been populated. The roster can also be retrieved again at any time by calling the RetrieveRoster method, which also fires the Sync event.
Each buddy in the Buddies collection includes the following fields:
| Field | Description |
|---|---|
| Id | The Jabber ID of the buddy. |
| NickName | The name associated with the buddy in the roster. |
| Group | The group the buddy belongs to. A buddy in more than one group has a separate entry for each group. |
| Subscription | The subscription type: stNone, stTo (the user receives the buddy's presence), stFrom (the buddy receives the user's presence), or stBoth. |
xmpp.OnSync += (s, e) => {
foreach (XMPPBuddy buddy in xmpp.Buddies) {
string group = buddy.Group == "" ? "Other" : buddy.Group;
Console.WriteLine(group + ": " + buddy.Id + " (" + buddy.Subscription + ")");
}
};
Presence
Presence indicates whether a user is available. When a buddy to whom the user has a subscription changes their presence, the Presence event fires. Its User, Domain, and Resource parameters identify the buddy, its Status parameter contains an optional status message, and its Availability parameter contains one of the following values:
| Value | Meaning |
|---|---|
| pcOffline (0) | The buddy is offline. |
| pcChat (1) | The buddy is online and available. |
| pcAway (2) | The buddy is online, but away. |
| pcXA (3) | The buddy is online, but away for an extended period of time. |
| pcDND (4) | The buddy is online, but does not wish to be disturbed. |
xmpp.OnPresence += (s, e) => {
Console.WriteLine(e.User + "@" + e.Domain + " is now " + (XMPPPresences)e.Availability + " " + e.Status);
};
To change the user's own presence, call the ChangePresence method with one of the values above and an optional status message. By default, the user's presence is set to pcChat (available) after logging in.
xmpp.ChangePresence((int)XMPPPresences.pcAway, "In a meeting");
Sending Messages
To send a message, set the MessageText property (and optionally the MessageType, MessageSubject, and MessageHTML properties), and then call the SendMessage method with the recipient's Jabber ID. The method returns the ID of the sent message. For one-on-one conversations, set MessageType to jmtChat.
xmpp.MessageType = XMPPMessageTypes.jmtChat;
xmpp.MessageText = "Hello! Are you available for a quick call?";
xmpp.SendMessage("buddy@example.com");
If the recipient's Jabber ID does not include a resource (e.g., buddy@example.com/laptop), the message is delivered to all of the recipient's logged-in clients.
Receiving Messages
When a message is received, the MessageIn event fires. Its From, Domain, and Resource parameters identify the sender, and its MessageText and MessageHTML parameters contain the body of the message.
xmpp.OnMessageIn += (s, e) => {
Console.WriteLine(e.From + "@" + e.Domain + ": " + e.MessageText);
};
Adding and Removing Buddies
To add a buddy to the roster, call the Add method with the buddy's Jabber ID, a name for the buddy, and an optional comma-separated list of groups. Adding a buddy to the roster does not subscribe to their presence, so the SubscribeTo method is typically called as well.
// Add a buddy to the "Coworkers" group, and request a subscription to their presence.
xmpp.Add("buddy@example.com", "Buddy", "Coworkers");
xmpp.SubscribeTo("buddy@example.com");
To remove a buddy from a group in the roster, call the Remove method with the buddy's Jabber ID, name, and group. To stop receiving a buddy's presence, call the UnsubscribeTo method.
xmpp.Remove("buddy@example.com", "Buddy", "Coworkers");
Subscription Requests
When another user requests a subscription to the current user's presence, the SubscriptionRequest event fires. By default, the request is rejected; to allow it, set the event's Accept parameter to true.
xmpp.OnSubscriptionRequest += (s, e) => {
// Only accept requests from users in the organization's domain.
if (e.Domain == "example.com") e.Accept = true;
};
Sending Custom XML
The XMPP component implements the core XMPP protocol. For protocol extensions that the component does not implement directly, such as chat state notifications (e.g., "user is typing" indicators), the SendCommand method can be used to send raw XML to the server.
// Notify a buddy that the user is typing (XEP-0085: Chat State Notifications).
xmpp.SendCommand("<message to='buddy@example.com' type='chat'><composing xmlns='http://jabber.org/protocol/chatstates'/></message>");
To process incoming XML that the component does not parse, use the PITrail event, which provides the raw XML of all data sent and received. The IQ event also fires for each incoming IQ (info/query) request, and provides its raw XML.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.