summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/isode/stroke/disco/DiscoServiceWalker.java104
1 files changed, 65 insertions, 39 deletions
diff --git a/src/com/isode/stroke/disco/DiscoServiceWalker.java b/src/com/isode/stroke/disco/DiscoServiceWalker.java
index 1b5c54e..39900aa 100644
--- a/src/com/isode/stroke/disco/DiscoServiceWalker.java
+++ b/src/com/isode/stroke/disco/DiscoServiceWalker.java
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
/*
* Copyright (c) 2015 Tarun Gupta.
* Licensed under the simplified BSD license.
@@ -20,15 +20,19 @@ import com.isode.stroke.disco.GetDiscoItemsRequest;
import com.isode.stroke.queries.IQRouter;
import com.isode.stroke.signals.Signal;
import com.isode.stroke.signals.Slot2;
import com.isode.stroke.signals.Signal2;
import com.isode.stroke.signals.SignalConnection;
import com.isode.stroke.base.NotNull;
+
import java.util.logging.Logger;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
+
import com.isode.stroke.base.NotNull;
/**
* Recursively walk service discovery trees to find all services offered.
* This stops on any disco item that's not reporting itself as a server.
*/
@@ -43,14 +47,24 @@ public class DiscoServiceWalker {
private Set<GetDiscoInfoRequest> pendingDiscoInfoRequests_ = new HashSet<GetDiscoInfoRequest>();
private Set<GetDiscoItemsRequest> pendingDiscoItemsRequests_ = new HashSet<GetDiscoItemsRequest>();
private Logger logger_ = Logger.getLogger(this.getClass().getName());
private SignalConnection onServiceFoundConnection;
private SignalConnection onWalkAbortedConnection;
private SignalConnection onWalkCompleteConnection;
- private SignalConnection onResponseDiscoInfoConnection;
- private SignalConnection onResponseDiscoItemsConnection;
+
+ /**
+ * The discoInfo.onResponse connections for each GetDiscoInfoRequest
+ */
+ private Map<GetDiscoInfoRequest,SignalConnection> onResponseDiscoInfoConnections =
+ new HashMap<GetDiscoInfoRequest,SignalConnection>();
+
+ /**
+ * The discoItems.onResponse connections for each GetDiscoItemsRequest
+ */
+ private Map<GetDiscoItemsRequest,SignalConnection> onResponseDiscoItemsConnections =
+ new HashMap<GetDiscoItemsRequest,SignalConnection>();
/** Emitted for each service found. */
public final Signal2<JID, DiscoInfo> onServiceFound = new Signal2<JID, DiscoInfo>();
/** Emitted when walking is aborted. */
public final Signal onWalkAborted = new Signal();
@@ -96,41 +110,44 @@ public class DiscoServiceWalker {
}
/**
* End the walk.
*/
public void endWalk() {
- if (active_) {
- logger_.fine("Ending walk to" + service_ + "\n");
- for (GetDiscoInfoRequest request : pendingDiscoInfoRequests_) {
- onResponseDiscoInfoConnection.disconnect();
- }
- for (GetDiscoItemsRequest request : pendingDiscoItemsRequests_) {
- onResponseDiscoItemsConnection.disconnect();
- }
- active_ = false;
- onWalkAborted.emit();
- }
+ if (active_) {
+ logger_.fine("Ending walk to" + service_ + "\n");
+ for (SignalConnection discoInfoConnection : onResponseDiscoInfoConnections.values()) {
+ discoInfoConnection.disconnect();
+ }
+ onResponseDiscoInfoConnections.clear();
+ for (SignalConnection discoItemsConnection : onResponseDiscoItemsConnections.values()) {
+ discoItemsConnection.disconnect();
+ }
+ onResponseDiscoItemsConnections.clear();
+ active_ = false;
+ onWalkAborted.emit();
+ }
}
public boolean isActive() {
return active_;
}
private void walkNode(JID jid) {
logger_.fine("Walking node" + jid + "\n");
servicesBeingSearched_.add(jid);
searchedServices_.add(jid);
final GetDiscoInfoRequest discoInfoRequest = GetDiscoInfoRequest.create(jid, iqRouter_);
- onResponseDiscoInfoConnection = discoInfoRequest.onResponse.connect(new Slot2<DiscoInfo, ErrorPayload>() {
+ SignalConnection connection = discoInfoRequest.onResponse.connect(new Slot2<DiscoInfo, ErrorPayload>() {
@Override
public void call(DiscoInfo info, ErrorPayload error) {
handleDiscoInfoResponse(info, error, discoInfoRequest);
}
});
+ onResponseDiscoInfoConnections.put(discoInfoRequest, connection);
pendingDiscoInfoRequests_.add(discoInfoRequest);
discoInfoRequest.send();
}
private void markNodeCompleted(JID jid) {
logger_.fine("Node completed " + jid + "\n");
@@ -152,12 +169,16 @@ public class DiscoServiceWalker {
if (!active_) {
return;
}
logger_.fine("Disco info response from " + request.getReceiver() + "\n");
+
+ SignalConnection connection = onResponseDiscoInfoConnections.remove(request);
+ connection.disconnect();
+
pendingDiscoInfoRequests_.remove(request);
if (error != null) {
handleDiscoError(request.getReceiver(), error);
return;
}
@@ -167,54 +188,59 @@ public class DiscoServiceWalker {
couldContainServices = true;
}
}
boolean completed = false;
if (couldContainServices) {
final GetDiscoItemsRequest discoItemsRequest = GetDiscoItemsRequest.create(request.getReceiver(), iqRouter_);
- onResponseDiscoItemsConnection = discoItemsRequest.onResponse.connect(new Slot2<DiscoItems, ErrorPayload>() {
+ SignalConnection discoItemsConnection = discoItemsRequest.onResponse.connect(new Slot2<DiscoItems, ErrorPayload>() {
@Override
public void call(DiscoItems item, ErrorPayload error) {
handleDiscoItemsResponse(item, error, discoItemsRequest);
}
});
+ onResponseDiscoItemsConnections.put(discoItemsRequest, discoItemsConnection);
pendingDiscoItemsRequests_.add(discoItemsRequest);
discoItemsRequest.send();
} else {
completed = true;
}
onServiceFound.emit(request.getReceiver(), info);
if (completed) {
markNodeCompleted(request.getReceiver());
}
}
private void handleDiscoItemsResponse(DiscoItems items, ErrorPayload error, GetDiscoItemsRequest request) {
- /* If we got canceled, don't do anything */
- if (!active_) {
- return;
- }
-
- logger_.fine("Received disco items from " + request.getReceiver() + "\n");
- pendingDiscoItemsRequests_.remove(request);
- if (error != null) {
- handleDiscoError(request.getReceiver(), error);
- return;
- }
- for (DiscoItems.Item item : items.getItems()) {
- if (item.getNode().isEmpty()) {
- /* Don't look at noded items. It's possible that this will exclude some services,
- * but I've never seen one in the wild, and it's an easy fix for not looping.
- */
- if(!searchedServices_.contains(item.getJID())) {
- logger_.fine("Received disco item " + item.getJID() + "\n");
- walkNode(item.getJID());
- }
- }
- }
- markNodeCompleted(request.getReceiver());
+ /* If we got canceled, don't do anything */
+ if (!active_) {
+ return;
+ }
+
+ logger_.fine("Received disco items from " + request.getReceiver() + "\n");
+
+ SignalConnection connection = onResponseDiscoItemsConnections.remove(request);
+ connection.disconnect();
+
+ pendingDiscoItemsRequests_.remove(request);
+ if (error != null) {
+ handleDiscoError(request.getReceiver(), error);
+ return;
+ }
+ for (DiscoItems.Item item : items.getItems()) {
+ if (item.getNode().isEmpty()) {
+ /* Don't look at noded items. It's possible that this will exclude some services,
+ * but I've never seen one in the wild, and it's an easy fix for not looping.
+ */
+ if(!searchedServices_.contains(item.getJID())) {
+ logger_.fine("Received disco item " + item.getJID() + "\n");
+ walkNode(item.getJID());
+ }
+ }
+ }
+ markNodeCompleted(request.getReceiver());
}
private void handleDiscoError(JID jid, ErrorPayload error) {
logger_.fine("Disco error from " + jid + "\n");
markNodeCompleted(jid);
}