aboutsummaryrefslogtreecommitdiff
path: root/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2016-11-08 15:54:33 +0300
committerGravatar Vitaly Takmazov2016-11-08 15:54:33 +0300
commit4314d834724bbb5c671e7300b7de865fe53c51fb (patch)
treeadf95198a7db90a8cb6d2cdab90935af1e612ddc /juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java
parent397179619fdfa0b4b15f62437a91bd17924e7678 (diff)
reorganize structure again
Diffstat (limited to 'juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java')
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java168
1 files changed, 168 insertions, 0 deletions
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java
new file mode 100644
index 00000000..cedb3745
--- /dev/null
+++ b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java
@@ -0,0 +1,168 @@
+package com.juick.components.s2s;
+
+import com.juick.components.XMPPServer;
+import com.juick.xmpp.extensions.StreamFeatures;
+import com.juick.xmpp.utils.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.UUID;
+import java.util.logging.Level;
+
+/**
+ * @author ugnich
+ */
+public class ConnectionOut extends Connection implements Runnable {
+
+ public boolean streamReady = false;
+ public String to;
+ String checkSID = null;
+ String dbKey = null;
+
+ public ConnectionOut(XMPPServer xmpp, String hostname) throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, XmlPullParserException, KeyManagementException, KeyStoreException, IOException {
+ super(xmpp);
+ to = hostname;
+ }
+
+ public ConnectionOut(XMPPServer xmpp, String hostname, String checkSID, String dbKey) throws Exception {
+ super(xmpp);
+ to = hostname;
+ this.checkSID = checkSID;
+ this.dbKey = dbKey;
+ streamID = UUID.randomUUID().toString();
+ }
+
+ void sendOpenStream() throws IOException {
+ sendStanza("<?xml version='1.0'?><stream:stream xmlns='jabber:server' id='" + streamID +
+ "' xmlns:stream='http://etherx.jabber.org/streams' xmlns:db='jabber:server:dialback' from='" +
+ xmpp.HOSTNAME + "' to='" + to + "' version='1.0'>");
+ }
+
+ void processDialback() throws Exception {
+ if (checkSID != null) {
+ sendDialbackVerify(checkSID, dbKey);
+ }
+ sendStanza("<db:result from='" + xmpp.HOSTNAME + "' to='" + to + "'>" +
+ generateDialbackKey(to, xmpp.HOSTNAME, streamID) + "</db:result>");
+ }
+
+ @Override
+ public void run() {
+ logger.info("STREAM TO " + to + " START");
+ try {
+ socket = new Socket();
+ socket.connect(DNSQueries.getServerAddress(to));
+ restartParser();
+
+ sendOpenStream();
+
+ 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");
+ xmpp.addConnectionOut(ConnectionOut.this);
+ boolean xmppversionnew = parser.getAttributeValue(null, "version") != null;
+ if (!xmppversionnew) {
+ processDialback();
+ }
+
+ 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 = xmpp.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("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 = xmpp.getConnectionIn(sid);
+ if (c != null) {
+ c.sendDialbackResult(from, type);
+ }
+ }
+ XmlUtils.skip(parser);
+ } else if (tag.equals("features") && parser.getNamespace().equals(NS_STREAM)) {
+ StreamFeatures features = StreamFeatures.parse(parser);
+ if (sc != null && !isSecured() && features.STARTTLS >= 0 && !xmpp.brokenSSLhosts.contains(to)) {
+ logger.info("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);
+ logger.info("STREAM " + streamID + " SECURED");
+ restartParser();
+ sendOpenStream();
+ } catch (SSLException sex) {
+ logger.log(Level.SEVERE, String.format("s2s ssl error: %s %s", to, streamID), sex);
+ sendStanza("<failed xmlns\"" + NS_TLS + "\" />");
+ xmpp.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));
+ }
+ }
+
+ logger.warning("STREAM TO " + to + " " + streamID + " FINISHED");
+ xmpp.removeConnectionOut(ConnectionOut.this);
+ closeConnection();
+ } catch (EOFException | SocketException eofex) {
+ logger.info(String.format("STREAM %s %s CLOSED (dirty)", to, streamID));
+ xmpp.removeConnectionOut(ConnectionOut.this);
+ closeConnection();
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, String.format("s2s out exception: %s %s", to, streamID), e);
+ xmpp.removeConnectionOut(ConnectionOut.this);
+ closeConnection();
+ }
+ }
+
+ public void sendDialbackVerify(String sid, String key) {
+ try {
+ sendStanza("<db:verify from='" + xmpp.HOSTNAME + "' to='" + to + "' id='" + sid + "'>" + key + "</db:verify>");
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "STREAM TO " + to + " " + streamID + " ERROR", e);
+ }
+ }
+}