mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-12-22 10:37:59 +01:00
Remove ConnectionListener from Socks5BytestreamManager
and use weak references. Disabling the Socks5Manager every time the connection is terminated, and re-enabling it when it got connected again causes unwanted side effects. Like adding a new feature to the ServiceDiscoveryManager causes an update of the entity's capabilities, which then triggers a new outgoing presence (announcing the new caps version). SMACK-671
This commit is contained in:
parent
385798f9ba
commit
35317a19bd
2 changed files with 26 additions and 42 deletions
|
@ -28,7 +28,7 @@ import java.util.Random;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jivesoftware.smack.AbstractConnectionClosedListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.FeatureNotSupportedException;
|
||||
|
@ -86,7 +86,7 @@ import org.jivesoftware.smackx.filetransfer.FileTransferManager;
|
|||
*
|
||||
* @author Henning Staib
|
||||
*/
|
||||
public final class Socks5BytestreamManager implements BytestreamManager {
|
||||
public final class Socks5BytestreamManager extends Manager implements BytestreamManager {
|
||||
|
||||
/*
|
||||
* create a new Socks5BytestreamManager and register a shutdown listener on every established
|
||||
|
@ -98,22 +98,6 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
public void connectionCreated(final XMPPConnection connection) {
|
||||
// create the manager for this connection
|
||||
Socks5BytestreamManager.getBytestreamManager(connection);
|
||||
|
||||
// register shutdown listener
|
||||
connection.addConnectionListener(new AbstractConnectionClosedListener() {
|
||||
|
||||
@Override
|
||||
public void connectionTerminated() {
|
||||
Socks5BytestreamManager.getBytestreamManager(connection).disableService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnectionSuccessful() {
|
||||
// re-create the manager for this connection
|
||||
Socks5BytestreamManager.getBytestreamManager(connection);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -128,9 +112,6 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
/* stores one Socks5BytestreamManager for each XMPP connection */
|
||||
private final static Map<XMPPConnection, Socks5BytestreamManager> managers = new HashMap<XMPPConnection, Socks5BytestreamManager>();
|
||||
|
||||
/* XMPP connection */
|
||||
private final XMPPConnection connection;
|
||||
|
||||
/*
|
||||
* assigns a user to a listener that is informed if a bytestream request for this user is
|
||||
* received
|
||||
|
@ -185,7 +166,6 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
if (manager == null) {
|
||||
manager = new Socks5BytestreamManager(connection);
|
||||
managers.put(connection, manager);
|
||||
manager.activate();
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
@ -196,8 +176,9 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* @param connection the XMPP connection
|
||||
*/
|
||||
private Socks5BytestreamManager(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
super(connection);
|
||||
this.initiationListener = new InitiationListener(this);
|
||||
activate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -282,7 +263,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* Using the file transfer API will automatically re-enable the SOCKS5 Bytestream feature.
|
||||
*/
|
||||
public synchronized void disableService() {
|
||||
|
||||
XMPPConnection connection = connection();
|
||||
// remove initiation packet listener
|
||||
connection.unregisterIQRequestHandler(initiationListener);
|
||||
|
||||
|
@ -299,7 +280,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
this.ignoredBytestreamRequests.clear();
|
||||
|
||||
// remove manager from static managers map
|
||||
managers.remove(this.connection);
|
||||
managers.remove(connection);
|
||||
|
||||
// shutdown local SOCKS5 proxy if there are no more managers for other connections
|
||||
if (managers.size() == 0) {
|
||||
|
@ -307,7 +288,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
}
|
||||
|
||||
// remove feature from service discovery
|
||||
ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(this.connection);
|
||||
ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
|
||||
// check if service discovery is not already disposed by connection shutdown
|
||||
if (serviceDiscoveryManager != null) {
|
||||
|
@ -423,7 +404,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
*/
|
||||
public Socks5BytestreamSession establishSession(String targetJID, String sessionID)
|
||||
throws IOException, InterruptedException, NoResponseException, SmackException, XMPPException{
|
||||
|
||||
XMPPConnection connection = connection();
|
||||
XMPPErrorException discoveryException = null;
|
||||
// check if target supports SOCKS5 Bytestream
|
||||
if (!supportsSocks5(targetJID)) {
|
||||
|
@ -452,7 +433,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
}
|
||||
|
||||
// compute digest
|
||||
String digest = Socks5Utils.createDigest(sessionID, this.connection.getUser(), targetJID);
|
||||
String digest = Socks5Utils.createDigest(sessionID, connection.getUser(), targetJID);
|
||||
|
||||
// prioritize last working SOCKS5 proxy if exists
|
||||
if (this.proxyPrioritizationEnabled && this.lastWorkingProxy != null) {
|
||||
|
@ -493,7 +474,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
|
||||
// build SOCKS5 client
|
||||
Socks5Client socks5Client = new Socks5ClientForInitiator(usedStreamHost, digest,
|
||||
this.connection, sessionID, targetJID);
|
||||
connection, sessionID, targetJID);
|
||||
|
||||
// establish connection to proxy
|
||||
Socket socket = socks5Client.getSocket(getProxyConnectionTimeout());
|
||||
|
@ -503,7 +484,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
|
||||
// negotiation successful, return the output stream
|
||||
return new Socks5BytestreamSession(socket, usedStreamHost.getJID().equals(
|
||||
this.connection.getUser()));
|
||||
connection.getUser()));
|
||||
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
|
@ -529,7 +510,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* @throws NotConnectedException
|
||||
*/
|
||||
private boolean supportsSocks5(String targetJID) throws NoResponseException, XMPPErrorException, NotConnectedException {
|
||||
return ServiceDiscoveryManager.getInstanceFor(connection).supportsFeature(targetJID, Bytestream.NAMESPACE);
|
||||
return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(targetJID, Bytestream.NAMESPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -542,12 +523,13 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* @throws NotConnectedException
|
||||
*/
|
||||
private List<String> determineProxies() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
||||
ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(this.connection);
|
||||
XMPPConnection connection = connection();
|
||||
ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
|
||||
List<String> proxies = new ArrayList<String>();
|
||||
|
||||
// get all items from XMPP server
|
||||
DiscoverItems discoverItems = serviceDiscoveryManager.discoverItems(this.connection.getServiceName());
|
||||
DiscoverItems discoverItems = serviceDiscoveryManager.discoverItems(connection.getServiceName());
|
||||
|
||||
// query all items if they are SOCKS5 proxies
|
||||
for (Item item : discoverItems.getItems()) {
|
||||
|
@ -590,6 +572,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* @return a list of stream hosts containing the IP address an the port
|
||||
*/
|
||||
private List<StreamHost> determineStreamHostInfos(List<String> proxies) {
|
||||
XMPPConnection connection = connection();
|
||||
List<StreamHost> streamHosts = new ArrayList<StreamHost>();
|
||||
|
||||
// add local proxy on first position if exists
|
||||
|
@ -636,7 +619,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* is not running
|
||||
*/
|
||||
private List<StreamHost> getLocalStreamHost() {
|
||||
|
||||
XMPPConnection connection = connection();
|
||||
// get local proxy singleton
|
||||
Socks5Proxy socks5Server = Socks5Proxy.getSocks5Proxy();
|
||||
|
||||
|
@ -704,7 +687,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
protected void replyRejectPacket(IQ packet) throws NotConnectedException {
|
||||
XMPPError xmppError = new XMPPError(XMPPError.Condition.not_acceptable);
|
||||
IQ errorIQ = IQ.createErrorResponse(packet, xmppError);
|
||||
this.connection.sendStanza(errorIQ);
|
||||
connection().sendStanza(errorIQ);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -713,7 +696,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
*/
|
||||
private void activate() {
|
||||
// register bytestream initiation packet listener
|
||||
connection.registerIQRequestHandler(initiationListener);
|
||||
connection().registerIQRequestHandler(initiationListener);
|
||||
|
||||
// enable SOCKS5 feature
|
||||
enableService();
|
||||
|
@ -723,7 +706,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* Adds the SOCKS5 Bytestream feature to the service discovery.
|
||||
*/
|
||||
private void enableService() {
|
||||
ServiceDiscoveryManager manager = ServiceDiscoveryManager.getInstanceFor(this.connection);
|
||||
ServiceDiscoveryManager manager = ServiceDiscoveryManager.getInstanceFor(connection());
|
||||
manager.addFeature(Bytestream.NAMESPACE);
|
||||
}
|
||||
|
||||
|
@ -745,7 +728,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
|
|||
* @return the XMPP connection
|
||||
*/
|
||||
protected XMPPConnection getConnection() {
|
||||
return this.connection;
|
||||
return connection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.jivesoftware.smackx.bytestreams.socks5;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
|
@ -41,7 +42,7 @@ import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
|
|||
class Socks5ClientForInitiator extends Socks5Client {
|
||||
|
||||
/* the XMPP connection used to communicate with the SOCKS5 proxy */
|
||||
private XMPPConnection connection;
|
||||
private WeakReference<XMPPConnection> connection;
|
||||
|
||||
/* the session ID used to activate SOCKS5 stream */
|
||||
private String sessionID;
|
||||
|
@ -61,7 +62,7 @@ class Socks5ClientForInitiator extends Socks5Client {
|
|||
public Socks5ClientForInitiator(StreamHost streamHost, String digest, XMPPConnection connection,
|
||||
String sessionID, String target) {
|
||||
super(streamHost, digest);
|
||||
this.connection = connection;
|
||||
this.connection = new WeakReference<>(connection);
|
||||
this.sessionID = sessionID;
|
||||
this.target = target;
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ class Socks5ClientForInitiator extends Socks5Client {
|
|||
Socket socket = null;
|
||||
|
||||
// check if stream host is the local SOCKS5 proxy
|
||||
if (this.streamHost.getJID().equals(this.connection.getUser())) {
|
||||
if (this.streamHost.getJID().equals(this.connection.get().getUser())) {
|
||||
Socks5Proxy socks5Server = Socks5Proxy.getSocks5Proxy();
|
||||
socket = socks5Server.getSocket(this.digest);
|
||||
if (socket == null) {
|
||||
|
@ -109,7 +110,7 @@ class Socks5ClientForInitiator extends Socks5Client {
|
|||
private void activate() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
||||
Bytestream activate = createStreamHostActivation();
|
||||
// if activation fails #nextResultOrThrow() throws an exception
|
||||
connection.createPacketCollectorAndSend(activate).nextResultOrThrow();
|
||||
connection.get().createPacketCollectorAndSend(activate).nextResultOrThrow();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue