aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs/conversations/xmpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu/siacs/conversations/xmpp')
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java89
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java32
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java1
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java32
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java5
5 files changed, 126 insertions, 33 deletions
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index 19e271b2..48dc2150 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -242,6 +242,13 @@ public class XmppConnection implements Runnable {
@Override
public void run() {
+ try {
+ if (socket != null) {
+ socket.close();
+ }
+ } catch (final IOException ignored) {
+
+ }
connect();
}
@@ -515,8 +522,9 @@ public class XmppConnection implements Runnable {
sslSocket.setEnabledProtocols(supportProtocols);
- final String[] cipherSuites = CryptoHelper.getSupportedCipherSuites(
+ final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites(
sslSocket.getSupportedCipherSuites());
+ //Log.d(Config.LOGTAG, "Using ciphers: " + Arrays.toString(cipherSuites));
if (cipherSuites.length > 0) {
sslSocket.setEnabledCipherSuites(cipherSuites);
}
@@ -658,6 +666,12 @@ public class XmppConnection implements Runnable {
}
private void sendBindRequest() {
+ while(!mXmppConnectionService.areMessagesInitialized()) {
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException ignored) {
+ }
+ }
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind")
.addChild("resource").setContent(account.getResource());
@@ -673,28 +687,11 @@ public class XmppConnection implements Runnable {
} catch (final InvalidJidException e) {
// TODO: Handle the case where an external JID is technically invalid?
}
- if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) {
- smVersion = 3;
- final EnablePacket enable = new EnablePacket(smVersion);
- tagWriter.writeStanzaAsync(enable);
- stanzasSent = 0;
- messageReceipts.clear();
- } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) {
- smVersion = 2;
- final EnablePacket enable = new EnablePacket(smVersion);
- tagWriter.writeStanzaAsync(enable);
- stanzasSent = 0;
- messageReceipts.clear();
- }
- features.carbonsEnabled = false;
- features.blockListRequested = false;
- disco.clear();
- sendServiceDiscoveryInfo(account.getServer());
- sendServiceDiscoveryItems(account.getServer());
- if (bindListener != null) {
- bindListener.onBind(account);
+ if (streamFeatures.hasChild("session")) {
+ sendStartSession();
+ } else {
+ sendPostBindInitialization();
}
- sendInitialPing();
} else {
disconnect(true);
}
@@ -703,12 +700,45 @@ 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);
- startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session");
- this.sendUnmodifiedIqPacket(startSession, null);
+ }
+
+ private void sendStartSession() {
+ final IqPacket startSession = new IqPacket(IqPacket.TYPE.SET);
+ startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session");
+ this.sendUnmodifiedIqPacket(startSession, new OnIqPacketReceived() {
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ if (packet.getType() == IqPacket.TYPE.RESULT) {
+ sendPostBindInitialization();
+ } else {
+ disconnect(true);
+ }
+ }
+ });
+ }
+
+ private void sendPostBindInitialization() {
+ smVersion = 0;
+ if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) {
+ smVersion = 3;
+ } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) {
+ smVersion = 2;
+ }
+ if (smVersion != 0) {
+ final EnablePacket enable = new EnablePacket(smVersion);
+ tagWriter.writeStanzaAsync(enable);
+ stanzasSent = 0;
+ messageReceipts.clear();
}
+ features.carbonsEnabled = false;
+ features.blockListRequested = false;
+ disco.clear();
+ sendServiceDiscoveryInfo(account.getServer());
+ sendServiceDiscoveryItems(account.getServer());
+ if (bindListener != null) {
+ bindListener.onBind(account);
+ }
+ sendInitialPing();
}
private void sendServiceDiscoveryInfo(final Jid server) {
@@ -1027,6 +1057,11 @@ public class XmppConnection implements Runnable {
this.sendPacket(new InactivePacket());
}
+ public void resetAttemptCount() {
+ this.attempt = 0;
+ this.lastConnect = 0;
+ }
+
public class Features {
XmppConnection connection;
private boolean carbonsEnabled = false;
diff --git a/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java b/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java
new file mode 100644
index 00000000..f85efbdb
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java
@@ -0,0 +1,32 @@
+package eu.siacs.conversations.xmpp.chatstate;
+
+import eu.siacs.conversations.xml.Element;
+
+public enum ChatState {
+
+ ACTIVE, INACTIVE, GONE, COMPOSING, PAUSED, mIncomingChatState;
+
+ public static ChatState parse(Element element) {
+ final String NAMESPACE = "http://jabber.org/protocol/chatstates";
+ if (element.hasChild("active",NAMESPACE)) {
+ return ACTIVE;
+ } else if (element.hasChild("inactive",NAMESPACE)) {
+ return INACTIVE;
+ } else if (element.hasChild("composing",NAMESPACE)) {
+ return COMPOSING;
+ } else if (element.hasChild("gone",NAMESPACE)) {
+ return GONE;
+ } else if (element.hasChild("paused",NAMESPACE)) {
+ return PAUSED;
+ } else {
+ return null;
+ }
+ }
+
+ public static Element toElement(ChatState state) {
+ final String NAMESPACE = "http://jabber.org/protocol/chatstates";
+ final Element element = new Element(state.toString().toLowerCase());
+ element.setAttribute("xmlns",NAMESPACE);
+ return element;
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java
index f1855263..164e8849 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java
@@ -8,6 +8,7 @@ public class InvalidJidException extends Exception {
public final static String INVALID_PART_LENGTH = "JID part must be between 0 and 1023 characters";
public final static String INVALID_CHARACTER = "JID contains an invalid character";
public final static String STRINGPREP_FAIL = "The STRINGPREP operation has failed for the given JID";
+ public final static String IS_NULL = "JID can not be NULL";
/**
* Constructs a new {@code Exception} that includes the current stack trace.
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
index a35ea37c..295e067a 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
@@ -1,9 +1,12 @@
package eu.siacs.conversations.xmpp.jid;
+import android.util.LruCache;
+
import net.java.otr4j.session.SessionID;
import java.net.IDN;
+import eu.siacs.conversations.Config;
import gnu.inet.encoding.Stringprep;
import gnu.inet.encoding.StringprepException;
@@ -12,6 +15,8 @@ import gnu.inet.encoding.StringprepException;
*/
public final class Jid {
+ private static LruCache<String,Jid> cache = new LruCache<>(1024);
+
private final String localpart;
private final String domainpart;
private final String resourcepart;
@@ -41,7 +46,11 @@ public final class Jid {
}
public static Jid fromString(final String jid) throws InvalidJidException {
- return new Jid(jid);
+ return Jid.fromString(jid, false);
+ }
+
+ public static Jid fromString(final String jid, final boolean safe) throws InvalidJidException {
+ return new Jid(jid, safe);
}
public static Jid fromParts(final String localpart,
@@ -56,10 +65,21 @@ public final class Jid {
if (resourcepart != null && !resourcepart.isEmpty()) {
out = out + "/" + resourcepart;
}
- return new Jid(out);
+ return new Jid(out, false);
}
- private Jid(final String jid) throws InvalidJidException {
+ private Jid(final String jid, final boolean safe) throws InvalidJidException {
+ if (jid == null) throw new InvalidJidException(InvalidJidException.IS_NULL);
+
+ Jid fromCache = Jid.cache.get(jid);
+ if (fromCache != null) {
+ displayjid = fromCache.displayjid;
+ localpart = fromCache.localpart;
+ domainpart = fromCache.domainpart;
+ resourcepart = fromCache.resourcepart;
+ return;
+ }
+
// Hackish Android way to count the number of chars in a string... should work everywhere.
final int atCount = jid.length() - jid.replace("@", "").length();
final int slashCount = jid.length() - jid.replace("/", "").length();
@@ -88,7 +108,7 @@ public final class Jid {
} else {
final String lp = jid.substring(0, atLoc);
try {
- localpart = Stringprep.nodeprep(lp);
+ localpart = Config.DISABLE_STRING_PREP || safe ? lp : Stringprep.nodeprep(lp);
} catch (final StringprepException e) {
throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
}
@@ -103,7 +123,7 @@ public final class Jid {
if (slashCount > 0) {
final String rp = jid.substring(slashLoc + 1, jid.length());
try {
- resourcepart = Stringprep.resourceprep(rp);
+ resourcepart = Config.DISABLE_STRING_PREP || safe ? rp : Stringprep.resourceprep(rp);
} catch (final StringprepException e) {
throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
}
@@ -139,6 +159,8 @@ public final class Jid {
throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
}
+ Jid.cache.put(jid, this);
+
this.displayjid = finaljid;
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
index 4e7b532b..93aaa68c 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
@@ -26,7 +26,7 @@ public class MessagePacket extends AbstractStanza {
this.children.remove(findChild("body"));
Element body = new Element("body");
body.setContent(text);
- this.children.add(body);
+ this.children.add(0, body);
}
public void setType(int type) {
@@ -39,6 +39,9 @@ public class MessagePacket extends AbstractStanza {
break;
case TYPE_NORMAL:
break;
+ case TYPE_ERROR:
+ this.setAttribute("type","error");
+ break;
default:
this.setAttribute("type", "chat");
break;