Wednesday, May 13, 2009

Tell me what you chat with' Ill tell you who you are

So as I mentioned earlier in my previous post I was hoping to participate in Google Summer of Code 2009 and I started working on this sip-communicator project with higher expectations. I was so in to this and I studied a lot of materials to learn some technologies such as OGSI, XML and about various IM protocols. Some stuff I had to work with were completely new to me and I had never worked with IM protocols before. But anyway with time I gained some knowledge and experience to get the basic understanding about the project. So I got the Sip-communicator source code in eclipse and started coding. It was fun but time consuming. After analyzing the code and some playing around with it, I managed to get the basic implementation of the project done. I could see the name tag of the application software the other party is using on my GUI. But sadly after all these efforts the results were announced and I was not selected, but anyway everything happens for the good :). The next day I mailed my would-have-been mentor Yana Stamcheva. He said I was ranked second and the project was given out to the first.( Brett Geren was the accepted student. Congratulations!! ).

I though I should blog about what I did regarding this project. So if anybody is interested it might be a little help.:)

OK! so hears how I did it,

First I analyzed the data packets being received by Sip-Communicator (SC). I analyzed them by editing the SC code and using Wireshark (Its a good tool if you want to try capture packets). This is how I edited the code to test.

There is a package called net.java.sip.communicator.impl.protocols.* . And in it there are classes OperationSetBasicInstantMessagin....Impl. This ... represents the relevant protocol. These classes are extended from AbstractOperationSetBasicInstandMessaging abstract class. These classes are responsible for stuff dealing with incoming and outgoing IM messages of relevant protocols. So in OperationSetBasicInstantMessagingJabberImpl.java class there is an inner class called SmackMessageListner. This acts as a listener to incoming messages of Jabber(XMPP) protocol. This inner class implements org.jivesoftware.smack.PacketListner interface which provides the basic functionality of this protocol. So the object packet in this inner class represents the incoming data packet. Likewise other classes like this there will be similar inner classes. So the method toXml() in this interface will return the xml representation of the data packet. So now we can analyze the packet. I hope its clear. :)

This is the xml tag representing the user agent. from="jeewamp@gmail.com/gmail.7E1F24EA". Here /gmail.### means I used gmail chat. If its Google Talk it would be /Talk.###.

Now about the real coding.

For XMPP i used the inner class SmackMessageListner and it fires a messagerecieved event.

First i added a new constructor in public class MessageReceivedEvent

public String agent="";

public MessageReceivedEvent(Message source, Contact from, long timestamp,String pagent)
{
this(source, from, timestamp, CONVERSATION_MESSAGE_RECEIVED);
agent=pagent;
}


and added this method

public String getAgent()
{
return agent;
}


Then in public class OperationSetBasicInstantMessagingJabberImpl i added this method to get the user agent as a String (not perfect)

private String getUserAgent(String from){
String userAgent="";
StringTokenizer tokanize1=new StringTokenizer(from,"/");
tokanize1.nextToken();
userAgent=tokanize1.nextToken();
return userAgent;
}


in SmackMessageListener inner class in public void processPacket(Packet packet) i added

String agent=getUserAgent(packet.getFrom()); and added this

MessageReceivedEvent msgReceivedEvt
= new MessageReceivedEvent(
newMessage, sourceContact , System.currentTimeMillis(),agent);


fireMessageEvent(msgReceivedEvt);

So now the listeners to this event can retrieve the name of the agent

In public void messageReceived(MessageReceivedEvent evt) of public class ContactListPane listens to this event. so in this method i added(there is a final object chatPanel)

chatPanel.addLogo(evt.getAgent());

so in ChatPanel.java class the following method is there.

public void addLogo(String agent){
this.getChatWindow().setUserAgentLogo(agent);
}


this is the method that sets the logo of the user agent in the chat window.

so i modified public class ChatWindow accordingly

First I edited the constructor

public ChatWindow(){

.......

userAgentLogoPanel.setVisible(chatToolbarVisible);

northPanel.add(userAgentLogoPanel, BorderLayout.WEST);


}

and added this method

public void setUserAgentLogo(String agent)
{
this.userAgentLogoPanel.setLogo(agent);


}

and added this inner class

private class UserAgentLogoPanel extends JLayeredPane
{
private final JLabel agentNameLabel=new JLabel();


public UserAgentLogoPanel()
{
this.setLayout(null);


this.setPreferredSize(
new Dimension(  ChatContact.AVATAR_ICON_WIDTH + 10,
ChatContact.AVATAR_ICON_HEIGHT));


this.add(agentNameLabel, 1);
this.agentNameLabel.setBounds(4, 0, 200, 20);


}

public void setLogo(String agent)
{


this.agentNameLabel.setText(agent);

}

}

So when this is done you can see the name of the user agent the other party using. This is how it appears in my GUI.

I hope this would help someone.