Merge branch 'master' into development

This commit is contained in:
Daniel Gultsch 2015-08-23 13:57:14 +02:00
commit b0710cdf04
8 changed files with 221 additions and 181 deletions

View file

@ -1,5 +1,8 @@
###Changelog ###Changelog
####Version 1.6.1
* fixed crashes
####Version 1.6.0 ####Version 1.6.0
* new multi-end-to-multi-end encryption method * new multi-end-to-multi-end encryption method
* redesigned chat bubbles * redesigned chat bubbles

View file

@ -48,7 +48,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 21 targetSdkVersion 21
versionCode 84 versionCode 85
versionName "1.7.0-alpha" versionName "1.7.0-alpha"
} }

View file

@ -15,6 +15,8 @@
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"

View file

@ -307,21 +307,25 @@ public class AxolotlService {
mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
Element item = mXmppConnectionService.getIqParser().getItem(packet); if (packet.getType() == IqPacket.TYPE.RESULT) {
Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); Element item = mXmppConnectionService.getIqParser().getItem(packet);
if (deviceIds == null) { Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
deviceIds = new HashSet<Integer>(); if (deviceIds == null) {
} deviceIds = new HashSet<Integer>();
if (!deviceIds.contains(getOwnDeviceId())) { }
deviceIds.add(getOwnDeviceId()); if (!deviceIds.contains(getOwnDeviceId())) {
IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); deviceIds.add(getOwnDeviceId());
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist. Publishing: " + publish); IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds);
mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Own device " + getOwnDeviceId() + " not in PEP devicelist. Publishing: " + publish);
@Override mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() {
public void onIqPacketReceived(Account account, IqPacket packet) { @Override
// TODO: implement this! 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() { mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet); if (packet.getType() == IqPacket.TYPE.RESULT) {
Map<Integer, ECPublicKey> keys = mXmppConnectionService.getIqParser().preKeyPublics(packet); PreKeyBundle bundle = mXmppConnectionService.getIqParser().bundle(packet);
boolean flush = false; Map<Integer, ECPublicKey> keys = mXmppConnectionService.getIqParser().preKeyPublics(packet);
if (bundle == null) { boolean flush = false;
Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet); if (bundle == null) {
bundle = new PreKeyBundle(-1, -1, -1, null, -1, null, null, null); Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received invalid bundle:" + packet);
flush = true; 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); 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;
} }
// Validate signedPreKeyRecord + ID
SignedPreKeyRecord signedPreKeyRecord;
int numSignedPreKeys = axolotlStore.loadSignedPreKeys().size();
try { try {
signedPreKeyRecord = axolotlStore.loadSignedPreKey(bundle.getSignedPreKeyId()); boolean changed = false;
if (flush // Validate IdentityKey
|| !bundle.getSignedPreKey().equals(signedPreKeyRecord.getKeyPair().getPublicKey()) IdentityKeyPair identityKeyPair = axolotlStore.getIdentityKeyPair();
|| !Arrays.equals(bundle.getSignedPreKeySignature(), signedPreKeyRecord.getSignature())) { 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."); Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Adding new signedPreKey with ID " + (numSignedPreKeys + 1) + " to PEP.");
signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1); signedPreKeyRecord = KeyHelper.generateSignedPreKey(identityKeyPair, numSignedPreKeys + 1);
axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord); axolotlStore.storeSignedPreKey(signedPreKeyRecord.getId(), signedPreKeyRecord);
changed = true; 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 // Validate PreKeys
Set<PreKeyRecord> preKeyRecords = new HashSet<>(); Set<PreKeyRecord> preKeyRecords = new HashSet<>();
if (keys != null) { if (keys != null) {
for (Integer id : keys.keySet()) { for (Integer id : keys.keySet()) {
try { try {
PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id); PreKeyRecord preKeyRecord = axolotlStore.loadPreKey(id);
if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) { if (preKeyRecord.getKeyPair().getPublicKey().equals(keys.get(id))) {
preKeyRecords.add(preKeyRecord); preKeyRecords.add(preKeyRecord);
}
} catch (InvalidKeyIdException ignored) {
} }
} catch (InvalidKeyIdException ignored) {
} }
} }
} int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size();
int newKeys = NUM_KEYS_TO_PUBLISH - preKeyRecords.size(); if (newKeys > 0) {
if (newKeys > 0) { List<PreKeyRecord> newRecords = KeyHelper.generatePreKeys(
List<PreKeyRecord> newRecords = KeyHelper.generatePreKeys( axolotlStore.getCurrentPreKeyId() + 1, newKeys);
axolotlStore.getCurrentPreKeyId() + 1, newKeys); preKeyRecords.addAll(newRecords);
preKeyRecords.addAll(newRecords); for (PreKeyRecord record : newRecords) {
for (PreKeyRecord record : newRecords) { axolotlStore.storePreKey(record.getId(), record);
axolotlStore.storePreKey(record.getId(), record);
}
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);
} }
}); 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);
}
});
}
} catch (InvalidKeyException e) {
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage());
return;
} }
} catch (InvalidKeyException e) { } else {
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Failed to publish bundle " + getOwnDeviceId() + ", reason: " + e.getMessage()); Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing Bundle:" + packet.findChild("error"));
return;
} }
} }
}); });
@ -453,45 +461,52 @@ public class AxolotlService {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); if (packet.getType() == IqPacket.TYPE.RESULT) {
final IqParser parser = mXmppConnectionService.getIqParser(); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing...");
final List<PreKeyBundle> preKeyBundleList = parser.preKeys(packet); final IqParser parser = mXmppConnectionService.getIqParser();
final PreKeyBundle bundle = parser.bundle(packet); final List<PreKeyBundle> preKeyBundleList = parser.preKeys(packet);
if (preKeyBundleList.isEmpty() || bundle == null) { final PreKeyBundle bundle = parser.bundle(packet);
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + 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();
} else {
fetchStatusMap.put(address, FetchStatus.ERROR); fetchStatusMap.put(address, FetchStatus.ERROR);
Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error"));
finish(); finish();
return; 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();
} }
}); });
} catch (InvalidJidException e) { } catch (InvalidJidException e) {

View file

@ -236,7 +236,9 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
@Override @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { 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"); final Element query = packet.findChild("query");
// If this is in response to a query for the whole roster: // If this is in response to a query for the whole roster:
if (packet.getType() == IqPacket.TYPE.RESULT) { 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); final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT);
mXmppConnectionService.sendIqPacket(account, response, null); mXmppConnectionService.sendIqPacket(account, response, null);
} else { } else {
if ((packet.getType() == IqPacket.TYPE.GET) if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) {
|| (packet.getType() == IqPacket.TYPE.SET)) {
final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR);
final Element error = response.addChild("error"); final Element error = response.addChild("error");
error.setAttribute("type", "cancel"); error.setAttribute("type", "cancel");
error.addChild("feature-not-implemented", error.addChild("feature-not-implemented","urn:ietf:params:xml:ns:xmpp-stanzas");
"urn:ietf:params:xml:ns:xmpp-stanzas");
account.getXmppConnection().sendIqPacket(response, null); account.getXmppConnection().sendIqPacket(response, null);
} }
} }
} }

