Transports do not support "subscribe" or "unsubscribe" stanzas incoming from a client.

Description

The BaseTransport class contains the following code, for dealing with incoming subscribe or unsubscribe presence stanzas:

else if (packet.getType() == Presence.Type.subscribe) {
// For the time being, we are going to lie to the end user that the subscription has worked.
Presence p = new Presence();
p.setType(Presence.Type.subscribed);
p.setTo(from);
p.setFrom(to);
sendPacket(p);
}

I am testing the XMPP transports, and this is causing my tests to fail - ie, clients never receive status updates from buddies that they have subscribed to because, although they believe that they have successfully subscribed, they are in fact not subscribed at all.

I have included a patch that I am currently using to fix the issue, although it is only implemented for the XMPP transport (other transports will need to implement this functionality themselves). If the patch is applied, transports will no longer send these "lying" packets.

  1.  

    1.  

      1. Eclipse Workspace Patch 1.0
        #P openfire
        Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/simple/SimpleSession.java
        ===================================================================

      • src/plugins/kraken/src/java/net/sf/kraken/protocols/simple/SimpleSession.java (revision 190)
        +++ src/plugins/kraken/src/java/net/sf/kraken/protocols/simple/SimpleSession.java (working copy)
        @@ -1405,4 +1405,22 @@
        Log.debug(new String(log));
        }
        }
        +
        + /**
        + * {@inheritDoc}
        + */
        + @Override
        + public void sendSubscribeRequest(SimpleBuddy buddy) {
        + // TODO Auto-generated method stub
        +
        + }
        +
        + /**
        + * {@inheritDoc}
        + */
        + @Override
        + public void sendUnsubscribeRequest(SimpleBuddy buddy) {
        + // TODO Auto-generated method stub
        +
        + }
        }
        Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/myspaceim/MySpaceIMSession.java
        ===================================================================

      • src/plugins/kraken/src/java/net/sf/kraken/protocols/myspaceim/MySpaceIMSession.java (revision 190)
        +++ src/plugins/kraken/src/java/net/sf/kraken/protocols/myspaceim/MySpaceIMSession.java (working copy)
        @@ -198,4 +198,22 @@
        connection.sendPacket(msg);
        }


+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(MySpaceIMBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(MySpaceIMBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/gadugadu/GaduGaduSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/gadugadu/GaduGaduSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/gadugadu/GaduGaduSession.java (working copy)
@@ -316,4 +316,22 @@
}
}

