diff options
Diffstat (limited to '')
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | build.gradle | 2 | ||||
-rw-r--r-- | src/main/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java | 247 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/parser/IqParser.java | 12 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 43 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/xml/Element.java | 5 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 82 |
8 files changed, 218 insertions, 178 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 64413709..0f081319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ###Changelog +####Version 1.6.1 +* fixed crashes + ####Version 1.6.0 * new multi-end-to-multi-end encryption method * redesigned chat bubbles diff --git a/build.gradle b/build.gradle index 94cce2ac..09ea1f6a 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 84 + versionCode 85 versionName "1.7.0-alpha" } diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 15d5bc25..7f07a39c 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -15,6 +15,8 @@ <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.NFC" /> + <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" /> + <application android:allowBackup="true" android:icon="@drawable/ic_launcher" diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index f3775b79..d700b644 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -307,21 +307,25 @@ public class AxolotlService { mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - Element item = mXmppConnectionService.getIqParser().getItem(packet); - Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); - if (deviceIds == null) { - deviceIds = new HashSet<Integer>(); - } - if (!deviceIds.contains(getOwnDeviceId())) { - deviceIds.add(getOwnDeviceId()); - IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist. Publishing: " + publish); - mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - // TODO: implement this! - } - }); + if (packet.getType() == IqPacket.TYPE.RESULT) { + Element item = mXmppConnectionService.getIqParser().getItem(packet); + Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); + if (deviceIds == null) { + deviceIds = new HashSet<Integer>(); + } + if (!deviceIds.contains(getOwnDeviceId())) { + deviceIds.add(getOwnDeviceId()); + IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist. Publishing: " + publish); + mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + // TODO: implement this! + } + }); + } + } else { + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing device ID:" + packet.findChild("error")); } } }); @@ -332,88 +336,92 @@ public class AxolotlService { mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet); - Map<Integer, ECPublicKey> keys = mXmppConnectionService.getIqParser().preKeyPublics(packet); - boolean flush = false; - if (bundle == null) { - Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet); - bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null); - flush = true; - } - if (keys == null) { - Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid prekeys:" + packet); - } - try { - boolean changed = false; - // Validate IdentityKey - IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair(); - if (flush || !identityKeyPair.getPublicKey().equals(bundle.getIdentityKey())) { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding own IdentityKey " + identityKeyPair.getPublicKey() + " to PEP."); - changed = true; + if (packet.getType() == IqPacket.TYPE.RESULT) { + PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet); + Map<Integer, ECPublicKey> keys = mXmppConnectionService.getIqParser().preKeyPublics(packet); + boolean flush = false; + if (bundle == null) { + Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet); + bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null); + flush = true; + } + if (keys == null) { + Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid prekeys:" + packet); } - - // Validate signedPreKeyRecord + ID - SignedPreKeyRecord signedPreKeyRecord; - int numSignedPreKeys = axolotlStore.loadSignedPreKeys().size(); try { - signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId()); - if (flush - || !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) - || !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) { + boolean changed = false; + // Validate IdentityKey + IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair(); + if (flush || !identityKeyPair.getPublicKey().equals(bundle.getIdentityKey())) { + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding own IdentityKey " + identityKeyPair.getPublicKey() + " to PEP."); + changed = true; + } + + // Validate signedPreKeyRecord + ID + SignedPreKeyRecord signedPreKeyRecord; + int numSignedPreKeys = axolotlStore.loadSignedPreKeys().size(); + try { + signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId()); + if (flush + || !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) + || !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) { + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP."); + signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); + axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); + changed = true; + } + } catch (InvalidKeyIdException e) { Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP."); signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); changed = true; } - } catch (InvalidKeyIdException e) { - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP."); - signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); - axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); - changed = true; - } - // Validate PreKeys - Set<PreKeyRecord> preKeyRecords = new HashSet<>(); - if (keys != null) { - for (Integer id : keys.keySet()) { - try { - PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id); - if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) { - preKeyRecords.add(preKeyRecord); + // Validate PreKeys + Set<PreKeyRecord> preKeyRecords = new HashSet<>(); + if (keys != null) { + for (Integer id : keys.keySet()) { + try { + PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id); + if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) { + preKeyRecords.add(preKeyRecord); + } + } catch (InvalidKeyIdException ignored) { } - } catch (InvalidKeyIdException ignored) { } } - } - int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size(); - if (newKeys > 0) { - List<PreKeyRecord> newRecords = KeyHelper.generatePreKeys( - axolotlStore.getCurrentPreKeyId() + 1, newKeys); - preKeyRecords.addAll(newRecords); - for (PreKeyRecord record : newRecords) { - axolotlStore.storePreKey(record.getId(), record); + int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size(); + if (newKeys > 0) { + List<PreKeyRecord> newRecords = KeyHelper.generatePreKeys( + axolotlStore.getCurrentPreKeyId() + 1, newKeys); + preKeyRecords.addAll(newRecords); + for (PreKeyRecord record : newRecords) { + axolotlStore.storePreKey(record.getId(), record); + } + changed = true; + Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding " + newKeys + " new preKeys to PEP."); } - changed = true; - Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding " + newKeys + " new preKeys to PEP."); - } - if (changed) { - IqPacket publish = mXmppConnectionService.getIqGenerator().publishBundles( - signedPreKeyRecord, axolotlStore.getIdentityKeyPair().getPublicKey(), - preKeyRecords, getOwnDeviceId()); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ": Bundle " + getOwnDeviceId() + " in PEP not current. Publishing: " + publish); - mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - // TODO: implement this! - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Published bundle, got: " + packet); - } - }); + if (changed) { + IqPacket publish = mXmppConnectionService.getIqGenerator().publishBundles( + signedPreKeyRecord, axolotlStore.getIdentityKeyPair().getPublicKey(), + preKeyRecords, getOwnDeviceId()); + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + ": Bundle " + getOwnDeviceId() + " in PEP not current. Publishing: " + publish); + mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + // TODO: implement this! + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Published bundle, got: " + packet); + } + }); + } + } catch (InvalidKeyException e) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage()); + return; } - } catch (InvalidKeyException e) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage()); - return; + } else { + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing Bundle:" + packet.findChild("error")); } } }); @@ -453,45 +461,52 @@ public class AxolotlService { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); - final IqParser parser = mXmppConnectionService.getIqParser(); - final List<PreKeyBundle> preKeyBundleList = parser.preKeys(packet); - final PreKeyBundle bundle = parser.bundle(packet); - if (preKeyBundleList.isEmpty() || bundle == null) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet); - fetchStatusMap.put(address, FetchStatus.ERROR); + if (packet.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); + final IqParser parser = mXmppConnectionService.getIqParser(); + final List<PreKeyBundle> preKeyBundleList = parser.preKeys(packet); + final PreKeyBundle bundle = parser.bundle(packet); + if (preKeyBundleList.isEmpty() || bundle == null) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet); + fetchStatusMap.put(address, FetchStatus.ERROR); + finish(); + return; + } + Random random = new Random(); + final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size())); + if (preKey == null) { + //should never happen + fetchStatusMap.put(address, FetchStatus.ERROR); + finish(); + return; + } + + final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), + preKey.getPreKeyId(), preKey.getPreKey(), + bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), + bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); + + axolotlStore.saveIdentity(address.getName(), bundle.getIdentityKey()); + + try { + SessionBuilder builder = new SessionBuilder(axolotlStore, address); + builder.process(preKeyBundle); + XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey().getFingerprint().replaceAll("\\s", "")); + sessions.put(address, session); + fetchStatusMap.put(address, FetchStatus.SUCCESS); + } catch (UntrustedIdentityException | InvalidKeyException e) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " + + e.getClass().getName() + ", " + e.getMessage()); + fetchStatusMap.put(address, FetchStatus.ERROR); + } + finish(); - return; - } - Random random = new Random(); - final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size())); - if (preKey == null) { - //should never happen + } else { fetchStatusMap.put(address, FetchStatus.ERROR); + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error")); finish(); return; } - - final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), - preKey.getPreKeyId(), preKey.getPreKey(), - bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), - bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); - - axolotlStore.saveIdentity(address.getName(), bundle.getIdentityKey()); - - try { - SessionBuilder builder = new SessionBuilder(axolotlStore, address); - builder.process(preKeyBundle); - XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey().getFingerprint().replaceAll("\\s", "")); - sessions.put(address, session); - fetchStatusMap.put(address, FetchStatus.SUCCESS); - } catch (UntrustedIdentityException | InvalidKeyException e) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " - + e.getClass().getName() + ", " + e.getMessage()); - fetchStatusMap.put(address, FetchStatus.ERROR); - } - - finish(); } }); } catch (InvalidJidException e) { diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index e74cb65c..4488eed8 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -236,7 +236,9 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { + if (packet.getType() == IqPacket.TYPE.ERROR) { + return; + } else if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { final Element query = packet.findChild("query"); // If this is in response to a query for the whole roster: if (packet.getType() == IqPacket.TYPE.RESULT) { @@ -306,15 +308,13 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); mXmppConnectionService.sendIqPacket(account, response, null); } else { - if ((packet.getType() == IqPacket.TYPE.GET) - || (packet.getType() == IqPacket.TYPE.SET)) { + if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) { final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); final Element error = response.addChild("error"); error.setAttribute("type", "cancel"); - error.addChild("feature-not-implemented", - "urn:ietf:params:xml:ns:xmpp-stanzas"); + error.addChild("feature-not-implemented","urn:ietf:params:xml:ns:xmpp-stanzas"); account.getXmppConnection().sendIqPacket(response, null); - } + } } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index e0f8d8d2..00729e2b 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -867,28 +867,31 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final Element query = packet.query(); - final List<Bookmark> bookmarks = new CopyOnWriteArrayList<>(); - final Element storage = query.findChild("storage", - "storage:bookmarks"); - if (storage != null) { - for (final Element item : storage.getChildren()) { - if (item.getName().equals("conference")) { - final Bookmark bookmark = Bookmark.parse(item, account); - bookmarks.add(bookmark); - Conversation conversation = find(bookmark); - if (conversation != null) { - conversation.setBookmark(bookmark); - } else if (bookmark.autojoin() && bookmark.getJid() != null) { - conversation = findOrCreateConversation( - account, bookmark.getJid(), true); - conversation.setBookmark(bookmark); - joinMuc(conversation); + if (packet.getType() == IqPacket.TYPE.RESULT) { + final Element query = packet.query(); + final List<Bookmark> bookmarks = new CopyOnWriteArrayList<>(); + final Element storage = query.findChild("storage", "storage:bookmarks"); + if (storage != null) { + for (final Element item : storage.getChildren()) { + if (item.getName().equals("conference")) { + final Bookmark bookmark = Bookmark.parse(item, account); + bookmarks.add(bookmark); + Conversation conversation = find(bookmark); + if (conversation != null) { + conversation.setBookmark(bookmark); + } else if (bookmark.autojoin() && bookmark.getJid() != null) { + conversation = findOrCreateConversation( + account, bookmark.getJid(), true); + conversation.setBookmark(bookmark); + joinMuc(conversation); + } } } } + account.setBookmarks(bookmarks); + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not fetch bookmarks"); } - account.setBookmarks(bookmarks); } }; sendIqPacket(account, iqPacket, callback); @@ -1952,10 +1955,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final IqPacket packet = XmppConnectionService.this.mIqGenerator .publishAvatarMetadata(avatar); sendIqPacket(account, packet, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, - IqPacket result) { + public void onIqPacketReceived(Account account, IqPacket result) { if (result.getType() == IqPacket.TYPE.RESULT) { if (account.setAvatar(avatar.getFilename())) { getAvatarService().clear(account); diff --git a/src/main/java/eu/siacs/conversations/xml/Element.java b/src/main/java/eu/siacs/conversations/xml/Element.java index dc5a68f6..7b4937b2 100644 --- a/src/main/java/eu/siacs/conversations/xml/Element.java +++ b/src/main/java/eu/siacs/conversations/xml/Element.java @@ -69,10 +69,9 @@ public class Element { public Element findChild(String name, String xmlns) { for (Element child : this.children) { - if (child.getName().equals(name) - && (child.getAttribute("xmlns").equals(xmlns))) { + if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) { return child; - } + } } return null; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index e2c9e25f..80f15f67 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -34,7 +34,6 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Map.Entry; import javax.net.ssl.HostnameVerifier; @@ -102,7 +101,7 @@ public class XmppConnection implements Runnable { private long lastConnect = 0; private long lastSessionStarted = 0; private int attempt = 0; - private final Map<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>(); + private final Hashtable<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>(); private OnPresencePacketReceived presenceListener = null; private OnJinglePacketReceived jingleListener = null; private OnIqPacketReceived unregisteredIqListener = null; @@ -649,8 +648,8 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final Element instructions = packet.query().findChild("instructions"); - if (packet.query().hasChild("username") + if (packet.getType() == IqPacket.TYPE.RESULT + && packet.query().hasChild("username") && (packet.query().hasChild("password"))) { final IqPacket register = new IqPacket(IqPacket.TYPE.SET); final Element username = new Element("username").setContent(account.getUsername()); @@ -677,6 +676,7 @@ public class XmppConnection implements Runnable { } }); } else { + final Element instructions = packet.query().findChild("instructions"); changeStatus(Account.State.REGISTRATION_FAILED); disconnect(true); Log.d(Config.LOGTAG, account.getJid().toBareJid() @@ -716,9 +716,11 @@ public class XmppConnection implements Runnable { sendPostBindInitialization(); } } else { + Log.d(Config.LOGTAG,account.getJid()+": disconnecting because of bind failure"); disconnect(true); } } else { + Log.d(Config.LOGTAG,account.getJid()+": disconnecting because of bind failure"); disconnect(true); } } @@ -726,16 +728,24 @@ public class XmppConnection implements Runnable { } private void clearIqCallbacks() { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing iq iq callbacks"); final IqPacket failurePacket = new IqPacket(IqPacket.TYPE.ERROR); + final ArrayList<OnIqPacketReceived> callbacks = new ArrayList<>(); synchronized (this.packetCallbacks) { - Iterator<Entry<String, Pair<IqPacket, OnIqPacketReceived>>> iterator = this.packetCallbacks.entrySet().iterator(); + if (this.packetCallbacks.size() == 0) { + return; + } + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing "+this.packetCallbacks.size()+" iq callbacks"); + final Iterator<Pair<IqPacket, OnIqPacketReceived>> iterator = this.packetCallbacks.values().iterator(); while (iterator.hasNext()) { - Entry<String, Pair<IqPacket, OnIqPacketReceived>> entry = iterator.next(); - entry.getValue().second.onIqPacketReceived(account, failurePacket); + Pair<IqPacket, OnIqPacketReceived> entry = iterator.next(); + callbacks.add(entry.second); iterator.remove(); } } + for(OnIqPacketReceived callback : callbacks) { + callback.onIqPacketReceived(account,failurePacket); + } + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": done clearing iq callbacks. "+this.packetCallbacks.size()+" left"); } private void sendStartSession() { @@ -747,6 +757,7 @@ public class XmppConnection implements Runnable { if (packet.getType() == IqPacket.TYPE.RESULT) { sendPostBindInitialization(); } else { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions"); disconnect(true); } } @@ -792,26 +803,29 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final List<Element> elements = packet.query().getChildren(); - final Info info = new Info(); - for (final Element element : elements) { - if (element.getName().equals("identity")) { - String type = element.getAttribute("type"); - String category = element.getAttribute("category"); - if (type != null && category != null) { - info.identities.add(new Pair<>(category,type)); + if (packet.getType() == IqPacket.TYPE.RESULT) { + final List<Element> elements = packet.query().getChildren(); + final Info info = new Info(); + for (final Element element : elements) { + if (element.getName().equals("identity")) { + String type = element.getAttribute("type"); + String category = element.getAttribute("category"); + if (type != null && category != null) { + info.identities.add(new Pair<>(category, type)); + } + } else if (element.getName().equals("feature")) { + info.features.add(element.getAttribute("var")); } - } else if (element.getName().equals("feature")) { - info.features.add(element.getAttribute("var")); } - } - disco.put(jid, info); - - if (account.getServer().equals(jid)) { - enableAdvancedStreamFeatures(); - for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) { - listener.onAdvancedStreamFeaturesAvailable(account); + disco.put(jid, info); + if (account.getServer().equals(jid)) { + enableAdvancedStreamFeatures(); + for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) { + listener.onAdvancedStreamFeaturesAvailable(account); + } } + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not query disco info for "+jid.toString()); } } }); @@ -836,14 +850,18 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { - final List<Element> elements = packet.query().getChildren(); - for (final Element element : elements) { - if (element.getName().equals("item")) { - final Jid jid = element.getAttributeAsJid("jid"); - if (jid != null && !jid.equals(account.getServer())) { - sendServiceDiscoveryInfo(jid); + if (packet.getType() == IqPacket.TYPE.RESULT) { + final List<Element> elements = packet.query().getChildren(); + for (final Element element : elements) { + if (element.getName().equals("item")) { + final Jid jid = element.getAttributeAsJid("jid"); + if (jid != null && !jid.equals(account.getServer())) { + sendServiceDiscoveryInfo(jid); + } } } + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not query disco items of "+server); } } }); @@ -877,6 +895,8 @@ public class XmppConnection implements Runnable { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": switching resource due to conflict (" + account.getResource() + ")"); + } else if (streamError != null) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString()); } } |