From d06d53708a1f87d41b14fc87d40a7b9233b36fcb Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sun, 31 Jul 2016 02:34:12 +0300 Subject: move components to ws module --- .../main/java/com/juick/ws/s2s/ConnectionIn.java | 227 +++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 juick-ws/src/main/java/com/juick/ws/s2s/ConnectionIn.java (limited to 'juick-ws/src/main/java/com/juick/ws/s2s/ConnectionIn.java') diff --git a/juick-ws/src/main/java/com/juick/ws/s2s/ConnectionIn.java b/juick-ws/src/main/java/com/juick/ws/s2s/ConnectionIn.java new file mode 100644 index 00000000..a57623c4 --- /dev/null +++ b/juick-ws/src/main/java/com/juick/ws/s2s/ConnectionIn.java @@ -0,0 +1,227 @@ +package com.juick.ws.s2s; + +import com.juick.ws.components.XMPPComponent; +import com.juick.xmpp.Iq; +import com.juick.xmpp.JID; +import com.juick.xmpp.Message; +import com.juick.xmpp.Presence; +import com.juick.xmpp.utils.XmlUtils; +import org.xmlpull.v1.XmlPullParser; + +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.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author ugnich + */ +public class ConnectionIn extends Connection implements Runnable { + + private static final Logger LOGGER = Logger.getLogger(ConnectionIn.class.getName()); + + final public List from = new ArrayList<>(); + public long tsRemoteData = 0; + public long packetsRemote = 0; + JuickBot bot; + + public ConnectionIn(XMPPComponent xmpp, JuickBot bot, Socket socket) throws Exception { + super(xmpp); + this.bot = bot; + this.socket = socket; + streamID = UUID.randomUUID().toString(); + restartParser(); + } + + @Override + public void run() { + LOGGER.info("STREAM FROM ? " + streamID + " START"); + try { + parser.next(); // stream:stream + updateTsRemoteData(); + if (!parser.getName().equals("stream") + || !parser.getNamespace("stream").equals(NS_STREAM)) { +// || !parser.getAttributeValue(null, "version").equals("1.0") +// || !parser.getAttributeValue(null, "to").equals(Main.HOSTNAME)) { + throw new Exception("STREAM FROM ? " + streamID + " INVALID FIRST PACKET"); + } + boolean xmppversionnew = parser.getAttributeValue(null, "version") != null; + String from = parser.getAttributeValue(null, "from"); + + if (xmpp.bannedHosts.contains(from)) { + closeConnection(); + return; + } + sendOpenStream(from, xmppversionnew); + + while (parser.next() != XmlPullParser.END_DOCUMENT) { + updateTsRemoteData(); + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + logParser(); + + packetsRemote++; + + String tag = parser.getName(); + if (tag.equals("result") && parser.getNamespace().equals(NS_DB)) { + String dfrom = parser.getAttributeValue(null, "from"); + String to = parser.getAttributeValue(null, "to"); + LOGGER.info("STREAM FROM " + dfrom + " TO " + to + " " + streamID + " ASKING FOR DIALBACK"); + if (dfrom.endsWith(xmpp.HOSTNAME) && (dfrom.equals(xmpp.HOSTNAME) || dfrom.endsWith("." + xmpp.HOSTNAME))) { + break; + } + if (to != null && to.equals(xmpp.HOSTNAME)) { + String dbKey = XmlUtils.getTagText(parser); + updateTsRemoteData(); + + ConnectionOut c = xmpp.getConnectionOut(dfrom, false); + if (c != null) { + c.sendDialbackVerify(streamID, dbKey); + } else { + c = new ConnectionOut(xmpp, dfrom, streamID, dbKey); + xmpp.executorService.submit(c); + } + } else { + throw new HostUnknownException("STREAM FROM " + dfrom + " " + streamID + " INVALID TO " + to); + } + } else if (tag.equals("verify") && parser.getNamespace().equals(NS_DB)) { + String vfrom = parser.getAttributeValue(null, "from"); + String vto = parser.getAttributeValue(null, "to"); + String vid = parser.getAttributeValue(null, "id"); + String vkey = XmlUtils.getTagText(parser); + updateTsRemoteData(); + boolean valid = false; + if (vfrom != null && vto != null && vid != null && vkey != null) { + String vkey2 = generateDialbackKey(vfrom, vto, vid); + valid = vkey.equals(vkey2); + } + if (valid) { + sendStanza(""); + LOGGER.info("STREAM FROM " + vfrom + " " + streamID + " DIALBACK VERIFY VALID"); + } else { + sendStanza(""); + LOGGER.warning("STREAM FROM " + vfrom + " " + streamID + " DIALBACK VERIFY INVALID"); + } + } else if (tag.equals("presence") && checkFromTo(parser)) { + Presence p = Presence.parse(parser, null); + if (p != null && (p.type == null || !p.type.equals(Presence.Type.error))) { + bot.incomingPresence(p); + } + } else if (tag.equals("message") && checkFromTo(parser)) { + updateTsRemoteData(); + Message msg = Message.parse(parser, xmpp.childParsers); + if (msg != null && (msg.type == null || !msg.type.equals(Message.Type.error))) { + LOGGER.info("STREAM " + streamID + ": " + msg.toString()); + if (!bot.incomingMessage(msg)) { + xmpp.getRouter().send(msg.toString()); + } + } + } else if (tag.equals("iq") && checkFromTo(parser)) { + updateTsRemoteData(); + String type = parser.getAttributeValue(null, "type"); + String xml = XmlUtils.parseToString(parser, true); + if (type == null || !type.equals(Iq.Type.error)) { + LOGGER.info("STREAM " + streamID + ": " + xml); + xmpp.getRouter().send(xml); + } + } else if (!isSecured() && tag.equals("starttls")) { + LOGGER.info("STREAM " + streamID + " SECURING"); + sendStanza(""); + try { + socket = sc.getSocketFactory().createSocket(socket, socket.getInetAddress().getHostAddress(), + socket.getPort(), true); + ((SSLSocket) socket).setUseClientMode(false); + ((SSLSocket) socket).startHandshake(); + setSecured(true); + LOGGER.info("STREAM " + streamID + " SECURED"); + restartParser(); + } catch (SSLException sex) { + LOGGER.warning("STREAM " + streamID + " SSL ERROR"); + sendStanza(""); + xmpp.removeConnectionIn(this); + closeConnection(); + } + } else if (isSecured() && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) { + sendOpenStream(null, true); + } else { + LOGGER.info("STREAM " + streamID + ": " + XmlUtils.parseToString(parser, true)); + } + } + LOGGER.warning("STREAM " + streamID + " FINISHED"); + xmpp.removeConnectionIn(this); + closeConnection(); + } catch (EOFException | SocketException ex) { + LOGGER.info(String.format("STREAM %s CLOSED (dirty)", streamID)); + xmpp.removeConnectionIn(this); + closeConnection(); + } catch (HostUnknownException e) { + LOGGER.warning(e.getMessage()); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "STREAM " + streamID + " ERROR", e); + xmpp.removeConnectionIn(this); + closeConnection(); + } + } + + void updateTsRemoteData() { + tsRemoteData = System.currentTimeMillis(); + } + + void sendOpenStream(String from, boolean xmppversionnew) throws IOException { + String openStream = ""; + if (xmppversionnew) { + openStream += ""; + if (!isSecured() && !xmpp.brokenSSLhosts.contains(from)) { + openStream += ""; + } + openStream += ""; + } + sendStanza(openStream); + } + + public void sendDialbackResult(String sfrom, String type) { + try { + sendStanza(""); + if (type.equals("valid")) { + from.add(sfrom); + LOGGER.info("STREAM FROM " + sfrom + " " + streamID + " READY"); + } + } catch (IOException e) { + LOGGER.warning("STREAM FROM " + sfrom + " " + streamID + " ERROR: " + e.toString()); + } + } + + boolean checkFromTo(XmlPullParser parser) throws Exception { + String cfrom = parser.getAttributeValue(null, "from"); + String cto = parser.getAttributeValue(null, "to"); + if (cfrom != null && cto != null && !cfrom.isEmpty() && !cto.isEmpty()) { + JID jidto = new JID(cto); + if (jidto.Host != null && jidto.Username != null && jidto.Host.equals(xmpp.HOSTNAME) && jidto.Username.matches("^[a-zA-Z0-9\\-]{2,16}$")) { + JID jidfrom = new JID(cfrom); + int size = from.size(); + for (int i = 0; i < size; i++) { + if (from.get(i).equals(jidfrom.Host)) { + return true; + } + } + } + } + return false; + } + class HostUnknownException extends Exception { + public HostUnknownException(String message) { + super(message); + } + } +} -- cgit v1.2.3