0
votes

I'm creating an instant messaging client using Smack 3.1.0 and Java. The problem I'm running in to has to do with sending messages to the user on a specific domain.

For example, I have two users, [email protected] and [email protected]. [email protected] logs in to XMPP through my IM client. [email protected] logs in to GChat through gmail.com AND a second time through pidgin. So now I have one instance of [email protected] and 2 instances of [email protected].

The way gmail works, if [email protected] sends a message to [email protected], the gmail and the pidgin client both get the initial message. But then if the gmail instance responds to the message, every message from then on only goes between [email protected] and the gmail instance of [email protected].

I would like to mimic this behavior with my IM client. I would think the way to do it would be to set up a Chat, send the initial IM to all instances of the recipient. Then I'd set up a MessageListener to listen for a response. When I get the response, I'd have to create a new chat, specifying the [email protected]/resource. But then I'd have to write the MessageListener twice. Any ideas? Here's some sample code that I'm using (the method AddText() simply appends the message to my conversation pane):

recipient = buddy;
setTitle("Instant Message - "+recipient);
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
    public void processMessage(Chat chat, Message msg) {
        //if(chat.getParticipant().indexOf('/')!=-1)
        addText(msg.getBody(), chat.getParticipant(), true);
    }
});

UPDATE I wanted to supplement the answer below with actual code that I used to make this work:

chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
    public void processMessage(Chat new_chat, Message msg) {
        if(msg.getFrom().replaceFirst("/.*", "").equals(recipient.getUser()))
        {
            if(buddy_resource==null || !msg.getFrom().replaceFirst(".*?/", "").equals(buddy_resource.getResource()))
            {
                buddy_resource = recipient.getResource(msg.getFrom().replaceFirst(".*?/", ""));
                chat = null;
                chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser()+"/"+buddy_resource.getResource(), new MessageListener(){
                    public void processMessage(Chat new_chat2, Message msg) {
                        addText(msg.getBody(), new_chat2.getParticipant(), true);
                    }
                });
            }
            addText(msg.getBody(), chat.getParticipant(), true);
        }
    }
});

To summarize, I send the first message to all resources of the recipient's address and wait for a response. When I get the response, I replace the current Chat object with a new one that specifies the individual resource that responded to the initial message. The code is a little messy with two different MessageListener objects that could probably be combined into a new class. But it works.

2

2 Answers

2
votes

So far I understood Message Carbon (XEP - 0280) will solve your problem. If you enable carbon it will distribute messages to all logged resources of a user. In your case if [email protected] send message to [email protected] it will be distributed to all logged resources of [email protected]. Here's a code sample using smack,

CarbonManager cm = CarbonManager.getInstanceFor(connection);
cm.enableCarbons();
cm.sendCarbonsEnabled();

First make sure that your server is supported Message Carbon. Then send message as usual.

0
votes

In your MessageListener why not always respond to the sender? I think you get it by calling something like msg.getSender() or getFrom() (I'm on mobile right now, cannot check)