Sends the initial xmpp presence packet after requesting and dispatching the roster.

deb-src-release-2.8.5426
Damian Minkov 12 years ago
parent f22bdef853
commit ea9c157612

@ -582,6 +582,22 @@ public void publishPresenceStatus(PresenceStatus status,
throw new IllegalArgumentException(status
+ " is not a valid Jabber status");
// if we got publish presence and we are still in a process of
// initializing the roster, just save the status and we will dispatch
// it when we are ready with the roster as sending initial presence
// is recommended to be done after requesting the roster, but we want
// to also dispatch it
synchronized(ssContactList.getRosterInitLock())
{
if(!ssContactList.isRosterInitialized())
{
// store it
ssContactList.setInitialStatus(status);
ssContactList.setInitialStatusMessage(statusMessage);
return;
}
}
if (status.equals(jabberStatusEnum.getStatus(JabberStatusEnum.OFFLINE)))
{
parentProvider.unregister();
@ -1050,13 +1066,13 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt)
// note that our listener will be added just before the
// one used in the Roster itself, but later we
// will wait for it to be ready
// (inside method XMPPConnection.getRoaster())
// (inside method XMPPConnection.getRoster())
parentProvider.getConnection().addPacketListener(
new ServerStoredListInit(),
new PacketTypeFilter(RosterPacket.class)
);
// will be used to store presence events till roaster is
// will be used to store presence events till roster is
// initialized
contactChangesListener = new ContactChangesListener();
@ -1799,9 +1815,9 @@ else if(response.getResponseCode()
/**
* Runnable that resolves our list against the server side roster.
* This thread is the one which will call getRoaster for the first time.
* And if roaster is currently processing will wait for it (the wait
* is internal into XMPPConnection.getRoaster method).
* This thread is the one which will call getRoster for the first time.
* And if roster is currently processing will wait for it (the wait
* is internal into XMPPConnection.getRoster method).
*/
private class ServerStoredListInit
implements Runnable,
@ -1817,16 +1833,16 @@ public void run()
// init ssList
ssContactList.init(contactChangesListener);
// as we have dispatched the contact list and Roaster is ready
// as we have dispatched the contact list and Roster is ready
// lets start the jingle nodes discovery
parentProvider.startJingleNodesDiscovery();
}
/**
* When roaster packet with no error is received we are ready to
* When roster packet with no error is received we are ready to
* to dispatch the contact list, doing it in different thread
* to avoid blocking xmpp packet receiving.
* @param packet the roaster packet
* @param packet the roster packet
*/
public void processPacket(Packet packet)
{

@ -1153,6 +1153,12 @@ private ConnectState connectAndLogin(
serviceName, proxy
);
// if we have OperationSetPersistentPresence skip sending initial
// presence while login is executed, the OperationSet will take care
// of it
if(getOperationSet(OperationSetPersistentPresence.class) != null)
confConn.setSendPresence(false);
confConn.setReconnectionAllowed(false);
boolean tlsRequired = loginStrategy.isTlsRequired();

@ -83,6 +83,26 @@ public class ServerStoredContactListJabberImpl
*/
private InfoRetreiver infoRetreiver = null;
/**
* Whether roster has been requested and dispatched.
*/
private boolean isRosterInitialized = false;
/**
* Lock object for the isRosterInitialized variable.
*/
private Object rosterInitLock = new Object();
/**
* The initial status saved.
*/
private PresenceStatus initialStatus = null;
/**
* The initial status message saved.
*/
private String initialStatusMessage = null;
/**
* Creates a ServerStoredContactList wrapper for the specified BuddyList.
*
@ -868,12 +888,50 @@ void init(OperationSetPersistentPresenceJabberImpl.ContactChangesListener
this.roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
initRoster();
// roster has been requested and dispatched, mark this
synchronized(rosterInitLock)
{
this.isRosterInitialized = true;
}
// no send initial status
sendInitialStatus();
presenceChangeListener.processStoredEvents();
rosterChangeListener = new ChangeListener();
this.roster.addRosterListener(rosterChangeListener);
}
/**
* Sends the initial presence to server. RFC 6121 says:
* a client SHOULD request the roster before sending initial presence
* We extend this and send it after we have dispatched the roster
*/
void sendInitialStatus()
{
// if we have initial status saved use it
if(initialStatus != null)
{
try
{
parentOperationSet.publishPresenceStatus(
initialStatus, initialStatusMessage);
}
catch(OperationFailedException ex)
{
logger.error("Error publishing initial presence", ex);
}
}
else
getParentProvider().getConnection()
.sendPacket(new Presence(Presence.Type.available));
// clean
initialStatus = null;
initialStatusMessage = null;
}
/**
* Cleanups references and listeners.
*/
@ -890,6 +948,11 @@ void cleanup()
this.rosterChangeListener = null;
this.roster = null;
synchronized(rosterInitLock)
{
this.isRosterInitialized = false;
}
}
/**
@ -954,11 +1017,11 @@ private synchronized void initRoster()
try
{
// process status if any that was received
// while the roaster reply packet was received and
// while the roster reply packet was received and
// added our presence listener
// Fixes a problem where Presence packets can be received
// before the roaster items packet, and we miss it,
// cause we add our listener after roaster is received
// before the roster items packet, and we miss it,
// cause we add our listener after roster is received
// and smack don't allow to add our listener earlier
parentOperationSet.firePresenceStatusChanged(
roster.getPresence(item.getUser()));
@ -1902,4 +1965,40 @@ public Iterator<Presence> getPresences(String user)
{
return roster.getPresences(user);
}
/**
* Returns whether roster is initialized.
* @return whether roster is initialized.
*/
boolean isRosterInitialized()
{
return isRosterInitialized;
}
/**
* The lock around isRosterInitialized variable.
* @return the lock around isRosterInitialized variable.
*/
Object getRosterInitLock()
{
return rosterInitLock;
}
/**
* Saves the initial status for later dispatching.
* @param initialStatus to be dispatched later.
*/
void setInitialStatus(PresenceStatus initialStatus)
{
this.initialStatus = initialStatus;
}
/**
* Saves the initial status message for later dispatching.
* @param initialStatusMessage to be dispatched later.
*/
void setInitialStatusMessage(String initialStatusMessage)
{
this.initialStatusMessage = initialStatusMessage;
}
}

Loading…
Cancel
Save