Showing posts with label xmpp. Show all posts
Showing posts with label xmpp. Show all posts

Tuesday, 2 April 2013

Openfire Custom IQ Handler


XMPP is providing plenty of Rosters. That we can use to develop a full fledged chat application. But Openfire is delighting its developers by providing custom plugins development.

I have been needed to add a plugin that would be helpful to search users from the server. On the application side i needed a list of users with some patterns.

I have developed following plugin code for that. This plugin gets installed on server side. It mainly deals with a custom IQ. Whenever application will request for that particular custom IQ. Server will pass flow to this custom plugin.

For developing custom iq. You need to extend IQHandler class. As well need to implement some of the methods from that class to provide your functionality.

public class SearchIQhanlder extends IQHandler { // extend IQ handler class to create a custom iq request
    private IQHandlerInfo info;
    
    public SearchIQhanlder(String moduleName)
    {
  super(moduleName);
  info = new IQHandlerInfo("query", "custom:iq:Search"); // provide a custom unique query signature for your IQ
    }
    
    public IQHandlerInfo getInfo()
    {
 return info;
    }
    
    public IQ handleIQ(IQ packet) throws UnauthorizedException{ // this method will handle the request. all login will go into this method.
 IQ result = IQ.createResultIQ(packet);
 try {
  // if you want to handle specific query. you need to check for its type. I needed this as i have wrote the plugin to provide some information to application. If you are setting some values on server side. You should use set type.
  IQ.Type type = packet.getType(); 
  result.setChildElement("query", "custom:iq:Search");
  Element query = result.getChildElement();
  // conditionally hanlde get or set type of IQ. I was not using set type. So i have make it as "not acceptable"
  if (type.equals(IQ.Type.get)) {
  } else {
      result.setChildElement(packet.getChildElement().createCopy());
      result.setChildElement("coord", "custom:iq:Search#response");    
      result.setError(PacketError.Condition.not_acceptable);
  }
  return result;
 } catch (Exception e) {
  // if you face any issue while processing. You can response back with "bad request"
  result.setChildElement(packet.getChildElement().createCopy());
  result.setChildElement("coord", "custom:iq:Search#response");    
  result.setError(PacketError.Condition.bad_request);
 } 
 return result;
    }
    
    public void initialize(XMPPServer server) {
 super.initialize(server);
    }    
}

Now you need to create one plugin class. That class would be extending plugin class. In that class you need to create one instance of IQ handler class that you have developed. Assign that handler class to IQ router. IQ router is kind bus of openfire that is managing roster requests.

 IQHandler handler = new SearchIQhanlder("SearchIQhanlder");
 IQRouter iqRouter = XMPPServer.getInstance().getIQRouter();
 iqRouter.addHandler(handler);  

On the application side you need to create one new IQ to request for your custom IQHanlder. Following is the example of what i have created.

<iq type='get' id='search' from='"+ Datas.jid.getLittleJid() + "'>
<query xmlns='custom:iq:Search'>
<search>"+ usernamefield.getText() +"</search>
</query>
</iq>

That is all to create a custom IQHandler. It is very easy to create such IQ. As well this would be very helpful for application development.

Let me know if you need any help regarding the same.

Friday, 20 July 2012

XMPP CHAT ROOM MECHANISM # PART-2

In last we have seen how to get list of all available rooms in server. This post is about how to use those information to chat in a room.