View file

@ -867,28 +867,31 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
@Override @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { public void onIqPacketReceived(final Account account, final IqPacket packet) {
final Element query = packet.query(); if (packet.getType() == IqPacket.TYPE.RESULT) {
final List<Bookmark> bookmarks = new CopyOnWriteArrayList<>(); final Element query = packet.query();
final Element storage = query.findChild("storage", final List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
"storage:bookmarks"); final Element storage = query.findChild("storage", "storage:bookmarks");
if (storage != null) { if (storage != null) {
for (final Element item : storage.getChildren()) { for (final Element item : storage.getChildren()) {
if (item.getName().equals("conference")) { if (item.getName().equals("conference")) {
final Bookmark bookmark = Bookmark.parse(item, account); final Bookmark bookmark = Bookmark.parse(item, account);
bookmarks.add(bookmark); bookmarks.add(bookmark);
Conversation conversation = find(bookmark); Conversation conversation = find(bookmark);
if (conversation != null) { if (conversation != null) {
conversation.setBookmark(bookmark); conversation.setBookmark(bookmark);
} else if (bookmark.autojoin() && bookmark.getJid() != null) { } else if (bookmark.autojoin() && bookmark.getJid() != null) {
conversation = findOrCreateConversation( conversation = findOrCreateConversation(
account, bookmark.getJid(), true); account, bookmark.getJid(), true);
conversation.setBookmark(bookmark); conversation.setBookmark(bookmark);
joinMuc(conversation); joinMuc(conversation);
}
} }
} }
} }
account.setBookmarks(bookmarks);
} else {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not fetch bookmarks");
} }
account.setBookmarks(bookmarks);
} }
}; };
sendIqPacket(account, iqPacket, callback); sendIqPacket(account, iqPacket, callback);
@ -1952,10 +1955,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
final IqPacket packet = XmppConnectionService.this.mIqGenerator final IqPacket packet = XmppConnectionService.this.mIqGenerator
.publishAvatarMetadata(avatar); .publishAvatarMetadata(avatar);
sendIqPacket(account, packet, new OnIqPacketReceived() { sendIqPacket(account, packet, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, public void onIqPacketReceived(Account account, IqPacket result) {
IqPacket result) {
if (result.getType() == IqPacket.TYPE.RESULT) { if (result.getType() == IqPacket.TYPE.RESULT) {
if (account.setAvatar(avatar.getFilename())) { if (account.setAvatar(avatar.getFilename())) {
getAvatarService().clear(account); getAvatarService().clear(account);

View file

@ -69,10 +69,9 @@ public class Element {
public Element findChild(String name, String xmlns) { public Element findChild(String name, String xmlns) {
for (Element child : this.children) { for (Element child : this.children) {
if (child.getName().equals(name) if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
&& (child.getAttribute("xmlns").equals(xmlns))) {
return child; return child;
} }
} }
return null; return null;
} }

View file

@ -34,7 +34,6 @@ import java.util.Hashtable;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
@ -102,7 +101,7 @@ public class XmppConnection implements Runnable {
private long lastConnect = 0; private long lastConnect = 0;
private long lastSessionStarted = 0; private long lastSessionStarted = 0;
private int attempt = 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 OnPresencePacketReceived presenceListener = null;
private OnJinglePacketReceived jingleListener = null; private OnJinglePacketReceived jingleListener = null;
private OnIqPacketReceived unregisteredIqListener = null; private OnIqPacketReceived unregisteredIqListener = null;
@ -649,8 +648,8 @@ public class XmppConnection implements Runnable {
@Override @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { public void onIqPacketReceived(final Account account, final IqPacket packet) {
final Element instructions = packet.query().findChild("instructions"); if (packet.getType() == IqPacket.TYPE.RESULT
if (packet.query().hasChild("username") && packet.query().hasChild("username")
&& (packet.query().hasChild("password"))) { && (packet.query().hasChild("password"))) {
final IqPacket register = new IqPacket(IqPacket.TYPE.SET); final IqPacket register = new IqPacket(IqPacket.TYPE.SET);
final Element username = new Element("username").setContent(account.getUsername()); final Element username = new Element("username").setContent(account.getUsername());
@ -677,6 +676,7 @@ public class XmppConnection implements Runnable {
} }
}); });
} else { } else {
final Element instructions = packet.query().findChild("instructions");
changeStatus(Account.State.REGISTRATION_FAILED); changeStatus(Account.State.REGISTRATION_FAILED);
disconnect(true); disconnect(true);
Log.d(Config.LOGTAG, account.getJid().toBareJid() Log.d(Config.LOGTAG, account.getJid().toBareJid()
@ -716,9 +716,11 @@ public class XmppConnection implements Runnable {
sendPostBindInitialization(); sendPostBindInitialization();
} }
} else { } else {
Log.d(Config.LOGTAG,account.getJid()+": disconnecting because of bind failure");
disconnect(true); disconnect(true);
} }
} else { } else {
Log.d(Config.LOGTAG,account.getJid()+": disconnecting because of bind failure");
disconnect(true); disconnect(true);
} }
} }
@ -726,16 +728,24 @@ public class XmppConnection implements Runnable {
} }
private void clearIqCallbacks() { private void clearIqCallbacks() {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing iq iq callbacks");
final IqPacket failurePacket = new IqPacket(IqPacket.TYPE.ERROR); final IqPacket failurePacket = new IqPacket(IqPacket.TYPE.ERROR);
final ArrayList<OnIqPacketReceived> callbacks = new ArrayList<>();
synchronized (this.packetCallbacks) { 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()) { while (iterator.hasNext()) {
Entry<String, Pair<IqPacket, OnIqPacketReceived>> entry = iterator.next(); Pair<IqPacket, OnIqPacketReceived> entry = iterator.next();
entry.getValue().second.onIqPacketReceived(account, failurePacket); callbacks.add(entry.second);
iterator.remove(); 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() { private void sendStartSession() {
@ -747,6 +757,7 @@ public class XmppConnection implements Runnable {
if (packet.getType() == IqPacket.TYPE.RESULT) { if (packet.getType() == IqPacket.TYPE.RESULT) {
sendPostBindInitialization(); sendPostBindInitialization();
} else { } else {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions");
disconnect(true); disconnect(true);
} }
} }
@ -792,26 +803,29 @@ public class XmppConnection implements Runnable {
@Override @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { public void onIqPacketReceived(final Account account, final IqPacket packet) {
final List<Element> elements = packet.query().getChildren(); if (packet.getType() == IqPacket.TYPE.RESULT) {
final Info info = new Info(); final List<Element> elements = packet.query().getChildren();
for (final Element element : elements) { final Info info = new Info();
if (element.getName().equals("identity")) { for (final Element element : elements) {
String type = element.getAttribute("type"); if (element.getName().equals("identity")) {
String category = element.getAttribute("category"); String type = element.getAttribute("type");
if (type != null && category != null) { String category = element.getAttribute("category");
info.identities.add(new Pair<>(category,type)); 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);
disco.put(jid, info); if (account.getServer().equals(jid)) {
enableAdvancedStreamFeatures();
if (account.getServer().equals(jid)) { for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
enableAdvancedStreamFeatures(); listener.onAdvancedStreamFeaturesAvailable(account);
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 @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { public void onIqPacketReceived(final Account account, final IqPacket packet) {
final List<Element> elements = packet.query().getChildren(); if (packet.getType() == IqPacket.TYPE.RESULT) {
for (final Element element : elements) { final List<Element> elements = packet.query().getChildren();
if (element.getName().equals("item")) { for (final Element element : elements) {
final Jid jid = element.getAttributeAsJid("jid"); if (element.getName().equals("item")) {
if (jid != null && !jid.equals(account.getServer())) { final Jid jid = element.getAttributeAsJid("jid");
sendServiceDiscoveryInfo(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, Log.d(Config.LOGTAG,
account.getJid().toBareJid() + ": switching resource due to conflict (" account.getJid().toBareJid() + ": switching resource due to conflict ("
+ account.getResource() + ")"); + account.getResource() + ")");
} else if (streamError != null) {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString());
} }
} }