summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2012-09-21 18:37:25 (GMT)
committerKevin Smith <git@kismith.co.uk>2012-09-21 18:37:25 (GMT)
commit816655ed98893382b82569ccbbebdb04c4af9127 (patch)
tree10274e693352516e36837b7bdbc88d979ee54f61 /src/com/isode/stroke/client
parent88c4b4ac3e8609049d6ccd6de9f57d5eaef67558 (diff)
downloadstroke-816655ed98893382b82569ccbbebdb04c4af9127.zip
stroke-816655ed98893382b82569ccbbebdb04c4af9127.tar.bz2
Update some interfaces for consistency with Swiften.
Makes ClientOptions do more.
Diffstat (limited to 'src/com/isode/stroke/client')
-rw-r--r--src/com/isode/stroke/client/Client.java4
-rw-r--r--src/com/isode/stroke/client/ClientOptions.java36
-rw-r--r--src/com/isode/stroke/client/ClientSession.java22
-rw-r--r--src/com/isode/stroke/client/CoreClient.java137
4 files changed, 141 insertions, 58 deletions
diff --git a/src/com/isode/stroke/client/Client.java b/src/com/isode/stroke/client/Client.java
index 69c893f..741597c 100644
--- a/src/com/isode/stroke/client/Client.java
+++ b/src/com/isode/stroke/client/Client.java
@@ -46,8 +46,8 @@ public class Client extends CoreClient {
* @param networkFactories An implementation of network interaction, must
* not be null.
*/
- public Client(EventLoop eventLoop, JID jid, String password, NetworkFactories networkFactories) {
- super(eventLoop,jid, password, networkFactories);
+ public Client(JID jid, String password, NetworkFactories networkFactories) {
+ super(jid, password, networkFactories);
stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel());
directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender);
diff --git a/src/com/isode/stroke/client/ClientOptions.java b/src/com/isode/stroke/client/ClientOptions.java
index 7a7e47e..4090d1f 100644
--- a/src/com/isode/stroke/client/ClientOptions.java
+++ b/src/com/isode/stroke/client/ClientOptions.java
@@ -16,13 +16,18 @@ public class ClientOptions {
public enum UseTLS {
NeverUseTLS,
- UseTLSWhenAvailable
+ UseTLSWhenAvailable,
+ RequireTLS
}
public ClientOptions() {
useStreamCompression = true;
useTLS = UseTLS.UseTLSWhenAvailable;
useStreamResumption = false;
+ allowPLAINWithoutTLS = false;
+ useAcks = true;
+ manualHostname = "";
+ manualPort = -1;
}
@Override
@@ -46,10 +51,37 @@ public class ClientOptions {
*/
public UseTLS useTLS;
/**
- * Use XEP-196 stream resumption when available.
+ * Sets whether plaintext authentication is
+ * allowed over non-TLS-encrypted connections.
+ *
+ * Default: false
+ */
+ public boolean allowPLAINWithoutTLS;
+ /**
+ * Use XEP-198 stream resumption when available.
*
* Default: false
*/
public boolean useStreamResumption;
+ /**
+ * Use XEP-0198 acks in the stream when available.
+ * Default: true
+ */
+ public boolean useAcks;
+
+ /**
+ * The hostname to connect to.
+ * Leave this empty for standard XMPP connection, based on the JID domain.
+ */
+ public String manualHostname;
+
+ /**
+ * The port to connect to.
+ * Leave this to -1 to use the port discovered by SRV lookups, and 5222 as a
+ * fallback.
+ */
+ public int manualPort;
+
+
}
diff --git a/src/com/isode/stroke/client/ClientSession.java b/src/com/isode/stroke/client/ClientSession.java
index 78594b0..b0afb7b 100644
--- a/src/com/isode/stroke/client/ClientSession.java
+++ b/src/com/isode/stroke/client/ClientSession.java
@@ -104,14 +104,18 @@ public class ClientSession {
public enum UseTLS {
NeverUseTLS,
- UseTLSWhenAvailable
+ UseTLSWhenAvailable,
+ RequireTLS
}
private ClientSession(JID jid, SessionStream stream) {
localJID = jid;
state = State.Initial;
this.stream = stream;
- allowPLAINOverNonTLS = true; /* FIXME: false */
+ allowPLAINOverNonTLS = false;
+ useStreamCompression = true;
+ useTLS = UseTLS.UseTLSWhenAvailable;
+ useAcks = true;
needSessionStart = false;
needResourceBind = false;
needAcking = false;
@@ -138,6 +142,10 @@ public class ClientSession {
useTLS = use;
}
+ public void setUseAcks(boolean use) {
+ useAcks = use;
+ }
+
public boolean getStreamManagementEnabled() {
return stanzaAckRequester_ != null;
}
@@ -291,11 +299,14 @@ public class ClientSession {
return;
}
- if (streamFeatures.hasStartTLS() && stream.supportsTLSEncryption()) {
+ if (streamFeatures.hasStartTLS() && stream.supportsTLSEncryption() && !UseTLS.NeverUseTLS.equals(useTLS)) {
state = State.WaitingForEncrypt;
stream.writeElement(new StartTLSRequest());
}
- else if (false && streamFeatures.hasCompressionMethod("zlib")) { /*FIXME: test and enable!*/
+ else if (UseTLS.RequireTLS.equals(useTLS) && !stream.isTLSEncrypted()) {
+ finishSession(Error.Type.NoSupportedAuthMechanismsError);
+ }
+ else if (false && useStreamCompression && streamFeatures.hasCompressionMethod("zlib")) { /*FIXME: test and enable!*/
state = State.Compressing;
stream.writeElement(new CompressRequest("zlib"));
}
@@ -344,7 +355,7 @@ public class ClientSession {
stream.setWhitespacePingEnabled(true);
needSessionStart = streamFeatures.hasSession();
needResourceBind = streamFeatures.hasResourceBind();
- needAcking = streamFeatures.hasStreamManagement();
+ needAcking = streamFeatures.hasStreamManagement() && useAcks;
if (!needResourceBind) {
// Resource binding is a MUST
finishSession(Error.Type.ResourceBindError);
@@ -605,6 +616,7 @@ public class ClientSession {
private boolean allowPLAINOverNonTLS;
private boolean useStreamCompression;
private UseTLS useTLS;
+ private boolean useAcks;
private boolean needSessionStart;
private boolean needResourceBind;
private boolean needAcking;
diff --git a/src/com/isode/stroke/client/CoreClient.java b/src/com/isode/stroke/client/CoreClient.java
index 4326d44..55284d6 100644
--- a/src/com/isode/stroke/client/CoreClient.java
+++ b/src/com/isode/stroke/client/CoreClient.java
@@ -9,6 +9,7 @@
package com.isode.stroke.client;
import com.isode.stroke.base.NotNull;
+import com.isode.stroke.client.ClientSession.UseTLS;
import com.isode.stroke.elements.Message;
import com.isode.stroke.elements.Presence;
import com.isode.stroke.elements.Stanza;
@@ -18,6 +19,7 @@ import com.isode.stroke.jid.JID;
import com.isode.stroke.network.Connection;
import com.isode.stroke.network.ConnectionFactory;
import com.isode.stroke.network.Connector;
+import com.isode.stroke.network.DomainNameResolveError;
import com.isode.stroke.network.NetworkFactories;
import com.isode.stroke.parser.payloadparsers.FullPayloadParserFactoryCollection;
import com.isode.stroke.queries.IQRouter;
@@ -29,6 +31,7 @@ import com.isode.stroke.signals.Signal1;
import com.isode.stroke.signals.SignalConnection;
import com.isode.stroke.signals.Slot;
import com.isode.stroke.signals.Slot1;
+import com.isode.stroke.signals.Slot2;
import com.isode.stroke.tls.Certificate;
import com.isode.stroke.tls.CertificateTrustChecker;
import com.isode.stroke.tls.CertificateVerificationError;
@@ -119,47 +122,76 @@ public class CoreClient {
delete stanzaChannel_;
}*/
+
/**
* Connect using the standard XMPP connection rules (i.e. SRV then A/AAAA).
*
* @param o Client options to use in the connection, must not be null
*/
public void connect(ClientOptions o) {
- options = o;
- connect(jid_.getDomain(), 5222);
- }
-
- /**
- * Connect to the specified host, overriding the standard lookup rules for the JID.
- *
- * Internal method, do not use.
- *
- * @param host Host to connect to, non-null.
- * @param port Default port to use if SRV fails.
- */
- public void connect(String host, int port) {
- options = new ClientOptions();
+ forceReset();
disconnectRequested_ = false;
assert (connector_ == null);
/* FIXME: Port Proxies */
- connector_ = Connector.create(host, networkFactories.getDomainNameResolver(), networkFactories.getConnectionFactory(), networkFactories.getTimerFactory(), port);
- connectorConnectFinishedConnection_ = connector_.onConnectFinished.connect(new Slot1<Connection>() {
- public void call(Connection p1) {
- handleConnectorFinished(p1);
+ String host = o.manualHostname.isEmpty() ? jid_.getDomain() : o.manualHostname;
+ int port = o.manualPort;
+ connector_ = Connector.create(host, port, o.manualHostname.isEmpty(), networkFactories.getDomainNameResolver(), networkFactories.getConnectionFactory(), networkFactories.getTimerFactory());
+ connectorConnectFinishedConnection_ = connector_.onConnectFinished.connect(new Slot2<Connection, com.isode.stroke.base.Error>() {
+ public void call(Connection p1, com.isode.stroke.base.Error p2) {
+ handleConnectorFinished(p1, p2);
}
});
connector_.setTimeoutMilliseconds(60 * 1000);
connector_.start();
}
- void handleConnectorFinished(Connection connection) {
- if (connectorConnectFinishedConnection_ != null) {
- connectorConnectFinishedConnection_.disconnect();
+ private void bindSessionToStream() {
+ session_ = ClientSession.create(jid_, sessionStream_);
+ session_.setCertificateTrustChecker(certificateTrustChecker);
+ session_.setUseStreamCompression(options.useStreamCompression);
+ session_.setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS);
+ switch (options.useTLS) {
+ case UseTLSWhenAvailable:
+ session_.setUseTLS(ClientSession.UseTLS.UseTLSWhenAvailable);
+ session_.setCertificateTrustChecker(certificateTrustChecker);
+ break;
+ case NeverUseTLS:
+ session_.setUseTLS(ClientSession.UseTLS.NeverUseTLS);
+ break;
+ case RequireTLS:
+ session_.setUseTLS(ClientSession.UseTLS.RequireTLS);
+ break;
}
+ session_.setUseAcks(options.useAcks);
+ stanzaChannel_.setSession(session_);
+ sessionFinishedConnection_ = session_.onFinished.connect(new Slot1<com.isode.stroke.base.Error>() {
- connector_ = null;
+ public void call(com.isode.stroke.base.Error p1) {
+ handleSessionFinished(p1);
+ }
+ });
+ sessionNeedCredentialsConnection_ = session_.onNeedCredentials.connect(new Slot() {
+
+ public void call() {
+ handleNeedCredentials();
+ }
+ });
+ session_.start();
+ }
+
+ void handleConnectorFinished(Connection connection, com.isode.stroke.base.Error error) {
+ resetConnector();
+
if (connection == null) {
- onDisconnected.emit(disconnectRequested_ ? null : new ClientError(ClientError.Type.ConnectionError));
+ ClientError clientError = null;
+ if (!disconnectRequested_) {
+ if (error instanceof DomainNameResolveError) {
+ clientError = new ClientError(ClientError.Type.DomainNameResolveError);
+ } else {
+ clientError = new ClientError(ClientError.Type.ConnectionError);
+ }
+ }
+ onDisconnected.emit(clientError);
} else {
assert (connection_ == null);
connection_ = connection;
@@ -183,35 +215,12 @@ public class CoreClient {
}
});
- session_ = ClientSession.create(jid_, sessionStream_);
- session_.setCertificateTrustChecker(certificateTrustChecker);
- session_.setUseStreamCompression(options.useStreamCompression);
- switch (options.useTLS) {
- case UseTLSWhenAvailable:
- session_.setUseTLS(ClientSession.UseTLS.UseTLSWhenAvailable);
- session_.setCertificateTrustChecker(certificateTrustChecker);
- break;
- case NeverUseTLS:
- session_.setUseTLS(ClientSession.UseTLS.NeverUseTLS);
- break;
- }
- stanzaChannel_.setSession(session_);
- sessionFinishedConnection_ = session_.onFinished.connect(new Slot1<com.isode.stroke.base.Error>() {
-
- public void call(com.isode.stroke.base.Error p1) {
- handleSessionFinished(p1);
- }
- });
- sessionNeedCredentialsConnection_ = session_.onNeedCredentials.connect(new Slot() {
-
- public void call() {
- handleNeedCredentials();
- }
- });
- session_.start();
+ bindSessionToStream();
}
}
+
+
/**
* Close the stream and disconnect from the server.
*/
@@ -419,6 +428,26 @@ public class CoreClient {
return (isSessionTLSEncrypted() ? sessionStream_.getPeerCertificate() : null);
}
+ private void resetConnector() {
+ if (connectorConnectFinishedConnection_ != null) {
+ connectorConnectFinishedConnection_.disconnect();
+ }
+ connector_ = null;
+ }
+
+ private void resetSession() {
+ session_.onFinished.disconnectAll();
+ session_.onNeedCredentials.disconnectAll();
+
+ sessionStream_.onDataRead.disconnectAll();
+ sessionStream_.onDataWritten.disconnectAll();
+
+ if (connection_ != null) {
+ connection_.disconnect();
+ }
+ sessionStream_ = null;
+ connection_ = null;
+ }
/**
* @return JID of the client, will never be null. After the session was
@@ -433,6 +462,16 @@ public class CoreClient {
return jid_;
}
}
+
+ private void forceReset() {
+ if (connector_ != null) {
+ resetConnector();
+ }
+ if (sessionStream_ != null || connection_ != null) {
+ resetSession();
+ }
+
+ }
@Override
public String toString()