Once user get list of all room. He needs to choose one room out of it to chat with. User will send presence to existing room. Here there is a little bit change in presence stanza. User needs to add nick name for the room. All other user will see him as his nick name rather than username. e.g.
<presence from='{user-jid}/{resource}' to='{room-id}@conference.domain/{nick-name}'></presence>
Server will send presence to all the members of the room. As if any user joins room later, he will also be sent the presence. This way server informs all users of chat room about joining and leaving event of any user.
<presence to='{user-jid}/{resource}' from='{room-id}@conference.domain/{nick-name}'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item role='participant' affiliation='none'></item>
</x>
</presence>
Once user gets successfull presence. I have mentioned "successfully", as there are some conditions when user can not enter in a room. In that case server will return a error presence stanza. You can get more details about such stanze from here. If some user have already sent some message the room. User will get all those message as following format whenever he will join a room.
<message to='{user-jid}/{resource}' from='{room-id}@conference.domain' type='groupchat'>
<subject>us.country</subject>
<delay stamp='2012-07-18T18:02:24.328Z' from='{room-id}@conference.domain' xmlns='urn:xmpp:delay'></delay>
<x stamp='20120718T18:02:24' from='{room-id}@conference.domain' xmlns='jabber:x:delay'></x>
</message>
Once user joins a room. He can start sending message to the room. Here user must provide type attribute for presence stanza having value as "groupchat". Describe as following xml.
<message type='groupchat' from = '{user-jid}/{resource}' to ='{room-id}@conference.domain'>
<body>dfdf</body>
</message>
Whatever message is being sent to chat room. Room will send that message to all current users of the room.
<message to='{user-jid}/{resource}' from='{room-id}@conference.domain/{nick-name}' type='groupchat'>
<body>dfdf</body>
</message>
Now when user gets tired of chatting with bunch of people. He would like to leave the room. He needs to send unavailable presence stanza to room's jid, including nickname also. Here nick name is important because a room identifies user based on their nick name. So when you join a room. It will lock that nick name for you. If you are leaving it, you need to make server to unlock the nick name.
<presence from='{user-jid}/{resource}' to='{room-id}@conference.domain/{nick-name}' type='unavailable'></presence>
Server will send user's presence details to all user who have joined the room. The user, who will join the room after that, will not get details about that user. Here if you notice. Server has added a role related information to stanza. Same type of information have been added when user sends presence stanza for joining. This role defines what can this user do with this room. I will post more details about that afterwards.
<presence to='{user-jid}/{resource}' type='unavailable' from='{room-id}@conference.domain/{nick-name}'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item role='none' affiliation='none'></item>
</x>
</presence>
Let me know if you have any queries regarding this post.

References : http://xmpp.org/extensions/xep-0045.html/

Thursday, 19 July 2012

XMPP Chat room mechanism # Part-1

XMPP protocol provides specification for multi-user chatting(MUC). It is about service provider to implement it. You need to enable MUC from server side. Provider would also give facility to create persistent chat rooms. In terms of XMPP, chat room is known as conference. User can also create a new conference from client program.

When user is loggin in, he needs to ask for available service on server side. User need to send following XML to server.

<iq type='get' from='{user-jid/resource}' to='domain' id='discoitem1'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>

Server will send back all available services. Services will be sent as XML items. Each item contains service name and service JID.

<iq to='{user-jid/resource}' id='discoitem1' from='domain' type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item name='User Search' jid='search.domain'></item>
<item name='Socks 5 Bytestreams Proxy' jid='proxy.domain'></item>
<item name='Public Chatrooms' jid='conference.domain'></item>
<item name='Publish-Subscribe service' jid='pubsub.domain'></item>
</query>
</iq>

Once user gets all available services. It needs to be confirm whether conference service is there or not. If it is available user can ask for available chat rooms. These are all persistent chat rooms on the server.

<iq from='{user-jid/resource}' id='discoRooms' to='conference.domain' type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>

Server will send back all back all available chat rooms in following XML format.

<iq to='{user-jid/resource}' id='discoRooms' from='conference.domain' type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item name='university' jid='room1@conference.domain'></item>
<item name='country' jid='room2@conference.domain'></item>
</query>
</iq>

Now user is ready to join any room, he wants. User just needs to send one presence to the server. I will include more details about the same topic in next post. Stay in touch

Thursday, 12 July 2012

OpenFire Sub Group

XMPP has concept of chat rooms. A chat room is basically a conference room where users can discuss on some points. But Yahoo has provided room facility as social chatting rooms where any member can join the group and chat with other members. In this feature "nested chat rooms" are provided.

XMPP is not basically providing nested or child chat rooms. But twisting the logic little bit can make it possible with normal XMPP also.

Recall the concepts of domain name. Facebook has domain "facebook.com". Then they have started services of application. They bought sub domain. That became "apps.facebook.com".

Similarly in XMPP suppose you are creating chat room with name University. The JID will be something like "university@domain.com". Now you want different universities as sub chat room of this one. Just create sub University as "oxford.university@domain.com". The main logic that you need to take care is at the client side. You need to show this rooms in tree structure so that user will see it as sub chat room instead of independent chat room.

Creating chat rooms from admin panel is very easy. It is just a html form filling task. But for creating a chat room from client is real programming stuff. You can get information about it from this link. Remember in XMPP room has many types. If you want to keep the room alive forever. You will have to create persistent room. Other rooms will be removed as soon as the last occupant will leave the room.

Let me know if you have any queries regarding all this.



Tuesday, 19 June 2012

XMPP Plain Authentication

