fail pending messages on policy violation. fixes #3735

This commit is contained in:
Daniel Gultsch 2020-05-22 18:23:53 +02:00
parent ed4d7bff92
commit 88cc097732
1 changed files with 35 additions and 16 deletions

View File

@ -111,7 +111,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) {
account.setOption(Account.OPTION_REGISTER, false); account.setOption(Account.OPTION_REGISTER, false);
Log.d(Config.LOGTAG, account.getJid().asBareJid()+": successfully registered new account on server"); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": successfully registered new account on server");
throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL); throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL);
} else { } else {
final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList( final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList(
@ -272,7 +272,7 @@ public class XmppConnection implements Runnable {
final int port = account.getPort(); final int port = account.getPort();
final boolean directTls = Resolver.useDirectTls(port); final boolean directTls = Resolver.useDirectTls(port);
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": connect to " + destination + " via Tor. directTls="+directTls); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": connect to " + destination + " via Tor. directTls=" + directTls);
localSocket = SocksSocketFactory.createSocketOverTor(destination, port); localSocket = SocksSocketFactory.createSocketOverTor(destination, port);
if (directTls) { if (directTls) {
@ -302,7 +302,7 @@ public class XmppConnection implements Runnable {
return; return;
} }
if (results.size() == 0) { if (results.size() == 0) {
Log.e(Config.LOGTAG,account.getJid().asBareJid()+": Resolver results were empty"); Log.e(Config.LOGTAG, account.getJid().asBareJid() + ": Resolver results were empty");
return; return;
} }
final Resolver.Result storedBackupResult; final Resolver.Result storedBackupResult;
@ -325,7 +325,7 @@ public class XmppConnection implements Runnable {
// if tls is true, encryption is implied and must not be started // if tls is true, encryption is implied and must not be started
features.encryptionEnabled = result.isDirectTls(); features.encryptionEnabled = result.isDirectTls();
verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null; verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null;
Log.d(Config.LOGTAG,"verified hostname "+verifiedHostname); Log.d(Config.LOGTAG, "verified hostname " + verifiedHostname);
final InetSocketAddress addr; final InetSocketAddress addr;
if (result.getIp() != null) { if (result.getIp() != null) {
addr = new InetSocketAddress(result.getIp(), result.getPort()); addr = new InetSocketAddress(result.getIp(), result.getPort());
@ -383,7 +383,7 @@ public class XmppConnection implements Runnable {
this.changeStatus(Account.State.SERVER_NOT_FOUND); this.changeStatus(Account.State.SERVER_NOT_FOUND);
} catch (final SocksSocketFactory.SocksProxyNotFoundException e) { } catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
this.changeStatus(Account.State.TOR_NOT_AVAILABLE); this.changeStatus(Account.State.TOR_NOT_AVAILABLE);
} catch (final IOException | XmlPullParserException e) { } catch (final IOException | XmlPullParserException e) {
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": " + e.getMessage()); Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": " + e.getMessage());
this.changeStatus(Account.State.OFFLINE); this.changeStatus(Account.State.OFFLINE);
this.attempt = Math.max(0, this.attempt - 1); this.attempt = Math.max(0, this.attempt - 1);
@ -590,7 +590,7 @@ public class XmppConnection implements Runnable {
if (mWaitingForSmCatchup.compareAndSet(true, false)) { if (mWaitingForSmCatchup.compareAndSet(true, false)) {
final int messageCount = mSmCatchupMessageCounter.get(); final int messageCount = mSmCatchupMessageCounter.get();
final int pendingIQs = packetCallbacks.size(); final int pendingIQs = packetCallbacks.size();
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": SM catchup complete (messages=" + messageCount + ", pending IQs="+pendingIQs+")"); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": SM catchup complete (messages=" + messageCount + ", pending IQs=" + pendingIQs + ")");
accountUiNeedsRefresh = true; accountUiNeedsRefresh = true;
if (messageCount > 0) { if (messageCount > 0) {
mXmppConnectionService.getNotificationService().finishBacklog(true, account); mXmppConnectionService.getNotificationService().finishBacklog(true, account);
@ -835,7 +835,7 @@ public class XmppConnection implements Runnable {
if (isSecure) { if (isSecure) {
register(); register();
} else { } else {
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to find STARTTLS for registration process "+ XmlHelper.printElementNames(this.streamFeatures)); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to find STARTTLS for registration process " + XmlHelper.printElementNames(this.streamFeatures));
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
} }
} else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) { } else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) {
@ -854,7 +854,7 @@ public class XmppConnection implements Runnable {
if (this.streamFeatures.hasChild("bind") && isSecure) { if (this.streamFeatures.hasChild("bind") && isSecure) {
sendBindRequest(); sendBindRequest();
} else { } else {
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to find bind feature "+ XmlHelper.printElementNames(this.streamFeatures)); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to find bind feature " + XmlHelper.printElementNames(this.streamFeatures));
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
} }
} }
@ -893,7 +893,7 @@ public class XmppConnection implements Runnable {
} }
tagWriter.writeElement(auth); tagWriter.writeElement(auth);
} else { } else {
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to find supported SASL mechanism in "+mechanisms); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to find supported SASL mechanism in " + mechanisms);
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
} }
} }
@ -918,7 +918,7 @@ public class XmppConnection implements Runnable {
sendRegistryRequest(); sendRegistryRequest();
} else { } else {
final Element error = response.getError(); final Element error = response.getError();
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": failed to pre auth. "+error); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": failed to pre auth. " + error);
throw new StateChangingError(Account.State.REGISTRATION_INVALID_TOKEN); throw new StateChangingError(Account.State.REGISTRATION_INVALID_TOKEN);
} }
}, true); }, true);
@ -1241,10 +1241,10 @@ public class XmppConnection implements Runnable {
IqPacket request = new IqPacket(IqPacket.TYPE.GET); IqPacket request = new IqPacket(IqPacket.TYPE.GET);
request.addChild("prefs", MessageArchiveService.Version.MAM_2.namespace); request.addChild("prefs", MessageArchiveService.Version.MAM_2.namespace);
sendIqPacket(request, (account, response) -> { sendIqPacket(request, (account, response) -> {
if (response.getType() == IqPacket.TYPE.RESULT) { if (response.getType() == IqPacket.TYPE.RESULT) {
Element prefs = response.findChild("prefs", MessageArchiveService.Version.MAM_2.namespace); Element prefs = response.findChild("prefs", MessageArchiveService.Version.MAM_2.namespace);
isMamPreferenceAlways = "always".equals(prefs == null ? null : prefs.getAttribute("default")); isMamPreferenceAlways = "always".equals(prefs == null ? null : prefs.getAttribute("default"));
} }
}); });
} }
@ -1338,7 +1338,8 @@ public class XmppConnection implements Runnable {
} else if (streamError.hasChild("policy-violation")) { } else if (streamError.hasChild("policy-violation")) {
this.lastConnect = SystemClock.elapsedRealtime(); this.lastConnect = SystemClock.elapsedRealtime();
final String text = streamError.findChildContent("text"); final String text = streamError.findChildContent("text");
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": policy violation. "+text); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": policy violation. " + text);
failPendingMessages(text);
throw new StateChangingException(Account.State.POLICY_VIOLATION); throw new StateChangingException(Account.State.POLICY_VIOLATION);
} else { } else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": stream error " + streamError.toString()); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": stream error " + streamError.toString());
@ -1346,6 +1347,24 @@ public class XmppConnection implements Runnable {
} }
} }
private void failPendingMessages(final String error) {
synchronized (this.mStanzaQueue) {
for (int i = 0; i < mStanzaQueue.size(); ++i) {
final AbstractAcknowledgeableStanza stanza = mStanzaQueue.valueAt(i);
if (stanza instanceof MessagePacket) {
final MessagePacket packet = (MessagePacket) stanza;
final String id = packet.getId();
final Jid to = packet.getTo();
mXmppConnectionService.markMessage(account,
to.asBareJid(),
id,
Message.STATUS_SEND_FAILED,
error);
}
}
}
}
private void sendStartStream() throws IOException { private void sendStartStream() throws IOException {
final Tag stream = Tag.start("stream:stream"); final Tag stream = Tag.start("stream:stream");
stream.setAttribute("to", account.getServer()); stream.setAttribute("to", account.getServer());
@ -1903,7 +1922,7 @@ public class XmppConnection implements Runnable {
} }
public boolean externalServiceDiscovery() { public boolean externalServiceDiscovery() {
return hasDiscoFeature(account.getDomain(),Namespace.EXTERNAL_SERVICE_DISCOVERY); return hasDiscoFeature(account.getDomain(), Namespace.EXTERNAL_SERVICE_DISCOVERY);
} }
} }
} }