block code when doing unforced disconnect

This commit is contained in:
Daniel Gultsch 2015-10-16 09:58:31 +02:00
parent c1716a35e3
commit fb7359e6a3
2 changed files with 220 additions and 223 deletions

View file

@ -26,10 +26,9 @@ import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.security.KeyChain; import android.security.KeyChain;
import android.security.KeyChainException; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.LruCache; import android.util.LruCache;
import android.util.DisplayMetrics;
import android.util.Pair; import android.util.Pair;
import net.java.otr4j.OtrException; import net.java.otr4j.OtrException;
@ -38,16 +37,11 @@ import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionImpl;
import net.java.otr4j.session.SessionStatus; import net.java.otr4j.session.SessionStatus;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x500.style.IETFUtils;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection; import org.openintents.openpgp.util.OpenPgpServiceConnection;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
@ -124,9 +118,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification"; public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification";
public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground"; public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground";
private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
public static final String ACTION_TRY_AGAIN = "try_again"; public static final String ACTION_TRY_AGAIN = "try_again";
public static final String ACTION_DISABLE_ACCOUNT = "disable_account"; public static final String ACTION_DISABLE_ACCOUNT = "disable_account";
private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor();
private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor();
private final IBinder mBinder = new XmppConnectionBinder();
private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
private final IqGenerator mIqGenerator = new IqGenerator(this);
private final List<String> mInProgressAvatarFetches = new ArrayList<>();
public DatabaseBackend databaseBackend;
private ContentObserver contactObserver = new ContentObserver(null) { private ContentObserver contactObserver = new ContentObserver(null) {
@Override @Override
public void onChange(boolean selfChange) { public void onChange(boolean selfChange) {
@ -137,63 +138,30 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
startService(intent); startService(intent);
} }
}; };
private FileBackend fileBackend = new FileBackend(this);
private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor(); private MemorizingTrustManager mMemorizingTrustManager;
private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor(); private NotificationService mNotificationService = new NotificationService(
this);
private final IBinder mBinder = new XmppConnectionBinder(); private OnMessagePacketReceived mMessageParser = new MessageParser(this);
private final List<Conversation> conversations = new CopyOnWriteArrayList<>(); private OnPresencePacketReceived mPresenceParser = new PresenceParser(this);
private final FileObserver fileObserver = new FileObserver( private IqParser mIqParser = new IqParser(this);
FileBackend.getConversationsImageDirectory()) { private OnIqPacketReceived mDefaultIqHandler = new OnIqPacketReceived() {
@Override @Override
public void onEvent(int event, String path) { public void onIqPacketReceived(Account account, IqPacket packet) {
if (event == FileObserver.DELETE) { if (packet.getType() != IqPacket.TYPE.RESULT) {
markFileDeleted(path.split("\\.")[0]); Element error = packet.findChild("error");
} String text = error != null ? error.findChildContent("text") : null;
} if (text != null) {
}; Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received iq error - " + text);
private final OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
@Override
public void onJinglePacketReceived(Account account, JinglePacket packet) {
mJingleConnectionManager.deliverPacket(account, packet);
}
};
private final OnBindListener mOnBindListener = new OnBindListener() {
@Override
public void onBind(final Account account) {
account.getRoster().clearPresences();
fetchRosterFromServer(account);
fetchBookmarks(account);
sendPresence(account);
connectMultiModeConversations(account);
mMessageArchiveService.executePendingQueries(account);
mJingleConnectionManager.cancelInTransmission();
syncDirtyContacts(account);
account.getAxolotlService().publishBundlesIfNeeded(true, false);
}
};
private final OnMessageAcknowledged mOnMessageAcknowledgedListener = new OnMessageAcknowledged() {
@Override
public void onMessageAcknowledged(Account account, String uuid) {
for (final Conversation conversation : getConversations()) {
if (conversation.getAccount() == account) {
Message message = conversation.findUnsentMessageWithUuid(uuid);
if (message != null) {
markMessage(message, Message.STATUS_SEND);
if (conversation.setLastMessageTransmitted(System.currentTimeMillis())) {
databaseBackend.updateConversation(conversation);
}
}
} }
} }
} }
}; };
private final IqGenerator mIqGenerator = new IqGenerator(this); private MessageGenerator mMessageGenerator = new MessageGenerator(this);
public DatabaseBackend databaseBackend; private PresenceGenerator mPresenceGenerator = new PresenceGenerator(this);
private List<Account> accounts;
private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
this);
public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() { public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
@Override @Override
@ -220,42 +188,77 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
} }
}; };
private FileBackend fileBackend = new FileBackend(this); private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
private MemorizingTrustManager mMemorizingTrustManager;
private NotificationService mNotificationService = new NotificationService(
this); this);
private OnMessagePacketReceived mMessageParser = new MessageParser(this); private AvatarService mAvatarService = new AvatarService(this);
private OnPresencePacketReceived mPresenceParser = new PresenceParser(this); private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
private IqParser mIqParser = new IqParser(this); private OnConversationUpdate mOnConversationUpdate = null;
private OnIqPacketReceived mDefaultIqHandler = new OnIqPacketReceived() { private final FileObserver fileObserver = new FileObserver(
FileBackend.getConversationsImageDirectory()) {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onEvent(int event, String path) {
if (packet.getType() != IqPacket.TYPE.RESULT) { if (event == FileObserver.DELETE) {
Element error = packet.findChild("error"); markFileDeleted(path.split("\\.")[0]);
String text = error != null ? error.findChildContent("text") : null; }
if (text != null) { }
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": received iq error - "+text); };
private final OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
@Override
public void onJinglePacketReceived(Account account, JinglePacket packet) {
mJingleConnectionManager.deliverPacket(account, packet);
}
};
private final OnMessageAcknowledged mOnMessageAcknowledgedListener = new OnMessageAcknowledged() {
@Override
public void onMessageAcknowledged(Account account, String uuid) {
for (final Conversation conversation : getConversations()) {
if (conversation.getAccount() == account) {
Message message = conversation.findUnsentMessageWithUuid(uuid);
if (message != null) {
markMessage(message, Message.STATUS_SEND);
if (conversation.setLastMessageTransmitted(System.currentTimeMillis())) {
databaseBackend.updateConversation(conversation);
}
}
} }
} }
} }
}; };
private MessageGenerator mMessageGenerator = new MessageGenerator(this);
private PresenceGenerator mPresenceGenerator = new PresenceGenerator(this);
private List<Account> accounts;
private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
this);
private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
this);
private AvatarService mAvatarService = new AvatarService(this);
private final List<String> mInProgressAvatarFetches = new ArrayList<>();
private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
private OnConversationUpdate mOnConversationUpdate = null;
private int convChangedListenerCount = 0; private int convChangedListenerCount = 0;
private OnShowErrorToast mOnShowErrorToast = null; private OnShowErrorToast mOnShowErrorToast = null;
private int showErrorToastListenerCount = 0; private int showErrorToastListenerCount = 0;
private int unreadCount = -1; private int unreadCount = -1;
private OnAccountUpdate mOnAccountUpdate = null; private OnAccountUpdate mOnAccountUpdate = null;
private OnCaptchaRequested mOnCaptchaRequested = null; private OnCaptchaRequested mOnCaptchaRequested = null;
private int accountChangedListenerCount = 0;
private int captchaRequestedListenerCount = 0;
private OnRosterUpdate mOnRosterUpdate = null;
private OnUpdateBlocklist mOnUpdateBlocklist = null;
private int updateBlocklistListenerCount = 0;
private int rosterChangedListenerCount = 0;
private OnMucRosterUpdate mOnMucRosterUpdate = null;
private int mucRosterChangedListenerCount = 0;
private OnKeyStatusUpdated mOnKeyStatusUpdated = null;
private int keyStatusUpdatedListenerCount = 0;
private SecureRandom mRandom;
private final OnBindListener mOnBindListener = new OnBindListener() {
@Override
public void onBind(final Account account) {
account.getRoster().clearPresences();
fetchRosterFromServer(account);
fetchBookmarks(account);
sendPresence(account);
connectMultiModeConversations(account);
mMessageArchiveService.executePendingQueries(account);
mJingleConnectionManager.cancelInTransmission();
syncDirtyContacts(account);
account.getAxolotlService().publishBundlesIfNeeded(true, false);
}
};
private OnStatusChanged statusListener = new OnStatusChanged() { private OnStatusChanged statusListener = new OnStatusChanged() {
@Override @Override
@ -267,10 +270,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (account.getStatus() == Account.State.ONLINE) { if (account.getStatus() == Account.State.ONLINE) {
if (connection != null && connection.getFeatures().csi()) { if (connection != null && connection.getFeatures().csi()) {
if (checkListeners()) { if (checkListeners()) {
Log.d(Config.LOGTAG, account.getJid().toBareJid()+ " sending csi//inactive"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//inactive");
connection.sendInactive(); connection.sendInactive();
} else { } else {
Log.d(Config.LOGTAG, account.getJid().toBareJid()+ " sending csi//active"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//active");
connection.sendActive(); connection.sendActive();
} }
} }
@ -294,7 +297,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
resetSendingToWaiting(account); resetSendingToWaiting(account);
if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!account.isOptionSet(Account.OPTION_DISABLED)) {
int timeToReconnect = mRandom.nextInt(20) + 10; int timeToReconnect = mRandom.nextInt(20) + 10;
scheduleWakeUpCall(timeToReconnect,account.getUuid().hashCode()); scheduleWakeUpCall(timeToReconnect, account.getUuid().hashCode());
} }
} else if (account.getStatus() == Account.State.REGISTRATION_SUCCESSFUL) { } else if (account.getStatus() == Account.State.REGISTRATION_SUCCESSFUL) {
databaseBackend.updateAccount(account); databaseBackend.updateAccount(account);
@ -307,23 +310,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
+ ": error connecting account. try again in " + ": error connecting account. try again in "
+ next + "s for the " + next + "s for the "
+ (connection.getAttempt() + 1) + " time"); + (connection.getAttempt() + 1) + " time");
scheduleWakeUpCall(next,account.getUuid().hashCode()); scheduleWakeUpCall(next, account.getUuid().hashCode());
} }
} }
getNotificationService().updateErrorNotification(); getNotificationService().updateErrorNotification();
} }
}; };
private int accountChangedListenerCount = 0;
private int captchaRequestedListenerCount = 0;
private OnRosterUpdate mOnRosterUpdate = null;
private OnUpdateBlocklist mOnUpdateBlocklist = null;
private int updateBlocklistListenerCount = 0;
private int rosterChangedListenerCount = 0;
private OnMucRosterUpdate mOnMucRosterUpdate = null;
private int mucRosterChangedListenerCount = 0;
private OnKeyStatusUpdated mOnKeyStatusUpdated = null;
private int keyStatusUpdatedListenerCount = 0;
private SecureRandom mRandom;
private OpenPgpServiceConnection pgpServiceConnection; private OpenPgpServiceConnection pgpServiceConnection;
private PgpEngine mPgpEngine = null; private PgpEngine mPgpEngine = null;
private WakeLock wakeLock; private WakeLock wakeLock;
@ -333,6 +325,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
private EventReceiver mEventReceiver = new EventReceiver(); private EventReceiver mEventReceiver = new EventReceiver();
private boolean mRestoredFromDatabase = false; private boolean mRestoredFromDatabase = false;
private static String generateFetchKey(Account account, final Avatar avatar) {
return account.getJid().toBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum;
}
public boolean areMessagesInitialized() { public boolean areMessagesInitialized() {
return this.mRestoredFromDatabase; return this.mRestoredFromDatabase;
} }
@ -341,8 +338,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (pgpServiceConnection.isBound()) { if (pgpServiceConnection.isBound()) {
if (this.mPgpEngine == null) { if (this.mPgpEngine == null) {
this.mPgpEngine = new PgpEngine(new OpenPgpApi( this.mPgpEngine = new PgpEngine(new OpenPgpApi(
getApplicationContext(), getApplicationContext(),
pgpServiceConnection.getService()), this); pgpServiceConnection.getService()), this);
} }
return mPgpEngine; return mPgpEngine;
} else { } else {
@ -366,7 +363,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (encryption == Message.ENCRYPTION_PGP) { if (encryption == Message.ENCRYPTION_PGP) {
encryption = Message.ENCRYPTION_DECRYPTED; encryption = Message.ENCRYPTION_DECRYPTED;
} }
Message message = new Message(conversation,uri.toString(),encryption); Message message = new Message(conversation, uri.toString(), encryption);
if (conversation.getNextCounterpart() != null) { if (conversation.getNextCounterpart() != null) {
message.setCounterpart(conversation.getNextCounterpart()); message.setCounterpart(conversation.getNextCounterpart());
} }
@ -378,8 +375,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
public void attachFileToConversation(final Conversation conversation, public void attachFileToConversation(final Conversation conversation,
final Uri uri, final Uri uri,
final UiCallback<Message> callback) { final UiCallback<Message> callback) {
final Message message; final Message message;
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) { if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED); message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED);
@ -389,7 +386,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
message.setCounterpart(conversation.getNextCounterpart()); message.setCounterpart(conversation.getNextCounterpart());
message.setType(Message.TYPE_FILE); message.setType(Message.TYPE_FILE);
String path = getFileBackend().getOriginalPath(uri); String path = getFileBackend().getOriginalPath(uri);
if (path!=null) { if (path != null) {
message.setRelativeFilePath(path); message.setRelativeFilePath(path);
getFileBackend().updateFileParams(message); getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
@ -419,7 +416,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) { public void attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) {
if (getFileBackend().useImageAsIs(uri)) { if (getFileBackend().useImageAsIs(uri)) {
Log.d(Config.LOGTAG,"using image as is"); Log.d(Config.LOGTAG, "using image as is");
attachFileToConversation(conversation, uri, callback); attachFileToConversation(conversation, uri, callback);
return; return;
} }
@ -427,7 +424,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) { if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED); message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED);
} else { } else {
message = new Message(conversation, "",conversation.getNextEncryption()); message = new Message(conversation, "", conversation.getNextEncryption());
} }
message.setCounterpart(conversation.getNextCounterpart()); message.setCounterpart(conversation.getNextCounterpart());
message.setType(Message.TYPE_IMAGE); message.setType(Message.TYPE_IMAGE);
@ -462,7 +459,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
final String action = intent == null ? null : intent.getAction(); final String action = intent == null ? null : intent.getAction();
boolean interactive = false; boolean interactive = false;
if (action != null) { if (action != null) {
Log.d(Config.LOGTAG,"action: "+action); Log.d(Config.LOGTAG, "action: " + action);
switch (action) { switch (action) {
case ConnectivityManager.CONNECTIVITY_ACTION: case ConnectivityManager.CONNECTIVITY_ACTION:
if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) { if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) {
@ -483,7 +480,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
mNotificationService.clear(); mNotificationService.clear();
break; break;
case ACTION_DISABLE_FOREGROUND: case ACTION_DISABLE_FOREGROUND:
getPreferences().edit().putBoolean("keep_foreground_service",false).commit(); getPreferences().edit().putBoolean("keep_foreground_service", false).commit();
toggleForegroundService(); toggleForegroundService();
break; break;
case ACTION_TRY_AGAIN: case ACTION_TRY_AGAIN:
@ -495,7 +492,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
String jid = intent.getStringExtra("account"); String jid = intent.getStringExtra("account");
Account account = jid == null ? null : findAccountByJid(Jid.fromString(jid)); Account account = jid == null ? null : findAccountByJid(Jid.fromString(jid));
if (account != null) { if (account != null) {
account.setOption(Account.OPTION_DISABLED,true); account.setOption(Account.OPTION_DISABLED, true);
updateAccount(account); updateAccount(account);
} }
} catch (final InvalidJidException ignored) { } catch (final InvalidJidException ignored) {
@ -535,7 +532,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
long lastReceived = account.getXmppConnection().getLastPacketReceived(); long lastReceived = account.getXmppConnection().getLastPacketReceived();
long lastSent = account.getXmppConnection().getLastPingSent(); long lastSent = account.getXmppConnection().getLastPingSent();
long pingInterval = "ui".equals(action) ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000; long pingInterval = "ui".equals(action) ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000;
long msToNextPing = (Math.max(lastReceived,lastSent) + pingInterval) - SystemClock.elapsedRealtime(); long msToNextPing = (Math.max(lastReceived, lastSent) + pingInterval) - SystemClock.elapsedRealtime();
long pingTimeoutIn = (lastSent + Config.PING_TIMEOUT * 1000) - SystemClock.elapsedRealtime(); long pingTimeoutIn = (lastSent + Config.PING_TIMEOUT * 1000) - SystemClock.elapsedRealtime();
if (lastSent > lastReceived) { if (lastSent > lastReceived) {
if (pingTimeoutIn < 0) { if (pingTimeoutIn < 0) {
@ -543,24 +540,24 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
this.reconnectAccount(account, true, interactive); this.reconnectAccount(account, true, interactive);
} else { } else {
int secs = (int) (pingTimeoutIn / 1000); int secs = (int) (pingTimeoutIn / 1000);
this.scheduleWakeUpCall(secs,account.getUuid().hashCode()); this.scheduleWakeUpCall(secs, account.getUuid().hashCode());
} }
} else if (msToNextPing <= 0) { } else if (msToNextPing <= 0) {
account.getXmppConnection().sendPing(); account.getXmppConnection().sendPing();
Log.d(Config.LOGTAG, account.getJid().toBareJid()+" send ping"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping");
this.scheduleWakeUpCall(Config.PING_TIMEOUT,account.getUuid().hashCode()); this.scheduleWakeUpCall(Config.PING_TIMEOUT, account.getUuid().hashCode());
} else { } else {
this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode());
} }
} else if (account.getStatus() == Account.State.OFFLINE) { } else if (account.getStatus() == Account.State.OFFLINE) {
reconnectAccount(account,true, interactive); reconnectAccount(account, true, interactive);
} else if (account.getStatus() == Account.State.CONNECTING) { } else if (account.getStatus() == Account.State.CONNECTING) {
long timeout = Config.CONNECT_TIMEOUT - ((SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000); long timeout = Config.CONNECT_TIMEOUT - ((SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000);
if (timeout < 0) { if (timeout < 0) {
Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting"); Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting");
reconnectAccount(account, true, interactive); reconnectAccount(account, true, interactive);
} else { } else {
scheduleWakeUpCall((int) timeout,account.getUuid().hashCode()); scheduleWakeUpCall((int) timeout, account.getUuid().hashCode());
} }
} else { } else {
if (account.getXmppConnection().getTimeToNextAttempt() <= 0) { if (account.getXmppConnection().getTimeToNextAttempt() <= 0) {
@ -621,8 +618,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
private void resetAllAttemptCounts(boolean reallyAll) { private void resetAllAttemptCounts(boolean reallyAll) {
Log.d(Config.LOGTAG,"resetting all attepmt counts"); Log.d(Config.LOGTAG, "resetting all attepmt counts");
for(Account account : accounts) { for (Account account : accounts) {
if (account.hasErrorStatus() || reallyAll) { if (account.hasErrorStatus() || reallyAll) {
final XmppConnection connection = account.getXmppConnection(); final XmppConnection connection = account.getXmppConnection();
if (connection != null) { if (connection != null) {
@ -634,7 +631,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public boolean hasInternetConnection() { public boolean hasInternetConnection() {
ConnectivityManager cm = (ConnectivityManager) getApplicationContext() ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE); .getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnected(); return activeNetwork != null && activeNetwork.isConnected();
} }
@ -667,7 +664,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
this.pgpServiceConnection.bindToService(); this.pgpServiceConnection.bindToService();
this.pm = (PowerManager) getSystemService(Context.POWER_SERVICE); this.pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"XmppConnectionService"); this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "XmppConnectionService");
toggleForegroundService(); toggleForegroundService();
updateUnreadCountBadge(); updateUnreadCountBadge();
toggleScreenEventReceiver(); toggleScreenEventReceiver();
@ -677,7 +674,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void onTrimMemory(int level) { public void onTrimMemory(int level) {
super.onTrimMemory(level); super.onTrimMemory(level);
if (level >= TRIM_MEMORY_COMPLETE) { if (level >= TRIM_MEMORY_COMPLETE) {
Log.d(Config.LOGTAG,"clear cache due to low memory"); Log.d(Config.LOGTAG, "clear cache due to low memory");
getBitmapCache().evictAll(); getBitmapCache().evictAll();
} }
} }
@ -717,7 +714,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
@Override @Override
public void onTaskRemoved(final Intent rootIntent) { public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent); super.onTaskRemoved(rootIntent);
if (!getPreferences().getBoolean("keep_foreground_service",false)) { if (!getPreferences().getBoolean("keep_foreground_service", false)) {
this.logoutAndSave(); this.logoutAndSave();
} }
} }
@ -800,11 +797,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
message.getConversation().endOtrIfNeeded(); message.getConversation().endOtrIfNeeded();
message.getConversation().findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR, message.getConversation().findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR,
new Conversation.OnMessageFound() { new Conversation.OnMessageFound() {
@Override @Override
public void onMessageFound(Message message) { public void onMessageFound(Message message) {
markMessage(message,Message.STATUS_SEND_FAILED); markMessage(message, Message.STATUS_SEND_FAILED);
} }
}); });
} }
if (account.isOnlineAndConnected()) { if (account.isOnlineAndConnected()) {
@ -812,7 +809,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
case Message.ENCRYPTION_NONE: case Message.ENCRYPTION_NONE:
if (message.needsUploading()) { if (message.needsUploading()) {
if (account.httpUploadAvailable() || message.fixCounterpart()) { if (account.httpUploadAvailable() || message.fixCounterpart()) {
this.sendFileMessage(message,delay); this.sendFileMessage(message, delay);
} else { } else {
break; break;
} }
@ -824,7 +821,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
case Message.ENCRYPTION_DECRYPTED: case Message.ENCRYPTION_DECRYPTED:
if (message.needsUploading()) { if (message.needsUploading()) {
if (account.httpUploadAvailable() || message.fixCounterpart()) { if (account.httpUploadAvailable() || message.fixCounterpart()) {
this.sendFileMessage(message,delay); this.sendFileMessage(message, delay);
} else { } else {
break; break;
} }
@ -857,7 +854,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
message.setAxolotlFingerprint(account.getAxolotlService().getOwnFingerprint()); message.setAxolotlFingerprint(account.getAxolotlService().getOwnFingerprint());
if (message.needsUploading()) { if (message.needsUploading()) {
if (account.httpUploadAvailable() || message.fixCounterpart()) { if (account.httpUploadAvailable() || message.fixCounterpart()) {
this.sendFileMessage(message,delay); this.sendFileMessage(message, delay);
} else { } else {
break; break;
} }
@ -880,7 +877,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
} }
} else { } else {
switch(message.getEncryption()) { switch (message.getEncryption()) {
case Message.ENCRYPTION_DECRYPTED: case Message.ENCRYPTION_DECRYPTED:
if (!message.needsUploading()) { if (!message.needsUploading()) {
String pgpBody = message.getEncryptedBody(); String pgpBody = message.getEncryptedBody();
@ -907,9 +904,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (resend) { if (resend) {
if (packet != null) { if (packet != null) {
if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) { if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) {
markMessage(message,Message.STATUS_UNSEND); markMessage(message, Message.STATUS_UNSEND);
} else { } else {
markMessage(message,Message.STATUS_SEND); markMessage(message, Message.STATUS_SEND);
} }
} }
} else { } else {
@ -921,7 +918,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
if (packet != null) { if (packet != null) {
if (delay) { if (delay) {
mMessageGenerator.addDelay(packet,message.getTimeSent()); mMessageGenerator.addDelay(packet, message.getTimeSent());
} }
if (conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { if (conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) {
if (this.sendChatStates()) { if (this.sendChatStates()) {
@ -989,7 +986,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
account.setBookmarks(bookmarks); account.setBookmarks(bookmarks);
} else { } else {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not fetch bookmarks"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not fetch bookmarks");
} }
} }
}; };
@ -1013,12 +1010,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
mPhoneContactMergerThread = new Thread(new Runnable() { mPhoneContactMergerThread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
Log.d(Config.LOGTAG,"start merging phone contacts with roster"); Log.d(Config.LOGTAG, "start merging phone contacts with roster");
for (Account account : accounts) { for (Account account : accounts) {
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(); List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts();
for (Bundle phoneContact : phoneContacts) { for (Bundle phoneContact : phoneContacts) {
if (Thread.interrupted()) { if (Thread.interrupted()) {
Log.d(Config.LOGTAG,"interrupted merging phone contacts"); Log.d(Config.LOGTAG, "interrupted merging phone contacts");
return; return;
} }
Jid jid; Jid jid;
@ -1029,8 +1026,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
final Contact contact = account.getRoster().getContact(jid); final Contact contact = account.getRoster().getContact(jid);
String systemAccount = phoneContact.getInt("phoneid") String systemAccount = phoneContact.getInt("phoneid")
+ "#" + "#"
+ phoneContact.getString("lookup"); + phoneContact.getString("lookup");
contact.setSystemAccount(systemAccount); contact.setSystemAccount(systemAccount);
if (contact.setPhotoUri(phoneContact.getString("photouri"))) { if (contact.setPhotoUri(phoneContact.getString("photouri"))) {
getAvatarService().clear(contact); getAvatarService().clear(contact);
@ -1038,7 +1035,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
contact.setSystemName(phoneContact.getString("displayname")); contact.setSystemName(phoneContact.getString("displayname"));
withSystemAccounts.remove(contact); withSystemAccounts.remove(contact);
} }
for(Contact contact : withSystemAccounts) { for (Contact contact : withSystemAccounts) {
contact.setSystemAccount(null); contact.setSystemAccount(null);
contact.setSystemName(null); contact.setSystemName(null);
if (contact.setPhotoUri(null)) { if (contact.setPhotoUri(null)) {
@ -1046,7 +1043,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
} }
} }
Log.d(Config.LOGTAG,"finished merging phone contacts"); Log.d(Config.LOGTAG, "finished merging phone contacts");
updateAccountUi(); updateAccountUi();
} }
}); });
@ -1064,11 +1061,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
Account account = accountLookupTable.get(conversation.getAccountUuid()); Account account = accountLookupTable.get(conversation.getAccountUuid());
conversation.setAccount(account); conversation.setAccount(account);
} }
Runnable runnable =new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
Log.d(Config.LOGTAG,"restoring roster"); Log.d(Config.LOGTAG, "restoring roster");
for(Account account : accounts) { for (Account account : accounts) {
databaseBackend.readRoster(account.getRoster()); databaseBackend.readRoster(account.getRoster());
account.initAccountServices(XmppConnectionService.this); account.initAccountServices(XmppConnectionService.this);
} }
@ -1077,7 +1074,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
PhoneHelper.loadPhoneContacts(getApplicationContext(), PhoneHelper.loadPhoneContacts(getApplicationContext(),
new CopyOnWriteArrayList<Bundle>(), new CopyOnWriteArrayList<Bundle>(),
XmppConnectionService.this); XmppConnectionService.this);
Log.d(Config.LOGTAG,"restoring messages"); Log.d(Config.LOGTAG, "restoring messages");
for (Conversation conversation : conversations) { for (Conversation conversation : conversations) {
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
checkDeletedFiles(conversation); checkDeletedFiles(conversation);
@ -1090,7 +1087,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
mNotificationService.finishBacklog(); mNotificationService.finishBacklog();
mRestoredFromDatabase = true; mRestoredFromDatabase = true;
Log.d(Config.LOGTAG,"restored all messages"); Log.d(Config.LOGTAG, "restored all messages");
updateConversationUi(); updateConversationUi();
} }
}; };
@ -1110,8 +1107,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (!getFileBackend().isFileAvailable(message)) { if (!getFileBackend().isFileAvailable(message)) {
message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
final int s = message.getStatus(); final int s = message.getStatus();
if(s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) { if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
markMessage(message,Message.STATUS_SEND_FAILED); markMessage(message, Message.STATUS_SEND_FAILED);
} }
} }
} }
@ -1125,8 +1122,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (!getFileBackend().isFileAvailable(message)) { if (!getFileBackend().isFileAvailable(message)) {
message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
final int s = message.getStatus(); final int s = message.getStatus();
if(s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) { if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
markMessage(message,Message.STATUS_SEND_FAILED); markMessage(message, Message.STATUS_SEND_FAILED);
} else { } else {
updateConversationUi(); updateConversationUi();
} }
@ -1169,7 +1166,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) { public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) {
if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation,callback)) { if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation, callback)) {
return; return;
} }
Log.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp)); Log.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp));
@ -1177,7 +1174,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
@Override @Override
public void run() { public void run() {
final Account account = conversation.getAccount(); final Account account = conversation.getAccount();
List<Message> messages = databaseBackend.getMessages(conversation, 50,timestamp); List<Message> messages = databaseBackend.getMessages(conversation, 50, timestamp);
if (messages.size() > 0) { if (messages.size() > 0) {
conversation.addAll(0, messages); conversation.addAll(0, messages);
checkDeletedFiles(conversation); checkDeletedFiles(conversation);
@ -1186,7 +1183,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
&& account.isOnlineAndConnected()) { && account.isOnlineAndConnected()) {
if ((conversation.getMode() == Conversation.MODE_SINGLE && account.getXmppConnection().getFeatures().mam()) if ((conversation.getMode() == Conversation.MODE_SINGLE && account.getXmppConnection().getFeatures().mam())
|| (conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().mamSupport())) { || (conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().mamSupport())) {
MessageArchiveService.Query query = getMessageArchiveService().query(conversation,0,timestamp - 1); MessageArchiveService.Query query = getMessageArchiveService().query(conversation, 0, timestamp - 1);
if (query != null) { if (query != null) {
query.setCallback(callback); query.setCallback(callback);
} }
@ -1320,7 +1317,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void run() { public void run() {
try { try {
X509Certificate[] chain = KeyChain.getCertificateChain(XmppConnectionService.this, alias); X509Certificate[] chain = KeyChain.getCertificateChain(XmppConnectionService.this, alias);
Pair<Jid,String> info = CryptoHelper.extractJidAndName(chain[0]); Pair<Jid, String> info = CryptoHelper.extractJidAndName(chain[0]);
if (findAccountByJid(info.first) == null) { if (findAccountByJid(info.first) == null) {
Account account = new Account(info.first, ""); Account account = new Account(info.first, "");
account.setPrivateKeyAlias(alias); account.setPrivateKeyAlias(alias);
@ -1338,6 +1335,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
callback.informUser(R.string.account_already_exists); callback.informUser(R.string.account_already_exists);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
callback.informUser(R.string.unable_to_parse_certificate); callback.informUser(R.string.unable_to_parse_certificate);
} }
} }
@ -1364,13 +1362,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} else { } else {
showErrorToastInUi(R.string.jid_does_not_match_certificate); showErrorToastInUi(R.string.jid_does_not_match_certificate);
} }
} catch (InterruptedException e) { } catch (Exception e) {
e.printStackTrace();
} catch (KeyChainException e) {
e.printStackTrace();
} catch (InvalidJidException e) {
e.printStackTrace();
} catch (CertificateEncodingException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -1378,7 +1370,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void updateAccount(final Account account) { public void updateAccount(final Account account) {
this.statusListener.onStatusChanged(account); this.statusListener.onStatusChanged(account);
databaseBackend.updateAccount(account); databaseBackend.updateAccount(account);
reconnectAccount(account, false, true); reconnectAccountInBackground(account);
updateAccountUi(); updateAccountUi();
getNotificationService().updateErrorNotification(); getNotificationService().updateErrorNotification();
} }
@ -1655,7 +1647,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
} }
} }
for(Conversation conversation : getConversations()) { for (Conversation conversation : getConversations()) {
conversation.setIncomingChatState(ChatState.ACTIVE); conversation.setIncomingChatState(ChatState.ACTIVE);
} }
this.mNotificationService.setIsInForeground(false); this.mNotificationService.setIsInForeground(false);
@ -1666,7 +1658,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
List<Conversation> conversations = getConversations(); List<Conversation> conversations = getConversations();
for (Conversation conversation : conversations) { for (Conversation conversation : conversations) {
if (conversation.getMode() == Conversation.MODE_MULTI && conversation.getAccount() == account) { if (conversation.getMode() == Conversation.MODE_MULTI && conversation.getAccount() == account) {
joinMuc(conversation,true); joinMuc(conversation, true);
} }
} }
} }
@ -1791,10 +1783,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
public void leaveMuc(Conversation conversation) { public void leaveMuc(Conversation conversation) {
leaveMuc(conversation, false);
}
private void leaveMuc(Conversation conversation, boolean now) {
Account account = conversation.getAccount(); Account account = conversation.getAccount();
account.pendingConferenceJoins.remove(conversation); account.pendingConferenceJoins.remove(conversation);
account.pendingConferenceLeaves.remove(conversation); account.pendingConferenceLeaves.remove(conversation);
if (account.getStatus() == Account.State.ONLINE) { if (account.getStatus() == Account.State.ONLINE || now) {
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setTo(conversation.getJid()); packet.setTo(conversation.getJid());
packet.setFrom(conversation.getAccount().getJid()); packet.setFrom(conversation.getAccount().getJid());
@ -2006,7 +2002,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}); });
} }
public void disconnect(Account account, boolean force) { private void disconnect(Account account, boolean force) {
if ((account.getStatus() == Account.State.ONLINE) if ((account.getStatus() == Account.State.ONLINE)
|| (account.getStatus() == Account.State.DISABLED)) { || (account.getStatus() == Account.State.DISABLED)) {
if (!force) { if (!force) {
@ -2014,7 +2010,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
for (Conversation conversation : conversations) { for (Conversation conversation : conversations) {
if (conversation.getAccount() == account) { if (conversation.getAccount() == account) {
if (conversation.getMode() == Conversation.MODE_MULTI) { if (conversation.getMode() == Conversation.MODE_MULTI) {
leaveMuc(conversation); leaveMuc(conversation, true);
} else { } else {
if (conversation.endOtrIfNeeded()) { if (conversation.endOtrIfNeeded()) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() Log.d(Config.LOGTAG, account.getJid().toBareJid()
@ -2204,13 +2200,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
fetchAvatar(account, avatar, null); fetchAvatar(account, avatar, null);
} }
private static String generateFetchKey(Account account, final Avatar avatar) {
return account.getJid().toBareJid()+"_"+avatar.owner+"_"+avatar.sha1sum;
}
public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) {
final String KEY = generateFetchKey(account, avatar); final String KEY = generateFetchKey(account, avatar);
synchronized(this.mInProgressAvatarFetches) { synchronized (this.mInProgressAvatarFetches) {
if (this.mInProgressAvatarFetches.contains(KEY)) { if (this.mInProgressAvatarFetches.contains(KEY)) {
return; return;
} else { } else {
@ -2375,9 +2367,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!account.isOptionSet(Account.OPTION_DISABLED)) {
synchronized (this.mInProgressAvatarFetches) { synchronized (this.mInProgressAvatarFetches) {
for(Iterator<String> iterator = this.mInProgressAvatarFetches.iterator(); iterator.hasNext();) { for (Iterator<String> iterator = this.mInProgressAvatarFetches.iterator(); iterator.hasNext(); ) {
final String KEY = iterator.next(); final String KEY = iterator.next();
if (KEY.startsWith(account.getJid().toBareJid()+"_")) { if (KEY.startsWith(account.getJid().toBareJid() + "_")) {
iterator.remove(); iterator.remove();
} }
} }
@ -2385,6 +2377,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (account.getXmppConnection() == null) { if (account.getXmppConnection() == null) {
account.setXmppConnection(createConnection(account)); account.setXmppConnection(createConnection(account));
} else if (!force) {
try {
Log.d(Config.LOGTAG, "wait for disconnect");
Thread.sleep(500); //sleep wait for disconnect
} catch (InterruptedException e) {
//ignored
}
} }
Thread thread = new Thread(account.getXmppConnection()); Thread thread = new Thread(account.getXmppConnection());
account.getXmppConnection().setInteractive(interactive); account.getXmppConnection().setInteractive(interactive);
@ -2401,20 +2400,20 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
reconnectAccount(account,false,true); reconnectAccount(account, false, true);
} }
}).start(); }).start();
} }
public void invite(Conversation conversation, Jid contact) { public void invite(Conversation conversation, Jid contact) {
Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+": inviting "+contact+" to "+conversation.getJid().toBareJid()); Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": inviting " + contact + " to " + conversation.getJid().toBareJid());
MessagePacket packet = mMessageGenerator.invite(conversation, contact); MessagePacket packet = mMessageGenerator.invite(conversation, contact);
sendMessagePacket(conversation.getAccount(), packet); sendMessagePacket(conversation.getAccount(), packet);
} }
public void directInvite(Conversation conversation, Jid jid) { public void directInvite(Conversation conversation, Jid jid) {
MessagePacket packet = mMessageGenerator.directInvite(conversation, jid); MessagePacket packet = mMessageGenerator.directInvite(conversation, jid);
sendMessagePacket(conversation.getAccount(),packet); sendMessagePacket(conversation.getAccount(), packet);
} }
public void resetSendingToWaiting(Account account) { public void resetSendingToWaiting(Account account) {
@ -2499,7 +2498,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public int unreadCount() { public int unreadCount() {
int count = 0; int count = 0;
for(Conversation conversation : getConversations()) { for (Conversation conversation : getConversations()) {
count += conversation.unreadCount(); count += conversation.unreadCount();
} }
return count; return count;
@ -2534,8 +2533,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
boolean rc = false; boolean rc = false;
if (mOnCaptchaRequested != null) { if (mOnCaptchaRequested != null) {
DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics(); DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics();
Bitmap scaled = Bitmap.createScaledBitmap(captcha, (int)(captcha.getWidth() * metrics.scaledDensity), Bitmap scaled = Bitmap.createScaledBitmap(captcha, (int) (captcha.getWidth() * metrics.scaledDensity),
(int)(captcha.getHeight() * metrics.scaledDensity), false); (int) (captcha.getHeight() * metrics.scaledDensity), false);
mOnCaptchaRequested.onCaptchaRequested(account, id, data, scaled); mOnCaptchaRequested.onCaptchaRequested(account, id, data, scaled);
rc = true; rc = true;
@ -2557,7 +2556,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
public void keyStatusUpdated() { public void keyStatusUpdated() {
if(mOnKeyStatusUpdated != null) { if (mOnKeyStatusUpdated != null) {
mOnKeyStatusUpdated.onKeyStatusUpdated(); mOnKeyStatusUpdated.onKeyStatusUpdated();
} }
} }
@ -2582,7 +2581,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void markRead(final Conversation conversation) { public void markRead(final Conversation conversation) {
mNotificationService.clear(conversation); mNotificationService.clear(conversation);
for(Message message : conversation.markRead()) { for (Message message : conversation.markRead()) {
databaseBackend.updateMessage(message); databaseBackend.updateMessage(message);
} }
updateUnreadCountBadge(); updateUnreadCountBadge();
@ -2630,7 +2629,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
final MemorizingTrustManager tm; final MemorizingTrustManager tm;
final boolean dontTrustSystemCAs = getPreferences().getBoolean("dont_trust_system_cas", false); final boolean dontTrustSystemCAs = getPreferences().getBoolean("dont_trust_system_cas", false);
if (dontTrustSystemCAs) { if (dontTrustSystemCAs) {
tm = new MemorizingTrustManager(getApplicationContext(), null); tm = new MemorizingTrustManager(getApplicationContext(), null);
} else { } else {
tm = new MemorizingTrustManager(getApplicationContext()); tm = new MemorizingTrustManager(getApplicationContext());
} }
@ -2791,7 +2790,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
for (final Message msg : messages) { for (final Message msg : messages) {
msg.setTime(System.currentTimeMillis()); msg.setTime(System.currentTimeMillis());
markMessage(msg, Message.STATUS_WAITING); markMessage(msg, Message.STATUS_WAITING);
this.resendMessage(msg,false); this.resendMessage(msg, false);
} }
} }
@ -2840,6 +2839,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public interface OnAccountCreated { public interface OnAccountCreated {
void onAccountCreated(Account account); void onAccountCreated(Account account);
void informUser(int r); void informUser(int r);
} }
@ -2877,9 +2877,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public interface OnCaptchaRequested { public interface OnCaptchaRequested {
void onCaptchaRequested(Account account, void onCaptchaRequested(Account account,
String id, String id,
Data data, Data data,
Bitmap captcha); Bitmap captcha);
} }
public interface OnRosterUpdate { public interface OnRosterUpdate {

View file

@ -783,7 +783,7 @@ public class XmppConnection implements Runnable {
String urlString = url.findChildContent("value"); String urlString = url.findChildContent("value");
URL uri = new URL(urlString); URL uri = new URL(urlString);
captcha = BitmapFactory.decodeStream(uri.openConnection().getInputStream()); captcha = BitmapFactory.decodeStream(uri.openConnection().getInputStream());
} catch(IOException e) { } catch (IOException e) {
Log.e(Config.LOGTAG, e.toString()); Log.e(Config.LOGTAG, e.toString());
} }
} }
@ -884,7 +884,7 @@ public class XmppConnection implements Runnable {
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.RESULT) { if (packet.getType() == IqPacket.TYPE.RESULT) {
sendPostBindInitialization(); sendPostBindInitialization();
} else if (packet.getType() != IqPacket.TYPE.TIMEOUT){ } else if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions");
disconnect(true); disconnect(true);
} }
@ -1139,44 +1139,41 @@ public class XmppConnection implements Runnable {
} }
public void disconnect(final boolean force) { public void disconnect(final boolean force) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": disconnecting"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": disconnecting force="+Boolean.valueOf(force));
try { if (force) {
if (force) { try {
socket.close(); socket.close();
return; } catch(Exception e) {
Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()+": exception during force close ("+e.getMessage()+")");
} }
new Thread(new Runnable() { return;
} else {
@Override resetStreamId();
public void run() { if (tagWriter.isActive()) {
if (tagWriter.isActive()) { tagWriter.finish();
tagWriter.finish(); try {
try { int i = 0;
int i = 0; boolean warned = false;
boolean warned = false; while (!tagWriter.finished() && socket.isConnected() && i <= 10) {
while (!tagWriter.finished() && socket.isConnected() && i <= 10) { if (!warned) {
if (!warned) { Log.d(Config.LOGTAG, account.getJid().toBareJid()+": waiting for tag writer to finish");
Log.d(Config.LOGTAG, account.getJid().toBareJid()+": waiting for tag writer to finish"); warned = true;
warned = true;
}
Thread.sleep(200);
i++;
}
if (warned) {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": tag writer has finished");
}
tagWriter.writeTag(Tag.end("stream:stream"));
socket.close();
} catch (final IOException e) {
Log.d(Config.LOGTAG,"io exception during disconnect");
} catch (final InterruptedException e) {
Log.d(Config.LOGTAG, "interrupted");
} }
Thread.sleep(200);
i++;
} }
if (warned) {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": tag writer has finished");
}
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": closing stream");
tagWriter.writeTag(Tag.end("stream:stream"));
socket.close();
} catch (final IOException e) {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": io exception during disconnect ("+e.getMessage()+")");
} catch (final InterruptedException e) {
Log.d(Config.LOGTAG, "interrupted");
} }
}).start(); }
} catch (final IOException e) {
Log.d(Config.LOGTAG, "io exception during disconnect");
} }
} }