warn when attempting to write stanza to an unbound stream

This commit is contained in:
Daniel Gultsch 2018-02-20 17:03:44 +01:00
parent 72cf702e75
commit e7094af9d5
2 changed files with 29 additions and 21 deletions

View file

@ -3583,7 +3583,7 @@ public class XmppConnectionService extends Service {
final XmppConnection connection = account.getXmppConnection(); final XmppConnection connection = account.getXmppConnection();
if (connection != null) { if (connection != null) {
IqPacket request = mIqGenerator.generateCreateAccountWithCaptcha(account, id, data); IqPacket request = mIqGenerator.generateCreateAccountWithCaptcha(account, id, data);
connection.sendUnmodifiedIqPacket(request, connection.registrationResponseListener); connection.sendUnmodifiedIqPacket(request, connection.registrationResponseListener,true);
} }
} }

View file

@ -107,9 +107,9 @@ public class XmppConnection implements Runnable {
private XmlReader tagReader; private XmlReader tagReader;
private TagWriter tagWriter = new TagWriter(); private TagWriter tagWriter = new TagWriter();
private final Features features = new Features(this); private final Features features = new Features(this);
private boolean needsBinding = true;
private boolean shouldAuthenticate = true; private boolean shouldAuthenticate = true;
private boolean inSmacksSession = false; private boolean inSmacksSession = false;
private boolean isBound = false;
private Element streamFeatures; private Element streamFeatures;
private final HashMap<Jid, ServiceDiscoveryResult> disco = new HashMap<>(); private final HashMap<Jid, ServiceDiscoveryResult> disco = new HashMap<>();
@ -273,11 +273,12 @@ public class XmppConnection implements Runnable {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": connecting"); Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": connecting");
features.encryptionEnabled = false; features.encryptionEnabled = false;
inSmacksSession = false; inSmacksSession = false;
isBound = false;
this.attempt++; this.attempt++;
this.verifiedHostname = null; //will be set if user entered hostname is being used or hostname was verified with dnssec this.verifiedHostname = null; //will be set if user entered hostname is being used or hostname was verified with dnssec
try { try {
Socket localSocket; Socket localSocket;
shouldAuthenticate = needsBinding = !account.isOptionSet(Account.OPTION_REGISTER); shouldAuthenticate = !account.isOptionSet(Account.OPTION_REGISTER);
this.changeStatus(Account.State.CONNECTING); this.changeStatus(Account.State.CONNECTING);
final boolean useTor = mXmppConnectionService.useTorToConnect() || account.isOnion(); final boolean useTor = mXmppConnectionService.useTorToConnect() || account.isOnion();
final boolean extended = mXmppConnectionService.showExtendedConnectionOptions(); final boolean extended = mXmppConnectionService.showExtendedConnectionOptions();
@ -602,6 +603,7 @@ public class XmppConnection implements Runnable {
tagWriter.writeStanzaAsync(r); tagWriter.writeStanzaAsync(r);
} else if (nextTag.isStart("resumed")) { } else if (nextTag.isStart("resumed")) {
this.inSmacksSession = true; this.inSmacksSession = true;
this.isBound = true;
this.tagWriter.writeStanzaAsync(new RequestPacket(smVersion)); this.tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
lastPacketReceived = SystemClock.elapsedRealtime(); lastPacketReceived = SystemClock.elapsedRealtime();
final Element resumed = tagReader.readElement(nextTag); final Element resumed = tagReader.readElement(nextTag);
@ -878,6 +880,7 @@ public class XmppConnection implements Runnable {
private void processStreamFeatures(final Tag currentTag) throws XmlPullParserException, IOException { private void processStreamFeatures(final Tag currentTag) throws XmlPullParserException, IOException {
this.streamFeatures = tagReader.readElement(currentTag); this.streamFeatures = tagReader.readElement(currentTag);
final boolean isSecure = features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS; final boolean isSecure = features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS;
final boolean needsBinding = !isBound && !account.isOptionSet(Account.OPTION_REGISTER);
if (this.streamFeatures.hasChild("starttls") && !features.encryptionEnabled) { if (this.streamFeatures.hasChild("starttls") && !features.encryptionEnabled) {
sendStartTLS(); sendStartTLS();
} else if (this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) { } else if (this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) {
@ -975,7 +978,7 @@ public class XmppConnection implements Runnable {
register.query("jabber:iq:register").addChild(username); register.query("jabber:iq:register").addChild(username);
register.query().addChild(password); register.query().addChild(password);
register.setFrom(account.getJid().toBareJid()); register.setFrom(account.getJid().toBareJid());
sendUnmodifiedIqPacket(register, registrationResponseListener); sendUnmodifiedIqPacket(register, registrationResponseListener, true);
} else if (query.hasChild("x", Namespace.DATA)) { } else if (query.hasChild("x", Namespace.DATA)) {
final Data data = Data.parse(query.findChild("x", Namespace.DATA)); final Data data = Data.parse(query.findChild("x", Namespace.DATA));
final Element blob = query.findChild("data", "urn:xmpp:bob"); final Element blob = query.findChild("data", "urn:xmpp:bob");
@ -1025,7 +1028,7 @@ public class XmppConnection implements Runnable {
throw new StateChangingError(Account.State.REGISTRATION_FAILED); throw new StateChangingError(Account.State.REGISTRATION_FAILED);
} }
} }
}); },true);
} }
private void setAccountCreationFailed(String url) { private void setAccountCreationFailed(String url) {
@ -1065,7 +1068,6 @@ public class XmppConnection implements Runnable {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": interrupted while waiting for DB restore during bind"); Log.d(Config.LOGTAG,account.getJid().toBareJid()+": interrupted while waiting for DB restore during bind");
return; return;
} }
needsBinding = false;
clearIqCallbacks(); clearIqCallbacks();
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET); final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
iq.addChild("bind", Namespace.BIND).addChild("resource").setContent(account.getResource()); iq.addChild("bind", Namespace.BIND).addChild("resource").setContent(account.getResource());
@ -1077,6 +1079,7 @@ public class XmppConnection implements Runnable {
} }
final Element bind = packet.findChild("bind"); final Element bind = packet.findChild("bind");
if (bind != null && packet.getType() == IqPacket.TYPE.RESULT) { if (bind != null && packet.getType() == IqPacket.TYPE.RESULT) {
isBound = true;
final Element jid = bind.findChild("jid"); final Element jid = bind.findChild("jid");
if (jid != null && jid.getContent() != null) { if (jid != null && jid.getContent() != null) {
try { try {
@ -1114,7 +1117,7 @@ public class XmppConnection implements Runnable {
} }
throw new StateChangingError(Account.State.BIND_FAILURE); throw new StateChangingError(Account.State.BIND_FAILURE);
} }
}); },true);
} }
private void clearIqCallbacks() { private void clearIqCallbacks() {
@ -1154,16 +1157,13 @@ public class XmppConnection implements Runnable {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": sending legacy session to outdated server"); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": sending legacy session to outdated server");
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"); startSession.addChild("session", "urn:ietf:params:xml:ns:xmpp-session");
this.sendUnmodifiedIqPacket(startSession, new OnIqPacketReceived() { this.sendUnmodifiedIqPacket(startSession, (account, packet) -> {
@Override if (packet.getType() == IqPacket.TYPE.RESULT) {
public void onIqPacketReceived(Account account, IqPacket packet) { sendPostBindInitialization();
if (packet.getType() == IqPacket.TYPE.RESULT) { } else if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
sendPostBindInitialization(); throw new StateChangingError(Account.State.SESSION_FAILURE);
} else if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
throw new StateChangingError(Account.State.SESSION_FAILURE);
}
} }
}); },true);
} }
private void sendPostBindInitialization() { private void sendPostBindInitialization() {
@ -1369,10 +1369,10 @@ public class XmppConnection implements Runnable {
public String sendIqPacket(final IqPacket packet, final OnIqPacketReceived callback) { public String sendIqPacket(final IqPacket packet, final OnIqPacketReceived callback) {
packet.setFrom(account.getJid()); packet.setFrom(account.getJid());
return this.sendUnmodifiedIqPacket(packet, callback); return this.sendUnmodifiedIqPacket(packet, callback, false);
} }
public synchronized String sendUnmodifiedIqPacket(final IqPacket packet, final OnIqPacketReceived callback) { public synchronized String sendUnmodifiedIqPacket(final IqPacket packet, final OnIqPacketReceived callback, boolean force) {
if (packet.getId() == null) { if (packet.getId() == null) {
packet.setAttribute("id", nextRandomId()); packet.setAttribute("id", nextRandomId());
} }
@ -1381,7 +1381,7 @@ public class XmppConnection implements Runnable {
packetCallbacks.put(packet.getId(), new Pair<>(packet, callback)); packetCallbacks.put(packet.getId(), new Pair<>(packet, callback));
} }
} }
this.sendPacket(packet); this.sendPacket(packet,force);
return packet.getId(); return packet.getId();
} }
@ -1394,13 +1394,21 @@ public class XmppConnection implements Runnable {
} }
private synchronized void sendPacket(final AbstractStanza packet) { private synchronized void sendPacket(final AbstractStanza packet) {
sendPacket(packet,false);
}
private synchronized void sendPacket(final AbstractStanza packet, final boolean force) {
if (stanzasSent == Integer.MAX_VALUE) { if (stanzasSent == Integer.MAX_VALUE) {
resetStreamId(); resetStreamId();
disconnect(true); disconnect(true);
return; return;
} }
synchronized (this.mStanzaQueue) { synchronized (this.mStanzaQueue) {
tagWriter.writeStanzaAsync(packet); if (force || isBound) {
tagWriter.writeStanzaAsync(packet);
} else {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+" do not write stanza to unbound stream "+packet.toString());
}
if (packet instanceof AbstractAcknowledgeableStanza) { if (packet instanceof AbstractAcknowledgeableStanza) {
AbstractAcknowledgeableStanza stanza = (AbstractAcknowledgeableStanza) packet; AbstractAcknowledgeableStanza stanza = (AbstractAcknowledgeableStanza) packet;
@ -1413,7 +1421,7 @@ public class XmppConnection implements Runnable {
++stanzasSent; ++stanzasSent;
this.mStanzaQueue.append(stanzasSent, stanza); this.mStanzaQueue.append(stanzasSent, stanza);
if (stanza instanceof MessagePacket && stanza.getId() != null && getFeatures().sm()) { if (stanza instanceof MessagePacket && stanza.getId() != null && inSmacksSession) {
if (Config.EXTENDED_SM_LOGGING) { if (Config.EXTENDED_SM_LOGGING) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": requesting ack for message stanza #" + stanzasSent); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": requesting ack for message stanza #" + stanzasSent);
} }