+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(GaduGaduBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(GaduGaduBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/BaseTransport.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/BaseTransport.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/BaseTransport.java (working copy)
@@ -10,6 +10,19 @@

package net.sf.kraken;

+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+
import net.sf.kraken.avatars.Avatar;
import net.sf.kraken.muc.BaseMUCTransport;
import net.sf.kraken.permissions.PermissionManager;
@@ -20,7 +33,12 @@
import net.sf.kraken.session.TransportSession;
import net.sf.kraken.session.TransportSessionManager;
import net.sf.kraken.session.cluster.TransportSessionRouter;
-import net.sf.kraken.type.*;
+import net.sf.kraken.type.ChatStateType;
+import net.sf.kraken.type.NameSpace;
+import net.sf.kraken.type.PresenceType;
+import net.sf.kraken.type.SupportedFeature;
+import net.sf.kraken.type.TransportLoginStatus;
+import net.sf.kraken.type.TransportType;
import net.sf.kraken.util.chatstate.ChatStateChangeEvent;
import net.sf.kraken.util.chatstate.ChatStateEventListener;
import net.sf.kraken.util.chatstate.ChatStateEventSource;
@@ -41,27 +59,33 @@
import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.roster.Roster;
-import org.jivesoftware.openfire.roster.*;
+import org.jivesoftware.openfire.roster.RosterEventDispatcher;
+import org.jivesoftware.openfire.roster.RosterEventListener;
+import org.jivesoftware.openfire.roster.RosterItem;
+import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
+import org.jivesoftware.openfire.vcard.VCardEventDispatcher;
import org.jivesoftware.openfire.vcard.VCardListener;
-import org.jivesoftware.openfire.vcard.VCardEventDispatcher;
-import org.jivesoftware.util.*;
+import org.jivesoftware.util.Base64;
+import org.jivesoftware.util.JiveGlobals;
+import org.jivesoftware.util.LocaleUtils;
+import org.jivesoftware.util.NotFoundException;
+import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.cache.CacheFactory;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentManager;
-import org.xmpp.packet.*;
+import org.xmpp.packet.IQ;
+import org.xmpp.packet.JID;
+import org.xmpp.packet.Message;
+import org.xmpp.packet.Packet;
+import org.xmpp.packet.PacketError;
import org.xmpp.packet.PacketError.Condition;
+import org.xmpp.packet.Presence;

-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.concurrent.locks.Lock;
-
/**

  • Base class of all transport implementations.
    *
    @@ -499,20 +523,48 @@
    }
    }
    else if (packet.getType() == Presence.Type.subscribe) {

  • // For the time being, we are going to lie to the end user that the subscription has worked.

  • Presence p = new Presence();

  • p.setType(Presence.Type.subscribed);

  • p.setTo(from);

  • p.setFrom(to);

  • sendPacket(p);
    + if( session.isLoggedIn() ) {
    + try {
    + TransportBuddy buddy = session.getBuddyManager().getBuddy(to);
    + buddy.sendSubscribeRequest();
    + }
    + catch ( NotFoundException e ) {
    + // User was not found so send an error presence.
    + // User was not found so send an error presence
    + Presence p = new Presence();
    + p.setTo(from);
    + p.setFrom(to);
    + // TODO: this causes some ugliness in some clients
    +// p.setError(PacketError.Condition.forbidden);
    + // If the user tries to check on a buddy before we are totally logged in
    + // and have the full list, this gets thrown for legit contacts.
    + // We'll send unavailable for now.
    + p.setType(Presence.Type.unavailable);
    + sendPacket(p);
    + }
    + }
    }
    else if (packet.getType() == Presence.Type.unsubscribe) {

  • // For the time being, we are going to lie to the end user that the unsubscription has worked.

  • Presence p = new Presence();

  • p.setType(Presence.Type.unsubscribed);

  • p.setTo(from);

  • p.setFrom(to);

  • sendPacket(p);
    + if( session.isLoggedIn() ) {
    + try {
    + TransportBuddy buddy = session.getBuddyManager().getBuddy(to);
    + buddy.sendUnsubscribeRequest();
    + }
    + catch ( NotFoundException e ) {
    + // User was not found so send an error presence.
    + // User was not found so send an error presence
    + Presence p = new Presence();
    + p.setTo(from);
    + p.setFrom(to);
    + // TODO: this causes some ugliness in some clients
    +// p.setError(PacketError.Condition.forbidden);
    + // If the user tries to check on a buddy before we are totally logged in
    + // and have the full list, this gets thrown for legit contacts.
    + // We'll send unavailable for now.
    + p.setType(Presence.Type.unavailable);
    + sendPacket(p);
    + }
    + }
    }
    else if (packet.getType() == Presence.Type.subscribed) {
    // let the legacy domain know that the contact was accepted.
    Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/qq/QQSession.java
    ===================================================================

    •  

      • src/plugins/kraken/src/java/net/sf/kraken/protocols/qq/QQSession.java (revision 190)
        +++ src/plugins/kraken/src/java/net/sf/kraken/protocols/qq/QQSession.java (working copy)
        @@ -216,4 +216,22 @@
        return qqclient;
        }


+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(QQBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(QQBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/yahoo/YahooSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/yahoo/YahooSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/yahoo/YahooSession.java (working copy)
@@ -20,7 +20,11 @@
import net.sf.kraken.pseudoroster.PseudoRosterManager;
import net.sf.kraken.registration.Registration;
import net.sf.kraken.session.TransportSession;
-import net.sf.kraken.type.*;
+import net.sf.kraken.type.ChatStateType;
+import net.sf.kraken.type.ConnectionFailureReason;
+import net.sf.kraken.type.PresenceType;
+import net.sf.kraken.type.SupportedFeature;
+import net.sf.kraken.type.TransportLoginStatus;

import org.apache.log4j.Logger;
import org.jivesoftware.openfire.user.UserNotFoundException;
@@ -445,4 +449,22 @@
return yahooSession;
}

+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(YahooBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(YahooBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/roster/TransportBuddy.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/roster/TransportBuddy.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/roster/TransportBuddy.java (working copy)
@@ -10,7 +10,14 @@

package net.sf.kraken.roster;

+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
import net.sf.kraken.avatars.Avatar;
+import net.sf.kraken.session.TransportSession;
import net.sf.kraken.type.NameSpace;
import net.sf.kraken.type.PresenceType;

@@ -24,12 +31,6 @@
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;

-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-
/**

  • Transport Buddy.
    *
    @@ -606,4 +607,20 @@
    return "{Buddy: "this.jid" (Nickname: "this.nickname") (Groups: "this.groups")}";
    }


+ /**
+ * @param from
+ */
+ public void sendUnsubscribeRequest() {
+ TransportSession session = getManager().getSession();
+ session.sendUnsubscribeRequest( this );
+ }
+
+ /**
+ * @param from
+ */
+ public void sendSubscribeRequest() {
+ TransportSession session = getManager().getSession();
+ session.sendSubscribeRequest( this );
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/session/TransportSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/session/TransportSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/session/TransportSession.java (working copy)
@@ -10,6 +10,11 @@

package net.sf.kraken.session;

+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+
import net.sf.kraken.BaseTransport;
import net.sf.kraken.avatars.Avatar;
import net.sf.kraken.muc.MUCTransportSessionManager;
@@ -17,7 +22,12 @@
import net.sf.kraken.registration.RegistrationHandler;
import net.sf.kraken.roster.TransportBuddy;
import net.sf.kraken.roster.TransportBuddyManager;
-import net.sf.kraken.type.*;
+import net.sf.kraken.type.ChatStateType;
+import net.sf.kraken.type.ConnectionFailureReason;
+import net.sf.kraken.type.NameSpace;
+import net.sf.kraken.type.PresenceType;
+import net.sf.kraken.type.SupportedFeature;
+import net.sf.kraken.type.TransportLoginStatus;

import org.apache.log4j.Logger;
import org.dom4j.Element;
@@ -29,13 +39,12 @@
import org.jivesoftware.util.Base64;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.NotFoundException;
-import org.xmpp.packet.*;
+import org.xmpp.packet.IQ;
+import org.xmpp.packet.JID;
+import org.xmpp.packet.Message;
+import org.xmpp.packet.Packet;
+import org.xmpp.packet.Presence;

-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.concurrent.ConcurrentHashMap;
-
/**

  • Interface for a transport session.
    *
    @@ -957,4 +966,14 @@
    getTransport().getMUCTransport().cancelPendingRequest(getJID(), getTransport().getMUCTransport().convertIDToJID(room, null), NameSpace.DISCO_ITEMS);
    }


+ /**
+ * @param buddy
+ */
+ public abstract void sendSubscribeRequest(B buddy);
+
+ /**
+ * @param buddy
+ */
+ public abstract void sendUnsubscribeRequest(B buddy);
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/sametime/SameTimeSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/sametime/SameTimeSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/sametime/SameTimeSession.java (working copy)
@@ -239,4 +239,22 @@
public void updateStatus(PresenceType presenceType, String verboseStatus) {
}

+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(SameTimeBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(SameTimeBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/facebook/FacebookSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/facebook/FacebookSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/facebook/FacebookSession.java (working copy)
@@ -216,4 +216,22 @@
}
}

+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(FacebookBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(FacebookBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/msn/MSNSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/msn/MSNSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/msn/MSNSession.java (working copy)
@@ -517,4 +517,22 @@
}
}

+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(MSNBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(MSNBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/xmpp/XMPPSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/xmpp/XMPPSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/xmpp/XMPPSession.java (working copy)
@@ -26,12 +26,24 @@
import net.sf.kraken.protocols.xmpp.packet.VCardUpdateExtension;
import net.sf.kraken.registration.Registration;
import net.sf.kraken.session.TransportSession;
-import net.sf.kraken.type.*;
+import net.sf.kraken.type.ChatStateType;
+import net.sf.kraken.type.ConnectionFailureReason;
+import net.sf.kraken.type.PresenceType;
+import net.sf.kraken.type.SupportedFeature;
+import net.sf.kraken.type.TransportLoginStatus;
+import net.sf.kraken.type.TransportType;

import org.apache.log4j.Logger;
import org.jivesoftware.openfire.user.UserNotFoundException;
-import org.jivesoftware.smack.*;
+import org.jivesoftware.smack.Chat;
+import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.Roster.SubscriptionMode;
+import org.jivesoftware.smack.RosterEntry;
+import org.jivesoftware.smack.RosterGroup;
+import org.jivesoftware.smack.SASLAuthentication;
+import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.OrFilter;
import org.jivesoftware.smack.filter.PacketExtensionFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
@@ -665,7 +677,27 @@
// we'll let the roster listener take care of this though.
conn.getRoster().reload();
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest( XMPPBuddy buddy ) {
+ Presence p = new Presence( Presence.Type.subscribe );
+ p.setTo( getTransport().convertJIDToID(buddy.getJID()));
+ conn.sendPacket( p );
+ }

+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest( XMPPBuddy buddy ) {
+ Presence p = new Presence( Presence.Type.unsubscribe );
+ p.setFrom( buddy.getJID().toBareJID() );
+ conn.sendPacket( p );
+ }
+
private class MailCheck extends TimerTask {
/**

  • Check GMail for new mail.
    Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/oscar/OSCARSession.java
    ===================================================================

    •  

      • src/plugins/kraken/src/java/net/sf/kraken/protocols/oscar/OSCARSession.java (revision 190)
        +++ src/plugins/kraken/src/java/net/sf/kraken/protocols/oscar/OSCARSession.java (working copy)
        @@ -567,4 +567,22 @@
        }
        }


+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(OSCARBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(OSCARBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
}
Index: src/plugins/kraken/src/java/net/sf/kraken/protocols/irc/IRCSession.java
===================================================================
— src/plugins/kraken/src/java/net/sf/kraken/protocols/irc/IRCSession.java (revision 190)
+++ src/plugins/kraken/src/java/net/sf/kraken/protocols/irc/IRCSession.java (working copy)
@@ -24,7 +24,11 @@
import net.sf.kraken.registration.Registration;
import net.sf.kraken.roster.TransportBuddy;
import net.sf.kraken.session.TransportSession;
-import net.sf.kraken.type.*;
+import net.sf.kraken.type.ChatStateType;
+import net.sf.kraken.type.ConnectionFailureReason;
+import net.sf.kraken.type.NameSpace;
+import net.sf.kraken.type.PresenceType;
+import net.sf.kraken.type.TransportLoginStatus;
import net.sf.kraken.util.StringUtils;

import org.apache.log4j.Logger;
@@ -371,5 +375,23 @@
}
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendSubscribeRequest(IRCBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void sendUnsubscribeRequest(IRCBuddy buddy) {
+ // TODO Auto-generated method stub
+
+ }

}

Environment

None

Activity

Show:
John Doe
October 14, 2010, 3:17 PM

It has come to my attention that although my fix allows the addition of contacts via the XMPP transport, it results in a further problem wherein if you send out one request to add a contact (via pidgin, smack, etc), the user you want to add receives two requests. I have figured out why this happens and fixed the issue locally, but it required some more in-depth changes.

The problem is this: When you "add a contact" in XMPP, this is really two packets:
1. <iq> roster packet, which adds the user to your roster.
2. <presence> subscribe packet, which is meant for consumption by the target user - this is the actual "request" that they see.

The patch I wrote intercepts <presence> packets and forwards them along the XMPP transport. However, in the XMPPSession.addContact() method (which is called when Kraken encounters the iq packet), we are calling Roster.createEntry - which actually performs BOTH of the abovementioned operations; sending the iq packet AND the presence packet. Then when my patch code is called as a result of the presence packet, that causes Kraken to send a second subscribe request.

The solution I used is, instead of calling Roster.createEntry, XMPPSession.addContact should craft a custom RosterPacket, and send it manually. However, since the XMPPBuddy objects that are created require RosterEntry objects as a parameter to their constructor (and RosterEntry objects are returned by calls to Roster.createEntry), this solution requires some further changes - ie, modifying XMPPBuddy so that it doesn't use the RosterEntry objects (which I think is okay - these don't actually seem to be used at all anyway).

Here's the modified XMPPSession.addContact method. The other changes I made are pretty trivial:

/**

  • @see net.sf.kraken.session.TransportSession#addContact(org.xmpp.packet.JID, String, java.util.ArrayList)
    */
    @Override
    public void addContact(JID jid, String nickname, ArrayList<String> groups) {
    String mail = getTransport().convertJIDToID(jid);


// Create a roster packet manually - using Roster.createEntry() causes us to send out both
// roster.set AND presence.subscribe packets.
RosterPacket rosterPacket = new RosterPacket();
rosterPacket.setType(IQ.Type.SET);
RosterPacket.Item item = new RosterPacket.Item(mail, nickname);
for ( String group : groups ) {
item.addGroupName(group);
}
rosterPacket.addRosterItem( item );
conn.sendPacket(rosterPacket);
getBuddyManager().storeBuddy(new XMPPBuddy(getBuddyManager(), mail, nickname, groups));
}

daniel vultur
September 22, 2010, 4:29 PM

Thank you! I'm going to investigate this probably after 1.1.3 – trying to take down a small number of issues before I release it and don't want to make any changes at the moment that change "core functionality". I'll aim to look at it for 1.1.4.

Notes:
See this thread: http://kraken.blathersource.org/node/399

Should be able to reproduce issue by doing the following in Pidgin:
1. Create two users on the gateway server, each with a registration via an XMPP transport to another server (which I am calling the "target").

2. Use pidgin to login both accounts on the gateway.

3. Have user1 add user2, as "user2\40target@xmpp.gateway"

4. When user2 receives the subscription request, authorize it. When the box pops up so that user2 can add user1 as a contact as well, accept the defaults (ie: adding "user1\40target@xmpp.gateway"). Nickname the contact "user1".

5. Notice that the newly added user1 entry shows up as offline, and no subscription request is received by the signed on user1 account. At this point, user1 should receive a subscription request, but it never happens.

John Doe
September 22, 2010, 2:28 PM

Patch which I believe fixes this issue.

Assignee

Daniel Henninger

Reporter

John Doe

Labels

None

Expected Effort

None

Ignite Forum URL

None

Components

Fix versions

Priority

Major