Merge pull request #823 from SamWhited/issue20

Daniel Gultsch created

Verify IQ responses

Change summary

src/main/java/eu/siacs/conversations/generator/IqGenerator.java               | 16 
src/main/java/eu/siacs/conversations/parser/IqParser.java                     | 25 
src/main/java/eu/siacs/conversations/services/MessageArchiveService.java      |  2 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java      | 35 
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java                 | 70 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java        | 10 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java |  4 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java   | 14 
src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java         | 17 
src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java               | 46 
10 files changed, 123 insertions(+), 116 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/generator/IqGenerator.java 🔗

@@ -21,7 +21,7 @@ public class IqGenerator extends AbstractGenerator {
 	}
 
 	public IqPacket discoResponse(final IqPacket request) {
-		final IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT);
+		final IqPacket packet = new IqPacket(IqPacket.TYPE.RESULT);
 		packet.setId(request.getId());
 		packet.setTo(request.getFrom());
 		final Element query = packet.addChild("query",
@@ -40,7 +40,7 @@ public class IqGenerator extends AbstractGenerator {
 	}
 
 	protected IqPacket publish(final String node, final Element item) {
-		final IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
 		final Element pubsub = packet.addChild("pubsub",
 				"http://jabber.org/protocol/pubsub");
 		final Element publish = pubsub.addChild("publish");
@@ -50,7 +50,7 @@ public class IqGenerator extends AbstractGenerator {
 	}
 
 	protected IqPacket retrieve(String node, Element item) {
-		final IqPacket packet = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket packet = new IqPacket(IqPacket.TYPE.GET);
 		final Element pubsub = packet.addChild("pubsub",
 				"http://jabber.org/protocol/pubsub");
 		final Element items = pubsub.addChild("items");
@@ -100,7 +100,7 @@ public class IqGenerator extends AbstractGenerator {
 	}
 
 	public IqPacket queryMessageArchiveManagement(final MessageArchiveService.Query mam) {
-		final IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
 		final Element query = packet.query("urn:xmpp:mam:0");
 		query.setAttribute("queryid",mam.getQueryId());
 		final Data data = new Data();
@@ -119,28 +119,28 @@ public class IqGenerator extends AbstractGenerator {
 		return packet;
 	}
 	public IqPacket generateGetBlockList() {
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
 		iq.addChild("blocklist", Xmlns.BLOCKING);
 
 		return iq;
 	}
 
 	public IqPacket generateSetBlockRequest(final Jid jid) {
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 		final Element block = iq.addChild("block", Xmlns.BLOCKING);
 		block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
 		return iq;
 	}
 
 	public IqPacket generateSetUnblockRequest(final Jid jid) {
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 		final Element block = iq.addChild("unblock", Xmlns.BLOCKING);
 		block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
 		return iq;
 	}
 
 	public IqPacket generateSetPassword(final Account account, final String newPassword) {
-		final IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
 		packet.setTo(account.getServer());
 		final Element query = packet.addChild("query", Xmlns.REGISTER);
 		final Jid jid = account.getJid();

src/main/java/eu/siacs/conversations/parser/IqParser.java 🔗

@@ -71,24 +71,17 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
 		return super.avatarData(items);
 	}
 
-	public static boolean fromServer(final Account account, final IqPacket packet) {
-		return packet.getFrom() == null
-				|| packet.getFrom().equals(account.getServer())
-				|| packet.getFrom().equals(account.getJid().toBareJid())
-				|| packet.getFrom().equals(account.getJid());
-	}
-
 	@Override
 	public void onIqPacketReceived(final Account account, final IqPacket packet) {
-		if (packet.hasChild("query", Xmlns.ROSTER) && fromServer(account, packet)) {
+		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) {
+			if (packet.getType() == IqPacket.TYPE.RESULT) {
 				account.getRoster().markAllAsNotInRoster();
 			}
 			this.rosterItems(account, query);
 		} else if ((packet.hasChild("block", Xmlns.BLOCKING) || packet.hasChild("blocklist", Xmlns.BLOCKING)) &&
-				fromServer(account, packet)) {
+				packet.fromServer(account)) {
 			// Block list or block push.
 			Log.d(Config.LOGTAG, "Received blocklist update from server");
 			final Element blocklist = packet.findChild("blocklist", Xmlns.BLOCKING);
@@ -97,7 +90,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
 				(block != null ? block.getChildren() : null);
 			// If this is a response to a blocklist query, clear the block list and replace with the new one.
 			// Otherwise, just update the existing blocklist.
-			if (packet.getType() == IqPacket.TYPE_RESULT) {
+			if (packet.getType() == IqPacket.TYPE.RESULT) {
 				account.clearBlocklist();
 			}
 			if (items != null) {
@@ -116,7 +109,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
 			// Update the UI
 			mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED);
 		} else if (packet.hasChild("unblock", Xmlns.BLOCKING) &&
-				fromServer(account, packet) && packet.getType() == IqPacket.TYPE_SET) {
+				packet.fromServer(account) && packet.getType() == IqPacket.TYPE.SET) {
 			Log.d(Config.LOGTAG, "Received unblock update from server");
 			final Collection<Element> items = packet.findChild("unblock", Xmlns.BLOCKING).getChildren();
 			if (items.size() == 0) {
@@ -144,12 +137,12 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
 				.discoResponse(packet);
 			account.getXmppConnection().sendIqPacket(response, null);
 		} else if (packet.hasChild("ping", "urn:xmpp:ping")) {
-			final IqPacket response = packet.generateResponse(IqPacket.TYPE_RESULT);
+			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)) {
-				final IqPacket response = packet.generateResponse(IqPacket.TYPE_ERROR);
+			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",

src/main/java/eu/siacs/conversations/services/MessageArchiveService.java 🔗

@@ -111,7 +111,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
 			this.mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
 				@Override
 				public void onIqPacketReceived(Account account, IqPacket packet) {
-					if (packet.getType() == IqPacket.TYPE_ERROR) {
+					if (packet.getType() == IqPacket.TYPE.ERROR) {
 						Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": error executing mam: " + packet.toString());
 						finalizeQuery(query);
 					}

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -84,7 +84,6 @@ import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
 import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
 import eu.siacs.conversations.xmpp.OnStatusChanged;
 import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
-import eu.siacs.conversations.xmpp.PacketReceived;
 import eu.siacs.conversations.xmpp.XmppConnection;
 import eu.siacs.conversations.xmpp.forms.Data;
 import eu.siacs.conversations.xmpp.forms.Field;
@@ -787,7 +786,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	}
 
 	public void fetchRosterFromServer(final Account account) {
-		final IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET);
 		if (!"".equals(account.getRosterVersion())) {
 			Log.d(Config.LOGTAG, account.getJid().toBareJid()
 					+ ": fetching roster version " + account.getRosterVersion());
@@ -800,7 +799,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	}
 
 	public void fetchBookmarks(final Account account) {
-		final IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET);
 		final Element query = iqPacket.query("jabber:iq:private");
 		query.addChild("storage", "storage:bookmarks");
 		final OnIqPacketReceived callback = new OnIqPacketReceived() {
@@ -835,7 +834,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	}
 
 	public void pushBookmarks(Account account) {
-		IqPacket iqPacket = new IqPacket(IqPacket.TYPE_SET);
+		IqPacket iqPacket = new IqPacket(IqPacket.TYPE.SET);
 		Element query = iqPacket.query("jabber:iq:private");
 		Element storage = query.addChild("storage", "storage:bookmarks");
 		for (Bookmark bookmark : account.getBookmarks()) {
@@ -979,7 +978,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 						query.setCallback(callback);
 					}
 					callback.informUser(R.string.fetching_history_from_server);
-				}
+						}
 			}
 		}).start();
 	}
@@ -1107,7 +1106,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		sendIqPacket(account, iq, new OnIqPacketReceived() {
 			@Override
 			public void onIqPacketReceived(final Account account, final IqPacket packet) {
-				if (packet.getType() == IqPacket.TYPE_RESULT) {
+				if (packet.getType() == IqPacket.TYPE.RESULT) {
 					account.setPassword(newPassword);
 					databaseBackend.updateAccount(account);
 					callback.onPasswordChangeSucceeded();
@@ -1500,13 +1499,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	}
 
 	public void pushConferenceConfiguration(final Conversation conversation,final Bundle options, final OnConferenceOptionsPushed callback) {
-		IqPacket request = new IqPacket(IqPacket.TYPE_GET);
+		IqPacket request = new IqPacket(IqPacket.TYPE.GET);
 		request.setTo(conversation.getJid().toBareJid());
 		request.query("http://jabber.org/protocol/muc#owner");
 		sendIqPacket(conversation.getAccount(),request,new OnIqPacketReceived() {
 			@Override
 			public void onIqPacketReceived(Account account, IqPacket packet) {
-				if (packet.getType() != IqPacket.TYPE_ERROR) {
+				if (packet.getType() != IqPacket.TYPE.ERROR) {
 					Data data = Data.parse(packet.query().findChild("x", "jabber:x:data"));
 					for (Field field : data.getFields()) {
 						if (options.containsKey(field.getName())) {
@@ -1514,13 +1513,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 						}
 					}
 					data.submit();
-					IqPacket set = new IqPacket(IqPacket.TYPE_SET);
+					IqPacket set = new IqPacket(IqPacket.TYPE.SET);
 					set.setTo(conversation.getJid().toBareJid());
 					set.query("http://jabber.org/protocol/muc#owner").addChild(data);
 					sendIqPacket(account, set, new OnIqPacketReceived() {
 						@Override
 						public void onIqPacketReceived(Account account, IqPacket packet) {
-							if (packet.getType() == IqPacket.TYPE_RESULT) {
+							if (packet.getType() == IqPacket.TYPE.RESULT) {
 								if (callback != null) {
 									callback.onPushSucceeded();
 								}
@@ -1662,7 +1661,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 			final boolean sendUpdates = contact
 				.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)
 				&& contact.getOption(Contact.Options.PREEMPTIVE_GRANT);
-			final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+			final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 			iq.query(Xmlns.ROSTER).addChild(contact.asElement());
 			account.getXmppConnection().sendIqPacket(iq, null);
 			if (sendUpdates) {
@@ -1702,7 +1701,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 
 				@Override
 				public void onIqPacketReceived(Account account, IqPacket result) {
-					if (result.getType() == IqPacket.TYPE_RESULT) {
+					if (result.getType() == IqPacket.TYPE.RESULT) {
 						final IqPacket packet = XmppConnectionService.this.mIqGenerator
 							.publishAvatarMetadata(avatar);
 						sendIqPacket(account, packet, new OnIqPacketReceived() {
@@ -1710,7 +1709,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 							@Override
 							public void onIqPacketReceived(Account account,
 									IqPacket result) {
-								if (result.getType() == IqPacket.TYPE_RESULT) {
+								if (result.getType() == IqPacket.TYPE.RESULT) {
 									if (account.setAvatar(avatar.getFilename())) {
 										databaseBackend.updateAccount(account);
 									}
@@ -1747,7 +1746,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 			public void onIqPacketReceived(Account account, IqPacket result) {
 				final String ERROR = account.getJid().toBareJid()
 					+ ": fetching avatar for " + avatar.owner + " failed ";
-				if (result.getType() == IqPacket.TYPE_RESULT) {
+				if (result.getType() == IqPacket.TYPE.RESULT) {
 					avatar.image = mIqParser.avatarData(result);
 					if (avatar.image != null) {
 						if (getFileBackend().save(avatar)) {
@@ -1801,7 +1800,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 
 			@Override
 			public void onIqPacketReceived(Account account, IqPacket packet) {
-				if (packet.getType() == IqPacket.TYPE_RESULT) {
+				if (packet.getType() == IqPacket.TYPE.RESULT) {
 					Element pubsub = packet.findChild("pubsub",
 							"http://jabber.org/protocol/pubsub");
 					if (pubsub != null) {
@@ -1835,7 +1834,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		contact.setOption(Contact.Options.DIRTY_DELETE);
 		Account account = contact.getAccount();
 		if (account.getStatus() == Account.State.ONLINE) {
-			IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+			IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 			Element item = iq.query(Xmlns.ROSTER).addChild("item");
 			item.setAttribute("jid", contact.getJid().toString());
 			item.setAttribute("subscription", "remove");
@@ -2202,7 +2201,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 
 				@Override
 				public void onIqPacketReceived(final Account account, final IqPacket packet) {
-					if (packet.getType() == IqPacket.TYPE_RESULT) {
+					if (packet.getType() == IqPacket.TYPE.RESULT) {
 						account.getBlocklist().add(jid);
 						updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED);
 					}
@@ -2217,7 +2216,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 			this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetUnblockRequest(jid), new OnIqPacketReceived() {
 				@Override
 				public void onIqPacketReceived(final Account account, final IqPacket packet) {
-					if (packet.getType() == IqPacket.TYPE_RESULT) {
+					if (packet.getType() == IqPacket.TYPE.RESULT) {
 						account.getBlocklist().remove(jid);
 						updateBlocklistUi(OnUpdateBlocklist.Status.UNBLOCKED);
 					}

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -9,6 +9,7 @@ import android.os.PowerManager.WakeLock;
 import android.os.SystemClock;
 import android.preference.PreferenceManager;
 import android.util.Log;
+import android.util.Pair;
 import android.util.SparseArray;
 
 import org.apache.http.conn.ssl.StrictHostnameVerifier;
@@ -104,7 +105,7 @@ public class XmppConnection implements Runnable {
 	private long lastConnect = 0;
 	private long lastSessionStarted = 0;
 	private int attempt = 0;
-	private final Map<String, OnIqPacketReceived> packetCallbacks = new Hashtable<>();
+	private final Map<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>();
 	private OnPresencePacketReceived presenceListener = null;
 	private OnJinglePacketReceived jingleListener = null;
 	private OnIqPacketReceived unregisteredIqListener = null;
@@ -372,7 +373,7 @@ public class XmppConnection implements Runnable {
 
 	private void sendInitialPing() {
 		Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": sending intial ping");
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
 		iq.setFrom(account.getJid());
 		iq.addChild("ping", "urn:xmpp:ping");
 		this.sendIqPacket(iq, new OnIqPacketReceived() {
@@ -444,13 +445,26 @@ public class XmppConnection implements Runnable {
 							}
 						} else {
 							if (packetCallbacks.containsKey(packet.getId())) {
-								packetCallbacks.get(packet.getId()).onIqPacketReceived(account, packet);
-								packetCallbacks.remove(packet.getId());
-							} else if ((packet.getType() == IqPacket.TYPE_GET || packet
-										.getType() == IqPacket.TYPE_SET)
+								final Pair<IqPacket, OnIqPacketReceived> packetCallbackDuple = packetCallbacks.get(packet.getId());
+								// Packets to the server should have responses from the server
+								if (packetCallbackDuple.first.toServer(account)) {
+									if (packet.fromServer(account)) {
+										packetCallbackDuple.second
+											.onIqPacketReceived(account, packet);
+										packetCallbacks.remove(packet.getId());
+									}
+								} else {
+									if (packet.getFrom().equals(packetCallbackDuple.first.getTo())) {
+										packetCallbackDuple.second
+											.onIqPacketReceived(account, packet);
+										packetCallbacks.remove(packet.getId());
+									}
+								}
+							} else if ((packet.getType() == IqPacket.TYPE.GET || packet
+										.getType() == IqPacket.TYPE.SET)
 									&& this.unregisteredIqListener != null) {
 								this.unregisteredIqListener.onIqPacketReceived(account, packet);
-							}
+									}
 						}
 	}
 
@@ -479,19 +493,19 @@ public class XmppConnection implements Runnable {
 	}
 
 	private void switchOverToTls(final Tag currentTag) throws XmlPullParserException, IOException {
-        tagReader.readTag();
-        try {
+		tagReader.readTag();
+		try {
 			final SSLContext sc = SSLContext.getInstance("TLS");
 			sc.init(null,new X509TrustManager[]{this.mXmppConnectionService.getMemorizingTrustManager()},mXmppConnectionService.getRNG());
 			final SSLSocketFactory factory = sc.getSocketFactory();
 			final HostnameVerifier verifier = this.mXmppConnectionService.getMemorizingTrustManager().wrapHostnameVerifier(new StrictHostnameVerifier());
-            final InetAddress address = socket == null ? null : socket.getInetAddress();
+			final InetAddress address = socket == null ? null : socket.getInetAddress();
 
 			if (factory == null || address == null || verifier == null) {
 				throw new IOException("could not setup ssl");
 			}
 
-            final SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,address.getHostAddress(), socket.getPort(),true);
+			final SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,address.getHostAddress(), socket.getPort(),true);
 
 			if (sslSocket == null) {
 				throw new IOException("could not initialize ssl socket");
@@ -506,13 +520,13 @@ public class XmppConnection implements Runnable {
 				supportedProtocols.remove("SSLv3");
 				supportProtocols = new String[supportedProtocols.size()];
 				supportedProtocols.toArray(supportProtocols);
-            }
+			}
 			sslSocket.setEnabledProtocols(supportProtocols);
 
-            if (!verifier.verify(account.getServer().getDomainpart(),sslSocket.getSession())) {
-                Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
-                disconnect(true);
-                changeStatus(Account.State.SECURITY_ERROR);
+			if (!verifier.verify(account.getServer().getDomainpart(),sslSocket.getSession())) {
+				Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
+				disconnect(true);
+				changeStatus(Account.State.SECURITY_ERROR);
 			}
 			tagReader.setInputStream(sslSocket.getInputStream());
 			tagWriter.setOutputStream(sslSocket.getOutputStream());
@@ -521,11 +535,11 @@ public class XmppConnection implements Runnable {
 			enabledEncryption = true;
 			processStream(tagReader.readTag());
 			sslSocket.close();
-        } catch (final NoSuchAlgorithmException | KeyManagementException e1) {
+		} catch (final NoSuchAlgorithmException | KeyManagementException e1) {
 			Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
 			disconnect(true);
 			changeStatus(Account.State.SECURITY_ERROR);
-        }
+		}
 	}
 
 	private void processStreamFeatures(final Tag currentTag)
@@ -598,7 +612,7 @@ public class XmppConnection implements Runnable {
 	}
 
 	private void sendRegistryRequest() {
-		final IqPacket register = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket register = new IqPacket(IqPacket.TYPE.GET);
 		register.query("jabber:iq:register");
 		register.setTo(account.getServer());
 		sendIqPacket(register, new OnIqPacketReceived() {
@@ -608,7 +622,7 @@ public class XmppConnection implements Runnable {
 				final Element instructions = packet.query().findChild("instructions");
 				if (packet.query().hasChild("username")
 						&& (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 password = new Element("password")
@@ -619,7 +633,7 @@ public class XmppConnection implements Runnable {
 
 						@Override
 						public void onIqPacketReceived(final Account account, final IqPacket packet) {
-							if (packet.getType() == IqPacket.TYPE_RESULT) {
+							if (packet.getType() == IqPacket.TYPE.RESULT) {
 								account.setOption(Account.OPTION_REGISTER,
 										false);
 								changeStatus(Account.State.REGISTRATION_SUCCESSFUL);
@@ -646,7 +660,7 @@ public class XmppConnection implements Runnable {
 	}
 
 	private void sendBindRequest() {
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 		iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind")
 			.addChild("resource").setContent(account.getResource());
 		this.sendUnmodifiedIqPacket(iq, new OnIqPacketReceived() {
@@ -693,7 +707,7 @@ public class XmppConnection implements Runnable {
 		});
 		if (this.streamFeatures.hasChild("session")) {
 			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": sending deprecated session");
-			final IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
+			final IqPacket startSession = new IqPacket(IqPacket.TYPE.SET);
 			startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session");
 			this.sendUnmodifiedIqPacket(startSession, null);
 		}
@@ -705,7 +719,7 @@ public class XmppConnection implements Runnable {
 				enableAdvancedStreamFeatures();
 			}
 		} else {
-			final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+			final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
 			iq.setTo(server.toDomainJid());
 			iq.query("http://jabber.org/protocol/disco#info");
 			this.sendIqPacket(iq, new OnIqPacketReceived() {
@@ -750,7 +764,7 @@ public class XmppConnection implements Runnable {
 	}
 
 	private void sendServiceDiscoveryItems(final Jid server) {
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
 		iq.setTo(server.toDomainJid());
 		iq.query("http://jabber.org/protocol/disco#items");
 		this.sendIqPacket(iq, new OnIqPacketReceived() {
@@ -771,7 +785,7 @@ public class XmppConnection implements Runnable {
 	}
 
 	private void sendEnableCarbons() {
-		final IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+		final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 		iq.addChild("enable", "urn:xmpp:carbons:2");
 		this.sendIqPacket(iq, new OnIqPacketReceived() {
 
@@ -831,7 +845,7 @@ public class XmppConnection implements Runnable {
 			if (packet.getId() == null) {
 				packet.setId(nextRandomId());
 			}
-			packetCallbacks.put(packet.getId(), callback);
+			packetCallbacks.put(packet.getId(), new Pair<>(packet, callback));
 		}
 		this.sendPacket(packet);
 	}
@@ -861,7 +875,7 @@ public class XmppConnection implements Runnable {
 		if (streamFeatures.hasChild("sm")) {
 			tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
 		} else {
-			final IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+			final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
 			iq.setFrom(account.getJid());
 			iq.addChild("ping", "urn:xmpp:ping");
 			this.sendIqPacket(iq, null);

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java 🔗

@@ -75,7 +75,7 @@ public class JingleConnection implements Downloadable {
 
 		@Override
 		public void onIqPacketReceived(Account account, IqPacket packet) {
-			if (packet.getType() == IqPacket.TYPE_ERROR) {
+			if (packet.getType() == IqPacket.TYPE.ERROR) {
 				fail();
 			}
 		}
@@ -191,10 +191,10 @@ public class JingleConnection implements Downloadable {
 		}
 		IqPacket response;
 		if (returnResult) {
-			response = packet.generateResponse(IqPacket.TYPE_RESULT);
+			response = packet.generateResponse(IqPacket.TYPE.RESULT);
 
 		} else {
-			response = packet.generateResponse(IqPacket.TYPE_ERROR);
+			response = packet.generateResponse(IqPacket.TYPE.ERROR);
 		}
 		account.getXmppConnection().sendIqPacket(response, null);
 	}
@@ -552,7 +552,7 @@ public class JingleConnection implements Downloadable {
 					Log.d(Config.LOGTAG, "candidate "
 							+ connection.getCandidate().getCid()
 							+ " was our proxy. going to activate");
-					IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
+					IqPacket activation = new IqPacket(IqPacket.TYPE.SET);
 					activation.setTo(connection.getCandidate().getJid());
 					activation.query("http://jabber.org/protocol/bytestreams")
 							.setAttribute("sid", this.getSessionId());
@@ -564,7 +564,7 @@ public class JingleConnection implements Downloadable {
 								@Override
 								public void onIqPacketReceived(Account account,
 										IqPacket packet) {
-									if (packet.getType() == IqPacket.TYPE_ERROR) {
+									if (packet.getType() == IqPacket.TYPE.ERROR) {
 										onProxyActivated.failed();
 									} else {
 										onProxyActivated.success();

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java 🔗

@@ -46,7 +46,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
 					return;
 				}
 			}
-			IqPacket response = packet.generateResponse(IqPacket.TYPE_ERROR);
+			IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR);
 			Element error = response.addChild("error");
 			error.setAttribute("type", "cancel");
 			error.addChild("item-not-found",
@@ -84,7 +84,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
 			final String proxy = account.getXmppConnection()
 					.findDiscoItemByFeature(xmlns);
 			if (proxy != null) {
-				IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+				IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
 				iq.setAttribute("to", proxy);
 				iq.query(xmlns);
 				account.getXmppConnection().sendIqPacket(iq,

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java 🔗

@@ -44,7 +44,7 @@ public class JingleInbandTransport extends JingleTransport {
 	private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() {
 		@Override
 		public void onIqPacketReceived(Account account, IqPacket packet) {
-			if (connected && packet.getType() == IqPacket.TYPE_RESULT) {
+			if (connected && packet.getType() == IqPacket.TYPE.RESULT) {
 				sendNextBlock();
 			}
 		}
@@ -60,7 +60,7 @@ public class JingleInbandTransport extends JingleTransport {
 	}
 
 	public void connect(final OnTransportConnected callback) {
-		IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+		IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 		iq.setTo(this.counterpart);
 		Element open = iq.addChild("open", "http://jabber.org/protocol/ibb");
 		open.setAttribute("sid", this.sessionId);
@@ -73,7 +73,7 @@ public class JingleInbandTransport extends JingleTransport {
 					@Override
 					public void onIqPacketReceived(Account account,
 							IqPacket packet) {
-						if (packet.getType() == IqPacket.TYPE_ERROR) {
+						if (packet.getType() == IqPacket.TYPE.ERROR) {
 							callback.failed();
 						} else {
 							callback.established();
@@ -157,7 +157,7 @@ public class JingleInbandTransport extends JingleTransport {
 				this.remainingSize -= count;
 				this.digest.update(buffer);
 				String base64 = Base64.encodeToString(buffer, Base64.NO_WRAP);
-				IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+				IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
 				iq.setTo(this.counterpart);
 				Element data = iq.addChild("data",
 						"http://jabber.org/protocol/ibb");
@@ -208,15 +208,15 @@ public class JingleInbandTransport extends JingleTransport {
 				established = true;
 				connected = true;
 				this.account.getXmppConnection().sendIqPacket(
-						packet.generateResponse(IqPacket.TYPE_RESULT), null);
+						packet.generateResponse(IqPacket.TYPE.RESULT), null);
 			} else {
 				this.account.getXmppConnection().sendIqPacket(
-						packet.generateResponse(IqPacket.TYPE_ERROR), null);
+						packet.generateResponse(IqPacket.TYPE.ERROR), null);
 			}
 		} else if (connected && payload.getName().equals("data")) {
 			this.receiveNextBlock(payload.getContent());
 			this.account.getXmppConnection().sendIqPacket(
-					packet.generateResponse(IqPacket.TYPE_RESULT), null);
+					packet.generateResponse(IqPacket.TYPE.RESULT), null);
 		} else {
 			// TODO some sort of exception
 		}

src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java 🔗

@@ -1,11 +1,12 @@
 package eu.siacs.conversations.xmpp.stanzas;
 
+import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.xml.Element;
 import eu.siacs.conversations.xmpp.jid.Jid;
 
 public class AbstractStanza extends Element {
 
-	protected AbstractStanza(String name) {
+	protected AbstractStanza(final String name) {
 		super(name);
 	}
 
@@ -36,4 +37,18 @@ public class AbstractStanza extends Element {
 	public void setId(final String id) {
 		setAttribute("id", id);
 	}
+
+	public boolean fromServer(final Account account) {
+		return getFrom() == null
+			|| getFrom().equals(account.getServer())
+			|| getFrom().equals(account.getJid().toBareJid())
+			|| getFrom().equals(account.getJid());
+	}
+
+	public boolean toServer(final Account account) {
+		return getTo() == null
+			|| getTo().equals(account.getServer())
+			|| getTo().equals(account.getJid().toBareJid())
+			|| getTo().equals(account.getJid());
+	}
 }

src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java 🔗

@@ -4,32 +4,18 @@ import eu.siacs.conversations.xml.Element;
 
 public class IqPacket extends AbstractStanza {
 
-	public static final int TYPE_ERROR = -1;
-	public static final int TYPE_SET = 0;
-	public static final int TYPE_RESULT = 1;
-	public static final int TYPE_GET = 2;
-
-	private IqPacket(final String name) {
-		super(name);
+	public static enum TYPE {
+		ERROR,
+		SET,
+		RESULT,
+		GET,
+		INVALID
 	}
 
-	public IqPacket(final int type) {
+	public IqPacket(final TYPE type) {
 		super("iq");
-		switch (type) {
-			case TYPE_SET:
-				this.setAttribute("type", "set");
-				break;
-			case TYPE_GET:
-				this.setAttribute("type", "get");
-				break;
-			case TYPE_RESULT:
-				this.setAttribute("type", "result");
-				break;
-			case TYPE_ERROR:
-				this.setAttribute("type", "error");
-				break;
-			default:
-				break;
+		if (type != TYPE.INVALID) {
+			this.setAttribute("type", type.toString().toLowerCase());
 		}
 	}
 
@@ -51,23 +37,23 @@ public class IqPacket extends AbstractStanza {
 		return query();
 	}
 
-	public int getType() {
+	public TYPE getType() {
 		final String type = getAttribute("type");
 		switch (type) {
 			case "error":
-				return TYPE_ERROR;
+				return TYPE.ERROR;
 			case "result":
-				return TYPE_RESULT;
+				return TYPE.RESULT;
 			case "set":
-				return TYPE_SET;
+				return TYPE.SET;
 			case "get":
-				return TYPE_GET;
+				return TYPE.GET;
 			default:
-				return 1000;
+				return TYPE.INVALID;
 		}
 	}
 
-	public IqPacket generateResponse(final int type) {
+	public IqPacket generateResponse(final TYPE type) {
 		final IqPacket packet = new IqPacket(type);
 		packet.setTo(this.getFrom());
 		packet.setId(this.getId());