aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/juick/xmpp/s2s/ConnectionOut.java')
-rw-r--r--src/main/java/com/juick/xmpp/s2s/ConnectionOut.java186
1 files changed, 102 insertions, 84 deletions
diff --git a/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java b/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java
index 59fdfb60..4ebeffb6 100644
--- a/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java
+++ b/src/main/java/com/juick/xmpp/s2s/ConnectionOut.java
@@ -1,140 +1,158 @@
package com.juick.xmpp.s2s;
+import com.juick.xmpp.extensions.StreamFeatures;
import com.juick.xmpp.utils.XmlUtils;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.Channels;
import java.nio.channels.CompletionHandler;
+import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+
/**
- *
* @author ugnich
*/
-public class ConnectionOut extends Connection {
+public class ConnectionOut extends Connection implements Runnable {
public boolean streamReady = false;
public String to;
String checkSID = null;
String dbKey = null;
- public ConnectionOut(String hostname) {
+ public ConnectionOut(String hostname) throws Exception {
super();
to = hostname;
}
- public ConnectionOut(String hostname, String checkSID, String dbKey) {
+ public ConnectionOut(String hostname, String checkSID, String dbKey) throws Exception {
super();
to = hostname;
this.checkSID = checkSID;
this.dbKey = dbKey;
}
- public void parseStream() {
- LOGGER.info("STREAM TO " + to + " START");
+ void sendOpenStream() throws IOException {
+ sendStanza("<?xml version='1.0'?><stream:stream xmlns='jabber:server' " +
+ "xmlns:stream='http://etherx.jabber.org/streams' xmlns:db='jabber:server:dialback' from='" +
+ XMPPComponent.HOSTNAME + "' to='" + to + "' version='1.0'>");
+ }
+
+ void processDialback() throws Exception {
+ if (checkSID != null) {
+ sendDialbackVerify(checkSID, dbKey);
+ }
+ sendStanza("<db:result from='" + XMPPComponent.HOSTNAME + "' to='" + to + "'>" +
+ generateDialbackKey(to, XMPPComponent.HOSTNAME, streamID) + "</db:result>");
+ }
+ @Override
+ public void run() {
+ LOGGER.info("STREAM TO " + to + " START");
try {
HostnamePort addr = DNSQueries.getServerAddress(to);
- socket = AsynchronousSocketChannel.open();
- socket.connect(new InetSocketAddress(addr.hostname, addr.port), socket, new CompletionHandler<Void, AsynchronousSocketChannel>() {
- @Override
- public void completed(Void result, AsynchronousSocketChannel attachment) {
- try {
- parser.setInput(new InputStreamReader(Channels.newInputStream(socket)));
+ socket = new Socket(InetAddress.getByName(addr.hostname), addr.port);
+ parser.setInput(new InputStreamReader(socket.getInputStream()));
- writer = new OutputStreamWriter(Channels.newOutputStream(socket));
+ writer = new OutputStreamWriter(socket.getOutputStream());
- sendStanza("<?xml version='1.0'?><stream:stream xmlns='jabber:server' " +
- "xmlns:stream='http://etherx.jabber.org/streams' xmlns:db='jabber:server:dialback' from='" +
- XMPPComponent.HOSTNAME + "' to='" + to + "' version='1.0'>");
+ sendOpenStream();
- parser.next(); // stream:stream
- streamID = parser.getAttributeValue(null, "id");
- if (streamID == null || streamID.isEmpty()) {
- throw new Exception("STREAM TO " + to + " INVALID FIRST PACKET");
- }
+ parser.next(); // stream:stream
+ streamID = parser.getAttributeValue(null, "id");
+ if (streamID == null || streamID.isEmpty()) {
+ throw new Exception("STREAM TO " + to + " INVALID FIRST PACKET");
+ }
- LOGGER.info("STREAM TO " + to + " " + streamID + " OPEN");
- XMPPComponent.addConnectionOut(ConnectionOut.this);
+ LOGGER.info("STREAM TO " + to + " " + streamID + " OPEN");
+ XMPPComponent.addConnectionOut(ConnectionOut.this);
- if (checkSID != null) {
- sendDialbackVerify(checkSID, dbKey);
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
+ }
+ logParser();
+
+ String tag = parser.getName();
+ if (tag.equals("result") && parser.getNamespace().equals(NS_DB)) {
+ String type = parser.getAttributeValue(null, "type");
+ if (type != null && type.equals("valid")) {
+ streamReady = true;
+ LOGGER.info("STREAM TO " + to + " " + streamID + " READY");
+
+ String cache = XMPPComponent.getFromCache(to);
+ if (cache != null) {
+ LOGGER.info("STREAM TO " + to + " " + streamID + " SENDING CACHE");
+ sendStanza(cache);
}
- sendStanza("<db:result from='" + XMPPComponent.HOSTNAME + "' to='" + to + "'>" + generateDialbackKey(to, XMPPComponent.HOSTNAME, streamID) + "</db:result>");
-
- while (parser.next() != XmlPullParser.END_DOCUMENT) {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
- logParser();
-
- String tag = parser.getName();
- if (tag.equals("db:result")) {
- String type = parser.getAttributeValue(null, "type");
- if (type != null && type.equals("valid")) {
- streamReady = true;
- LOGGER.info("STREAM TO " + to + " " + streamID + " READY");
-
- String cache = XMPPComponent.getFromCache(to);
- if (cache != null) {
- LOGGER.info("STREAM TO " + to + " " + streamID + " SENDING CACHE");
- sendStanza(cache);
- }
-
- } else {
- LOGGER.info("STREAM TO " + to + " " + streamID + " DIALBACK FAIL");
- }
- XmlUtils.skip(parser);
- } else if (tag.equals("db:verify")) {
- String from = parser.getAttributeValue(null, "from");
- String type = parser.getAttributeValue(null, "type");
- String sid = parser.getAttributeValue(null, "id");
- if (from != null && from.equals(to) && sid != null && !sid.isEmpty() && type != null) {
- ConnectionIn c = XMPPComponent.getConnectionIn(sid);
- if (c != null) {
- c.sendDialbackResult(from, type);
- }
- }
- XmlUtils.skip(parser);
- } else {
- LOGGER.info("STREAM TO " + to + " " + streamID + ": " + XmlUtils.parseToString(parser, true));
- }
+ } else {
+ LOGGER.info("STREAM TO " + to + " " + streamID + " DIALBACK FAIL");
+ }
+ XmlUtils.skip(parser);
+ } else if (tag.equals("verify") && parser.getNamespace().equals(NS_DB)) {
+ String from = parser.getAttributeValue(null, "from");
+ String type = parser.getAttributeValue(null, "type");
+ String sid = parser.getAttributeValue(null, "id");
+ if (from != null && from.equals(to) && sid != null && !sid.isEmpty() && type != null) {
+ ConnectionIn c = XMPPComponent.getConnectionIn(sid);
+ if (c != null) {
+ c.sendDialbackResult(from, type);
}
-
- LOGGER.warning("STREAM TO " + to + " " + streamID + " FINISHED");
- XMPPComponent.removeConnectionOut(ConnectionOut.this);
- closeConnection();
- } catch (EOFException eofex) {
- LOGGER.info(String.format("STREAM %s %s CLOSED (dirty)", to, streamID));
- XMPPComponent.removeConnectionOut(ConnectionOut.this);
- closeConnection();
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "s2s out exception", e);
- XMPPComponent.removeConnectionOut(ConnectionOut.this);
+ }
+ XmlUtils.skip(parser);
+ } else if (tag.equals("features") && parser.getNamespace().equals(NS_STREAM)) {
+ StreamFeatures features = StreamFeatures.parse(parser);
+ if (!isSecured() && features.STARTTLS >= 0) {
+ System.out.println("STREAM TO " + to + " " + streamID + " SECURING");
+ sendStanza("<starttls xmlns=\"" + NS_TLS + "\" />");
+ } else {
+ processDialback();
+ }
+ } else if (tag.equals("proceed") && parser.getNamespace().equals(NS_TLS)) {
+ try {
+ socket = sc.getSocketFactory().createSocket(socket, socket.getInetAddress().getHostAddress(),
+ socket.getPort(), true);
+ ((SSLSocket) socket).startHandshake();
+ setSecured(true);
+ System.out.println("STREAM " + streamID + " SECURED");
+ restartParser();
+ sendOpenStream();
+ } catch (SSLException sex) {
+ System.err.println("STREAM " + streamID + " SSL ERROR");
+ sendStanza("<failed xmlns\"" + NS_TLS + "\" />");
+ XMPPComponent.removeConnectionOut(this);
closeConnection();
}
+ } else if (isSecured() && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) {
+ streamID = parser.getAttributeValue(null, "id");
+ } else {
+ LOGGER.info("STREAM TO " + to + " " + streamID + ": " + XmlUtils.parseToString(parser, true));
}
+ }
- @Override
- public void failed(Throwable exc, AsynchronousSocketChannel attachment) {
- LOGGER.log(Level.WARNING, "s2s out failed", exc);
- XMPPComponent.removeConnectionOut(ConnectionOut.this);
- closeConnection();
- }
- });
+ LOGGER.warning("STREAM TO " + to + " " + streamID + " FINISHED");
+ XMPPComponent.removeConnectionOut(ConnectionOut.this);
+ closeConnection();
+ } catch (EOFException eofex) {
+ LOGGER.info(String.format("STREAM %s %s CLOSED (dirty)", to, streamID));
+ XMPPComponent.removeConnectionOut(ConnectionOut.this);
+ closeConnection();
} catch (Exception e) {
- LOGGER.warning(e.toString());
- XMPPComponent.removeConnectionOut(this);
+ LOGGER.log(Level.SEVERE, "s2s out exception", e);
+ XMPPComponent.removeConnectionOut(ConnectionOut.this);
closeConnection();
}
}