From 3d977963dfe55c0f14720da8c671f77bf210229d Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Fri, 11 Nov 2016 11:39:56 +0300 Subject: xmpp: revert to Connection-based router because Stream-based router can not route full stanzas --- .../com/juick/components/s2s/ConnectionRouter.java | 250 +++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionRouter.java (limited to 'juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionRouter.java') diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionRouter.java b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionRouter.java new file mode 100644 index 00000000..86f12b82 --- /dev/null +++ b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionRouter.java @@ -0,0 +1,250 @@ +package com.juick.components.s2s; + +import com.juick.User; +import com.juick.components.XMPPServer; +import com.juick.server.MessagesQueries; +import com.juick.server.SubscriptionsQueries; +import com.juick.server.UserQueries; +import com.juick.xmpp.JID; +import com.juick.xmpp.Message; +import com.juick.xmpp.extensions.JuickMessage; +import com.juick.xmpp.extensions.Nickname; +import com.juick.xmpp.extensions.XOOB; +import com.juick.xmpp.utils.XmlUtils; +import org.apache.commons.codec.digest.DigestUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xmlpull.v1.XmlPullParser; + +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.InetSocketAddress; +import java.nio.channels.AsynchronousSocketChannel; +import java.nio.channels.Channels; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author ugnich + */ +public class ConnectionRouter extends Connection implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(ConnectionRouter.class); + + private String componentName; + private int componentPort; + private String password; + + public ConnectionRouter(XMPPServer s2s, String componentName, int componentPort, String password) throws Exception { + super(s2s); + this.componentName = componentName; + this.componentPort = componentPort; + this.password = password; + } + + @Override + public void run() { + logger.info("STREAM ROUTER START"); + + try { + AsynchronousSocketChannel socket = AsynchronousSocketChannel.open(); + socket.connect(new InetSocketAddress(componentPort)); + parser.setInput(new InputStreamReader(Channels.newInputStream(socket))); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + writer = new OutputStreamWriter(Channels.newOutputStream(socket)); + + String msg = String.format("", componentName); + writer.write(msg); + writer.flush(); + + parser.next(); // stream:stream + streamID = parser.getAttributeValue(null, "id"); + if (streamID == null || streamID.isEmpty()) { + throw new Exception("FAIL ON FIRST PACKET"); + } + + msg = "" + DigestUtils.sha1Hex(streamID + password) + ""; + writer.write(msg); + writer.flush(); + + parser.next(); + if (!parser.getName().equals("handshake")) { + throw new Exception("NO HANDSHAKE"); + } + XmlUtils.skip(parser); + logger.info("STREAM ROUTER OPEN"); + + while (parser.next() != XmlPullParser.END_DOCUMENT) { + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + + String tag = parser.getName(); + String to = parser.getAttributeValue(null, "to"); + if (to != null && (tag.equals("message") || tag.equals("presence") || tag.equals("iq"))) { + JID jid = new JID(to); + if (jid.Host != null) { + if (jid.Host.equals(componentName)) { + if (tag.equals("message")) { + Message xmsg = Message.parse(parser, xmpp.childParsers); + logger.info("STREAM ROUTER (PROCESS): " + xmsg.toString()); + JuickMessage jmsg = (JuickMessage) xmsg.getChild(JuickMessage.XMLNS); + if (jmsg != null) { + if (jid.Username != null && jid.Username.equals("recomm")) { + sendJuickRecommendation(jmsg); + } else { + if (jmsg.getRID() > 0) { + sendJuickComment(jmsg); + } else if (jmsg.getMID() > 0) { + sendJuickMessage(jmsg); + } + } + } + } + } else if (jid.Host.endsWith(xmpp.HOSTNAME) && (jid.Host.equals(xmpp.HOSTNAME) || jid.Host.endsWith("." + xmpp.HOSTNAME))) { + String xml = XmlUtils.parseToString(parser, true); + logger.info("STREAM ROUTER: " + xml); + } else { + String xml = XmlUtils.parseToString(parser, true); + logger.info("STREAM ROUTER (OUT): " + xml); + xmpp.sendOut(jid.Host, xml); + } + } else { + logger.info("STREAM ROUTER (NO TO): " + XmlUtils.parseToString(parser, true)); + } + } else { + logger.info("STREAM ROUTER: " + XmlUtils.parseToString(parser, true)); + } + } + + logger.warn("STREAM ROUTER FINISHED"); + } catch (Exception e) { + logger.warn("STREAM ROUTER PARSE ERROR: " + e.toString()); + } + } + + public void sendJuickMessage(JuickMessage jmsg) { + List jids = new ArrayList<>(); + + if (jmsg.FriendsOnly) { + jids = SubscriptionsQueries.getJIDSubscribedToUser(xmpp.jdbc, jmsg.getUser().getUID(), jmsg.FriendsOnly); + } else { + List users = SubscriptionsQueries.getSubscribedUsers(xmpp.jdbc, jmsg.getUser().getUID(), jmsg.getMID()); + for (User user : users) { + for (String jid : UserQueries.getJIDsbyUID(xmpp.jdbc, user.getUID())) { + jids.add(jid); + } + } + } + + String txt = "@" + jmsg.getUser().getUName() + ":" + jmsg.getTagsString() + "\n"; + String attachment = jmsg.getAttachmentURL(); + if (attachment != null) { + txt += attachment + "\n"; + } + txt += jmsg.getText() + "\n\n"; + txt += "#" + jmsg.getMID() + " http://juick.com/" + jmsg.getMID(); + + Nickname nick = new Nickname(); + nick.Nickname = "@" + jmsg.getUser().getUName(); + + com.juick.xmpp.Message msg = new com.juick.xmpp.Message(); + msg.from = xmpp.bot.getJid(); + msg.body = txt; + msg.type = Message.Type.chat; + msg.thread = "juick-" + jmsg.getMID(); + msg.addChild(jmsg); + msg.addChild(nick); + if (attachment != null) { + XOOB oob = new XOOB(); + oob.URL = attachment; + msg.addChild(oob); + } + + for (String jid : jids) { + msg.to = new JID(jid); + xmpp.sendOut(msg); + } + } + + public void sendJuickComment(JuickMessage jmsg) { + List users; + String replyQuote; + String replyTo; + + users = SubscriptionsQueries.getUsersSubscribedToComments(xmpp.jdbc, jmsg.getMID(), jmsg.getUser().getUID()); + com.juick.Message replyMessage = jmsg.ReplyTo > 0 ? MessagesQueries.getReply(xmpp.jdbc, jmsg.getMID(), jmsg.ReplyTo) + : MessagesQueries.getMessage(xmpp.jdbc, jmsg.getMID()); + replyTo = replyMessage.getUser().getUName(); + replyQuote = replyMessage.getReplyQuote(); + + String txt = "Reply by @" + jmsg.getUser().getUName() + ":\n" + replyQuote + "\n@" + replyTo + " "; + String attachment = jmsg.getAttachmentURL(); + if (attachment != null) { + txt += attachment + "\n"; + } + txt += jmsg.getText() + "\n\n" + "#" + jmsg.getMID() + "/" + jmsg.getRID() + " http://juick.com/" + jmsg.getMID() + "#" + jmsg.getRID(); + + com.juick.xmpp.Message msg = new com.juick.xmpp.Message(); + msg.from = xmpp.bot.getJid(); + msg.body = txt; + msg.type = Message.Type.chat; + msg.addChild(jmsg); + for (User user : users) { + for (String jid : UserQueries.getJIDsbyUID(xmpp.jdbc, user.getUID())) { + msg.to = new JID(jid); + xmpp.sendOut(msg); + } + } + } + + public void sendJuickRecommendation(JuickMessage recomm) { + List users; + JuickMessage jmsg; + jmsg = new JuickMessage(MessagesQueries.getMessage(xmpp.jdbc, recomm.getMID())); + users = SubscriptionsQueries.getUsersSubscribedToUserRecommendations(xmpp.jdbc, + recomm.getUser().getUID(), recomm.getMID(), jmsg.getUser().getUID()); + + String txt = "Recommended by @" + recomm.getUser().getUName() + ":\n"; + txt += "@" + jmsg.getUser().getUName() + ":" + jmsg.getTagsString() + "\n"; + String attachment = jmsg.getAttachmentURL(); + if (attachment != null) { + txt += attachment + "\n"; + } + txt += jmsg.getText() + "\n\n"; + txt += "#" + jmsg.getMID(); + if (jmsg.Replies > 0) { + if (jmsg.Replies % 10 == 1 && jmsg.Replies % 100 != 11) { + txt += " (" + jmsg.Replies + " reply)"; + } else { + txt += " (" + jmsg.Replies + " replies)"; + } + } + txt += " http://juick.com/" + jmsg.getMID(); + + Nickname nick = new Nickname(); + nick.Nickname = "@" + jmsg.getUser().getUName(); + + com.juick.xmpp.Message msg = new com.juick.xmpp.Message(); + msg.from = xmpp.bot.getJid(); + msg.body = txt; + msg.type = Message.Type.chat; + msg.thread = "juick-" + jmsg.getMID(); + msg.addChild(jmsg); + msg.addChild(nick); + if (attachment != null) { + XOOB oob = new XOOB(); + oob.URL = attachment; + msg.addChild(oob); + } + + for (User user : users) { + for (String jid : UserQueries.getJIDsbyUID(xmpp.jdbc, user.getUID())) { + msg.to = new JID(jid); + xmpp.sendOut(msg); + } + } + } +} \ No newline at end of file -- cgit v1.2.3