summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Young <consult.awy@gmail.com>2014-11-13 06:42:37 (GMT)
committerAlan Young <consult.awy@gmail.com>2015-04-10 06:50:58 (GMT)
commit7d2101b93b6253c3ea15b663f7f3dc385cb21364 (patch)
treed81338baf0d117e83cdc07f882cbedd9471e834d /src/com/isode/stroke/disco/CapsManager.java
parenta20ca7ba40d837abe228462be0aba5d32d6831e3 (diff)
downloadstroke-7d2101b93b6253c3ea15b663f7f3dc385cb21364.zip
stroke-7d2101b93b6253c3ea15b663f7f3dc385cb21364.tar.bz2
Checkpoint - A bunch of initial stuff for Android
MemoryStorages, Storages NickManager, NickResolver CryptoProvider, Hash, SafeByteArray, JavaCryptoProvider CapsInfoGenerator, CapsManager, CapsMemoryStorage, CapsProvider, CapsStorage, CapsInfo CapsInfoSerializer, CapsInfoParser ClientDiscoManager, DiscoInfoResponder, EntityCapsManager, EntityCapsProvider GetDiscoInfoRequest ChatState, Idle Presence, PayloadAddingPresenceSender, PresenceOracle, SubscriptionManager StatusSerializer, StatusShowSerializer, StatusParser, StatusShowParser, Replace, ReplaceParser, ReplaceSerializer SecurityLabel, SecurityLabelsCatalog, GetSecurityLabelsCatalogRequest VCard, GetVCardRequest, SetVCardRequest, VCardManager, VCardMemoryStorage, VCardStorage RosterMemoryStorage, RosterPushResponder, RosterStorage, SetRosterRequest XMPPRoster, XMPPRosterController, XMPPRosterImpl, XMPPRosterItem GetRosterRequest, SetResponder Add parsers and serializers for Idle, VCard, PrivateStorage & Stroage. Add parser for Subject. Add impromptu flag to MUCInvitation. Update copyrights. Change-Id: I9949f506b70e60b3a64f1dadde8f9b235b322e1d
Diffstat (limited to 'src/com/isode/stroke/disco/CapsManager.java')
-rw-r--r--src/com/isode/stroke/disco/CapsManager.java144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/com/isode/stroke/disco/CapsManager.java b/src/com/isode/stroke/disco/CapsManager.java
new file mode 100644
index 0000000..2e4c45b
--- /dev/null
+++ b/src/com/isode/stroke/disco/CapsManager.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.disco;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.isode.stroke.client.StanzaChannel;
+import com.isode.stroke.crypto.CryptoProvider;
+import com.isode.stroke.elements.CapsInfo;
+import com.isode.stroke.elements.DiscoInfo;
+import com.isode.stroke.elements.ErrorPayload;
+import com.isode.stroke.elements.Presence;
+import com.isode.stroke.jid.JID;
+import com.isode.stroke.queries.IQRouter;
+import com.isode.stroke.signals.Slot1;
+import com.isode.stroke.signals.Slot2;
+
+public class CapsManager extends CapsProvider {
+
+ private final IQRouter iqRouter;
+ private final CryptoProvider crypto;
+ private final CapsStorage capsStorage;
+ private boolean warnOnInvalidHash;
+ private Set<String> requestedDiscoInfos = new HashSet<String>();
+ private Set<CapsPair> failingCaps = new HashSet<CapsPair>();
+ private Map<String, Set<CapsPair>> fallbacks = new HashMap<String, Set<CapsPair>>();
+
+ private class CapsPair {
+ JID jid;
+ String node;
+
+ CapsPair(JID j, String n) {jid = j; node = n;}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof CapsPair)) return false;
+ CapsPair o1 = (CapsPair) o;
+ return jid.equals(o1.jid) && node.equals(o1.node);
+ }
+
+ @Override public int hashCode() {return jid.hashCode() * 5 + node.hashCode();}
+ }
+
+ public CapsManager(CapsStorage capsStorage, StanzaChannel stanzaChannel,
+ IQRouter iqRouter, CryptoProvider crypto) {
+ this.iqRouter = iqRouter;
+ this.crypto = crypto;
+ this.capsStorage = capsStorage;
+ this.warnOnInvalidHash = true;
+
+ stanzaChannel.onPresenceReceived.connect(new Slot1<Presence>() {
+ @Override
+ public void call(Presence p1) {
+ handlePresenceReceived(p1);
+ }
+ });
+ stanzaChannel.onAvailableChanged.connect(new Slot1<Boolean>() {
+ @Override
+ public void call(Boolean p1) {
+ handleStanzaChannelAvailableChanged(p1);
+ }
+ });
+ }
+
+ private void handlePresenceReceived(Presence presence) {
+ CapsInfo capsInfo = presence.getPayload(new CapsInfo());
+ if (capsInfo == null || !capsInfo.getHash().equals("sha-1")
+ || presence.getPayload(new ErrorPayload()) != null) {
+ return;
+ }
+ String hash = capsInfo.getVersion();
+ if (capsStorage.getDiscoInfo(hash) != null) {
+ return;
+ }
+ if (failingCaps.contains(new CapsPair(presence.getFrom(), hash))) {
+ return;
+ }
+ if (requestedDiscoInfos.contains(hash)) {
+ Set<CapsPair> fallback = fallbacks.get(hash);
+ if (fallback == null) fallbacks.put(hash, fallback = new HashSet<CapsPair>());
+ fallback.add(new CapsPair(presence.getFrom(), capsInfo.getNode()));
+ return;
+ }
+ requestDiscoInfo(presence.getFrom(), capsInfo.getNode(), hash);
+ }
+
+ private void handleStanzaChannelAvailableChanged(boolean available) {
+ if (available) {
+ failingCaps.clear();
+ fallbacks.clear();
+ requestedDiscoInfos.clear();
+ }
+ }
+
+ private void handleDiscoInfoReceived(final JID from, final String hash, DiscoInfo discoInfo, ErrorPayload error) {
+ requestedDiscoInfos.remove(hash);
+ if (error != null || discoInfo == null
+ || !new CapsInfoGenerator("", crypto).generateCapsInfo(discoInfo).getVersion().equals(hash)) {
+ if (warnOnInvalidHash && error == null && discoInfo != null) {
+// std.cerr << "Warning: Caps from " << from.toString() << " do not verify" << std.endl;
+ }
+ failingCaps.add(new CapsPair(from, hash));
+ Set<CapsPair> i = fallbacks.get(hash);
+ if (i != null && !i.isEmpty()) {
+ CapsPair fallbackAndNode = i.iterator().next();
+ i.remove(fallbackAndNode);
+ requestDiscoInfo(fallbackAndNode.jid, fallbackAndNode.node, hash);
+ }
+ return;
+ }
+ fallbacks.remove(hash);
+ capsStorage.setDiscoInfo(hash, discoInfo);
+ onCapsAvailable.emit(hash);
+ }
+
+ private void requestDiscoInfo(final JID jid, final String node, final String hash) {
+ GetDiscoInfoRequest request = GetDiscoInfoRequest.create(jid, node
+ + "#" + hash, iqRouter);
+ request.onResponse.connect(new Slot2<DiscoInfo, ErrorPayload>() {
+ @Override
+ public void call(DiscoInfo p1, ErrorPayload p2) {
+ handleDiscoInfoReceived(jid, hash, p1, p2);
+ }
+ });
+ requestedDiscoInfos.add(hash);
+ request.send();
+ }
+
+ @Override
+ DiscoInfo getCaps(String hash) {
+ return capsStorage.getDiscoInfo(hash);
+ }
+
+ // Mainly for testing purposes
+ void setWarnOnInvalidHash(boolean b) {
+ warnOnInvalidHash = b;
+ }
+
+}