All of the communication between clientand server are done by passing XML. So it is important to getknowledge about XML first. Following are the links to get hands onXML.

For authenticating user to the xmppserver. Client needs to open a stream. XMPP works on stream base.

A stream is a sequence of data ofundetermined length. It's called a stream because it's like a streamof water that continues to flow. There's no definite end to it.

A better analogy might be a queue ofpeople waiting to get on a ride at an amusement park. As people areprocessed at the front (i.e. get on the roller coaster) more areadded at the back of the line. If it's a slow day the roller coastermay catch up with the end of the line and have to wait for people toboard. Other days there may always be people in line until the parkcloses. Each person is a discrete individual and must be put on theroller coaster or not put on the roller coaster. There are nohalf-people. There's always a definite number of people in linethough this number may change from moment to moment as people enterat the back of the line and exit from the front of the line. Althoughall the people are discrete, you'll sometimes have a family that mustbe put together in the same car. Thus although the individuals arediscrete, they aren't necessarily unrelated.

In Java a stream is composed ofdiscrete bytes. The bytes may represent chars or other kinds of data.They may come faster than you can handle them, or your thread mayblock while waiting for the next one to arrive. It often doesn'tmatter.

To open a stream in XMPP user needs tosend following XML to the server. Here because of you are using itwith client application it is necessary to ass jabber:client inxmlns.
<?xml version='1.0'?>

<stream:stream to='{server name}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
Server would open a stream for thatclient. Server must notify client with opened stream. If the streamhas been opened successfully. Server will also send starttls."starttls" is basically being used for securing thecommunication client-server.
      <xml encoding='UTF-8'version='1.0'></xml>

<stream:stream id='95360e39'from='{server name}' version='1.0' xml:lang='en' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>

</stream:stream>

<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
</starttls>
Server will also send details aboutmethods of communication which is called stream-features. All of thestream features are explained in details athttp://xmpp.org/registrar/stream-features.html. Following are someexamples of the stream-features.
      <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'></auth>

<register xmlns='http://jabber.org/features/iq-register'></register>

<stream:features>

<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'></starttls>
<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'></auth>

<register xmlns='http://jabber.org/features/iq-register'></register>

</stream:features>
In my case i have been using plainauthentication. For that you need to make sure that server is enabledto use plain authentication. This detail would have been given inmechanism XML in stream-features. Auth XML needs to have base64 valueof (username + password). As given below.
      <auth id='sasl2' xmlns="urn:ietf:params:xml:ns:xmpp-sasl"mechanism="PLAIN">"\0" + username + "\0"+ password</auth>
if user gets logged in successfully.Client will get a success XML in return. If authentication will befailed on server side. It will send back a failure XML. Examples aregiven below
 <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'></success>  
<not-authorized></not-authorized>

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<not-authorized></not-authorized>
</failure>

Wednesday, 6 June 2012

Chat Application Protocol Suggestion


        Using XMPP is the easiest way toimplement chat application for any of the platform. There are manyoptions available in market which can be used to develop a chatapplication. There are many limitations and drawbacks of using someother protocol for chatting.

        Following are some of the benefits ofusing XMPP.

Decentralization

        The architecture of the XMPP network is similar to email; anyone canrun their own XMPP server and there is no central master server.
Open standards
        TheInternetEngineering Task Force hasformalized XMPP as an approved instant messaging and presencetechnology under the name of XMPP (the latest specifications are RFC6120 andRFC6121).No royalties are required to implement support of thesespecifications and their development is not tied to a single vendor.
History
        XMPP technologies have been in usesince 1999. Multiple implementations of the XMPP standards exist forclients, servers, components, and code libraries.
Security
        XMPPservers can be isolated from the public XMPP network (e.g., on acompany intranet), and strong security (via SASLandTLS)has been built into the core XMPP specifications.
Flexibility
        Custom functionality can be builton top of XMPP; to maintain interoperability, common extensions aremanaged by the XMPP Software Foundation. XMPP applications beyond IMinclude groupchat, network management, content syndication,collaboration tools, file sharing, gaming, remote systems control andmonitoring, geolocation, middleware and cloud computing, VoIP andIdentity services.
Integration
        Most of the chatting applicationprovider are exposing their service as XMPP. So it is easy tointegrate your application with others. As you are using standardprotocol, any customer who ask you for application. You can easilymarket it. As well you can provide specifications to them. That willcut off your cost of development also.

Following link contains list ofall XMPP server providers.
XMPPServer http://xmpp.org/xmpp-software/servers/

References have been taken from wikipedia.