Commit aecc6930 authored by Axel Brand's avatar Axel Brand Committed by daeva

Gojara

- implemented GojaraAdminManager & GojaraAdminProcessor, send admincommands to admin configured Spectrum & process returning Information
- create adminuser gojaraadmin, remove it when plugin is destroyed
- fixed not showing all open sessions when plugin restarts / loads through querying spectrum2 for online_users
- implemented unregistering registrations on spectrum side with admincommand unregister <barejid>
- check if transport is active before trying to remove the registration, maybe do specific new command for just deleting info on our side

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13695 b35dd754-fafc-0310-a699-88a17e54d16e
parent ea56c746
...@@ -14,6 +14,8 @@ import org.jivesoftware.openfire.container.Plugin; ...@@ -14,6 +14,8 @@ import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.interceptor.InterceptorManager; import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.MainInterceptor; import org.jivesoftware.openfire.plugin.gojara.messagefilter.MainInterceptor;
import org.jivesoftware.openfire.plugin.gojara.sessions.GojaraAdminManager;
import org.jivesoftware.openfire.plugin.gojara.sessions.TransportSessionManager;
import org.jivesoftware.openfire.plugin.gojara.utils.XpathHelper; import org.jivesoftware.openfire.plugin.gojara.utils.XpathHelper;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventDispatcher; import org.jivesoftware.util.PropertyEventDispatcher;
...@@ -48,6 +50,8 @@ public class RemoteRosterPlugin implements Plugin { ...@@ -48,6 +50,8 @@ public class RemoteRosterPlugin implements Plugin {
private MainInterceptor mainInterceptor = new MainInterceptor(); private MainInterceptor mainInterceptor = new MainInterceptor();
private InterceptorManager iManager = InterceptorManager.getInstance(); private InterceptorManager iManager = InterceptorManager.getInstance();
private InternalComponentManager compManager = InternalComponentManager.getInstance(); private InternalComponentManager compManager = InternalComponentManager.getInstance();
private TransportSessionManager transportSessionManager = TransportSessionManager.getInstance();
private GojaraAdminManager gojaraAdminManager = GojaraAdminManager.getInstance();
public void initializePlugin(PluginManager manager, File pluginDirectory) { public void initializePlugin(PluginManager manager, File pluginDirectory) {
Log.info("Starting RemoteRoster Plugin"); Log.info("Starting RemoteRoster Plugin");
...@@ -55,10 +59,11 @@ public class RemoteRosterPlugin implements Plugin { ...@@ -55,10 +59,11 @@ public class RemoteRosterPlugin implements Plugin {
iManager.addInterceptor(mainInterceptor); iManager.addInterceptor(mainInterceptor);
manageExternalComponents(); manageExternalComponents();
listenToSettings(); listenToSettings();
transportSessionManager.initializeSessions();
Log.info("Started Gojara successfully. Currently running interceptors: "+iManager.getInterceptors().size()); Log.info("Started Gojara successfully. Currently running interceptors: "+iManager.getInterceptors().size());
} }
/* /**
* Handles external components that connect to openfire. We check if the * Handles external components that connect to openfire. We check if the
* external component is maybe a gateway and interesting for us * external component is maybe a gateway and interesting for us
*/ */
...@@ -70,12 +75,7 @@ public class RemoteRosterPlugin implements Plugin { ...@@ -70,12 +75,7 @@ public class RemoteRosterPlugin implements Plugin {
*/ */
public void componentUnregistered(JID componentJID) { public void componentUnregistered(JID componentJID) {
// ComponentSession session = _sessionManager.getComponentSession(componentJID.getDomain());
// if (session != null && _interceptors.containsKey(session.getExternalComponent().getInitialSubdomain())) {
// String initialSubdomain = session.getExternalComponent().getInitialSubdomain();
// Remove it from Map & ComponentManager
mainInterceptor.removeTransport(componentJID.toString()); mainInterceptor.removeTransport(componentJID.toString());
// }
} }
/* /*
...@@ -109,7 +109,7 @@ public class RemoteRosterPlugin implements Plugin { ...@@ -109,7 +109,7 @@ public class RemoteRosterPlugin implements Plugin {
compManager.addListener(_componentObserver); compManager.addListener(_componentObserver);
} }
/* /**
* Registers a listener for JiveGlobals. We might restart our service, if * Registers a listener for JiveGlobals. We might restart our service, if
* there were some changes for our gateways * there were some changes for our gateways
*/ */
...@@ -129,6 +129,7 @@ public class RemoteRosterPlugin implements Plugin { ...@@ -129,6 +129,7 @@ public class RemoteRosterPlugin implements Plugin {
iManager.removeInterceptor(mainInterceptor); iManager.removeInterceptor(mainInterceptor);
PropertyEventDispatcher.removeListener(_settingsObserver); PropertyEventDispatcher.removeListener(_settingsObserver);
compManager.removeListener(_componentObserver); compManager.removeListener(_componentObserver);
gojaraAdminManager.removeAdminUser();
pluginManager = null; pluginManager = null;
mainInterceptor = null; mainInterceptor = null;
compManager = null; compManager = null;
......
...@@ -16,9 +16,19 @@ import org.jivesoftware.util.JiveGlobals; ...@@ -16,9 +16,19 @@ import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ; import org.xmpp.packet.IQ;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet; import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence; import org.xmpp.packet.Presence;
/**
* This is the only Interceptor GoJara uses. Each IQ/Message/Presence is checked if it is of interest to us, so we can
* process it accordingly. This is done in the specific Processors. The Interceptor keeps a set of currently connected
* Transports.
*
* @author axel.frederik.brand
* @author Holger Bergunde
*
*/
public class MainInterceptor implements PacketInterceptor { public class MainInterceptor implements PacketInterceptor {
private static final Logger Log = LoggerFactory.getLogger(MainInterceptor.class); private static final Logger Log = LoggerFactory.getLogger(MainInterceptor.class);
...@@ -39,6 +49,7 @@ public class MainInterceptor implements PacketInterceptor { ...@@ -39,6 +49,7 @@ public class MainInterceptor implements PacketInterceptor {
AbstractRemoteRosterProcessor updateToComponentProcessor = new ClientToComponentUpdateProcessor(activeTransports); AbstractRemoteRosterProcessor updateToComponentProcessor = new ClientToComponentUpdateProcessor(activeTransports);
AbstractRemoteRosterProcessor whitelistProcessor = new WhitelistProcessor(activeTransports); AbstractRemoteRosterProcessor whitelistProcessor = new WhitelistProcessor(activeTransports);
AbstractRemoteRosterProcessor mucfilterProcessor = new MucFilterProcessor(); AbstractRemoteRosterProcessor mucfilterProcessor = new MucFilterProcessor();
AbstractRemoteRosterProcessor gojaraAdminProcessor = new GojaraAdminProcessor();
packetProcessors.put("sparkIQRegistered", iqRegisteredProcessor); packetProcessors.put("sparkIQRegistered", iqRegisteredProcessor);
packetProcessors.put("iqRosterPayload", iqRosterPayloadProcessor); packetProcessors.put("iqRosterPayload", iqRosterPayloadProcessor);
packetProcessors.put("handleNonPersistant", nonPersistantProcessor); packetProcessors.put("handleNonPersistant", nonPersistantProcessor);
...@@ -46,8 +57,9 @@ public class MainInterceptor implements PacketInterceptor { ...@@ -46,8 +57,9 @@ public class MainInterceptor implements PacketInterceptor {
packetProcessors.put("clientToComponentUpdate", updateToComponentProcessor); packetProcessors.put("clientToComponentUpdate", updateToComponentProcessor);
packetProcessors.put("whitelistProcessor", whitelistProcessor); packetProcessors.put("whitelistProcessor", whitelistProcessor);
packetProcessors.put("mucfilterProcessor", mucfilterProcessor); packetProcessors.put("mucfilterProcessor", mucfilterProcessor);
packetProcessors.put("gojaraAdminProcessor", gojaraAdminProcessor);
frozen = false; frozen = false;
} }
public boolean addTransport(String subDomain) { public boolean addTransport(String subDomain) {
...@@ -55,7 +67,7 @@ public class MainInterceptor implements PacketInterceptor { ...@@ -55,7 +67,7 @@ public class MainInterceptor implements PacketInterceptor {
boolean retval = this.activeTransports.add(subDomain); boolean retval = this.activeTransports.add(subDomain);
if (retval) if (retval)
tSessionManager.addTransport(subDomain); tSessionManager.addTransport(subDomain);
return retval; return retval;
} }
...@@ -127,14 +139,14 @@ public class MainInterceptor implements PacketInterceptor { ...@@ -127,14 +139,14 @@ public class MainInterceptor implements PacketInterceptor {
packetProcessors.get("iqRosterPayload").process(packet, from, to, from); packetProcessors.get("iqRosterPayload").process(packet, from, to, from);
} }
// SPARK IQ REGISTERED Feature // SPARK IQ REGISTERED Feature
else if (query.getNamespaceURI().equals("http://jabber.org/protocol/disco#info") && to.length() > 0 && else if (query.getNamespaceURI().equals("http://jabber.org/protocol/disco#info") && to.length() > 0
activeTransports.contains(to) && iqPacket.getType().equals(IQ.Type.get)) { && activeTransports.contains(to) && iqPacket.getType().equals(IQ.Type.get)) {
packetProcessors.get("sparkIQRegistered").process(packet, to, to, from); packetProcessors.get("sparkIQRegistered").process(packet, to, to, from);
} }
// JABBER:IQ:LAST - Autoresponse Feature // JABBER:IQ:LAST - Autoresponse Feature
else if (JiveGlobals.getBooleanProperty("plugin.remoteroster.iqLastFilter", false) else if (JiveGlobals.getBooleanProperty("plugin.remoteroster.iqLastFilter", false)
&& query.getNamespaceURI().equals("jabber:iq:last")) { && query.getNamespaceURI().equals("jabber:iq:last")) {
String to_s = searchJIDforSubdomain(to); String to_s = searchJIDforSubdomain(to);
if (to_s.length() > 0 && iqPacket.getType().equals(IQ.Type.get)) if (to_s.length() > 0 && iqPacket.getType().equals(IQ.Type.get))
throw new PacketRejectedException(); throw new PacketRejectedException();
...@@ -148,32 +160,37 @@ public class MainInterceptor implements PacketInterceptor { ...@@ -148,32 +160,37 @@ public class MainInterceptor implements PacketInterceptor {
} else if (incoming && processed) { } else if (incoming && processed) {
// We ignore Pings from S2 to S2 itself. // We ignore Pings from S2 to S2 itself.
// STATISTICS - Feature // STATISTICS - Feature
String from_s = searchJIDforSubdomain(from); String from_searched = searchJIDforSubdomain(from);
String to_s = searchJIDforSubdomain(to); String to_searched = searchJIDforSubdomain(to);
String subdomain = from_s.length() == 0 ? to_s : from_s; String subdomain = from_searched.length() == 0 ? to_searched : from_searched;
if (!from.equals(to) && subdomain.length() > 0) if (!from.equals(to) && subdomain.length() > 0)
packetProcessors.get("statisticsProcessor").process(packet, subdomain, to, from); packetProcessors.get("statisticsProcessor").process(packet, subdomain, to, from);
// TransportSession Feature // TransportSession Feature
if (packet instanceof Presence && activeTransports.contains(from)){ if (packet instanceof Presence && activeTransports.contains(from)) {
Presence presence_packet = (Presence) packet; Presence presence_packet = (Presence) packet;
if (presence_packet.getType() == null) { if (presence_packet.getType() == null) {
tSessionManager.connectUserTo(from, packet.getTo().getNode().toString()); tSessionManager.connectUserTo(from, packet.getTo().getNode().toString());
} } else if (presence_packet.getType() != null && presence_packet.getType().equals(Presence.Type.unavailable)) {
else if (presence_packet.getType() != null && presence_packet.getType().equals(Presence.Type.unavailable)) {
tSessionManager.disconnectUserFrom(from, packet.getTo().getNode().toString()); tSessionManager.disconnectUserFrom(from, packet.getTo().getNode().toString());
} }
} else if (packet instanceof IQ && activeTransports.contains(to)) { }
// TransportSession Feature - track Registrations so we can reset unsuccesfull ones
else if (packet instanceof IQ && activeTransports.contains(to)) {
IQ iqPacket = (IQ) packet; IQ iqPacket = (IQ) packet;
Element query = iqPacket.getChildElement(); Element query = iqPacket.getChildElement();
if (query == null) if (query == null)
return; return;
if (query.getNamespaceURI().equals("jabber:iq:register")) { if (query.getNamespaceURI().equals("jabber:iq:register")) {
if (query.nodeCount() > 1) if (query.nodeCount() > 1)
tSessionManager.registerUserTo(to, iqPacket.getFrom().getNode().toString()); tSessionManager.registerUserTo(to, iqPacket.getFrom().getNode().toString());
else else
tSessionManager.removeRegistrationOfUser(to, iqPacket.getFrom().getNode().toString()); tSessionManager.removeRegistrationOfUser(to, iqPacket.getFrom().getNode().toString());
} }
}
// Gojara Admin Manager Feature - Intercept responses to ADHOC commands sent via AdminManager
else if (packet instanceof Message && activeTransports.contains(from) && to.contains("gojaraadmin")) {
packetProcessors.get("gojaraAdminProcessor").process(packet, from, to, from);
} }
} else if (!incoming && !processed) { } else if (!incoming && !processed) {
......
package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.sessions.TransportSessionManager;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
public class GojaraAdminProcessor extends AbstractRemoteRosterProcessor {
private TransportSessionManager transportSessionManager = TransportSessionManager.getInstance();
public GojaraAdminProcessor() {
Log.info("Created GojaraAdminProcessor");
}
/**
* Here we process the response of the remote command sent to Spectrum. We have to identify what kind of response it
* is, as no tag for the command being responded is being sent. Currently these commands are used in Gojara
* TransportSessionManager: online_users ( Chatmsg of online users for specific transport), usernames seperated by
* newlines
*/
@Override
public void process(Packet packet, String subdomain, String to, String from) throws PacketRejectedException {
Message message = (Message) packet;
String body = message.getBody();
// unregister <bare_jid>
if (body.endsWith("unregistered.") || body.endsWith("registered")) {
Log.info("Ignoring Message! " + message.toString());
}
// online_users
else {
String[] content = message.getBody().split("\\r?\\n");
for (String user : content) {
JID userjid = new JID(user);
transportSessionManager.connectUserTo(subdomain, userjid.getNode());
}
Log.info("Found online Users!" + message.toString());
}
}
}
\ No newline at end of file
package org.jivesoftware.openfire.plugin.gojara.sessions;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
/**
* This Class sends Ad-Hoc commands to given spectrum2 transports, which will then be intercepted by MainInterceptor,
* and processed by GojaraAdminProcessor
*
* @author axel.frederik.brand
*
*/
public class GojaraAdminManager {
private static GojaraAdminManager myself;
private PacketRouter router;
private static final Logger Log = LoggerFactory.getLogger(TransportSessionManager.class);
private JID adminUser;
private XMPPServer _server;
private GojaraAdminManager() {
_server = XMPPServer.getInstance();
router = _server.getPacketRouter();
UserManager userManager = UserManager.getInstance();
try {
userManager.createUser("gojaraadmin", "iAmTheLawgiver", "gojaraadmin", null);
Log.info("gojaraAdmin User created.");
} catch (UserAlreadyExistsException e) {
Log.info("gojaraAdmin User already created.");
}
adminUser = _server.createJID("gojaraadmin", null);
}
public static GojaraAdminManager getInstance() {
if (myself == null) {
myself = new GojaraAdminManager();
}
return myself;
}
public void removeAdminUser() {
UserManager userManager = UserManager.getInstance();
try {
userManager.deleteUser(userManager.getUser("gojaraadmin"));
} catch (UserNotFoundException e) {
Log.info("Couldn't remove adminUser.");
}
}
/**
* Sends the command online_users to specified Spectrum2 transport
* @param transport
*/
public void getOnlineUsersOf(String transport) {
Message message = new Message();
message.setFrom(adminUser);
message.setTo(transport);
message.setBody("online_users");
router.route(message);
Log.info("Sent following Packet!" + message.toString());
}
/**
* Sends the unregister <bare_jid> command to specified Spectrum2 transport
* @param transport
*/
public void unregisterUserFrom(String transport, String user) {
Message message = new Message();
message.setFrom(adminUser);
message.setTo(transport);
message.setBody("unregister " + _server.createJID(user, null).toString());
router.route(message);
Log.info("Sent following Packet!" + message.toString());
}
}
...@@ -13,21 +13,22 @@ import org.slf4j.LoggerFactory; ...@@ -13,21 +13,22 @@ import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
/** /**
* This is the central point for doing anything Gojara GatewaySession related, we can add component session, add * This is the central point for doing anything Gojara GatewaySession related. We keep track of Users connected to
* gatewaysession etc * Transports, stats about these and provide some methods for Presentation in JSP Pages.
* *
* @author axel.frederik.brand * @author axel.frederik.brand
*/ */
public class TransportSessionManager { public class TransportSessionManager {
private static TransportSessionManager myself; private static TransportSessionManager myself;
private DatabaseManager db; private DatabaseManager db;
private GojaraAdminManager adminManager;
private Map<String, Map<String, Date>> transportSessions = new ConcurrentHashMap<String, Map<String, Date>>(); private Map<String, Map<String, Date>> transportSessions = new ConcurrentHashMap<String, Map<String, Date>>();
private static final Logger Log = LoggerFactory.getLogger(TransportSessionManager.class); private static final Logger Log = LoggerFactory.getLogger(TransportSessionManager.class);
private TransportSessionManager() { private TransportSessionManager() {
db = DatabaseManager.getInstance(); db = DatabaseManager.getInstance();
adminManager = GojaraAdminManager.getInstance();
Log.info(" Created TransportSessionManager"); Log.info(" Created TransportSessionManager");
} }
public static TransportSessionManager getInstance() { public static TransportSessionManager getInstance() {
...@@ -109,21 +110,40 @@ public class TransportSessionManager { ...@@ -109,21 +110,40 @@ public class TransportSessionManager {
} }
/** /**
*
* Removing a registration will cause a unregister msg being sent to Spectrum2 for this specific User/Gateway * Removing a registration will cause a unregister msg being sent to Spectrum2 for this specific User/Gateway
* combination Also it will be removed from our db. * combination Also it will be removed from our db.
* For this to happen the transport has to be active.
* *
* @param transport * @param transport
* @param user * @param user
* @return * @return String that describes what happened.
*/ */
public String removeRegistrationOfUser(String transport, String user) { public String removeRegistrationOfUser(String transport, String user) {
int result = db.removeSessionEntry(transport, user); if (transportSessions.containsKey(transport)) {
if (result == 0) { adminManager.unregisterUserFrom(transport, user);
return "Did not remove entry for user: " + user + " and transport: " + transport + "\n"; int result = db.removeSessionEntry(transport, user);
} else if (result == 1) { if (result == 0) {
return "Successfully removed entry for user: " + user + " and transport: " + transport + " \n"; return "Did not remove entry for user: " + user + " and transport: " + transport + "\n";
} else if (result == 1) {
return "Successfully removed entry for user: " + user + " and transport: " + transport + " \n";
} else {
return "What is happening ???: " + result;
}
} else { } else {
return "What is happening ???: " + result; return "Cannot Unregister user " + user + " from " + transport + " when it's inactive.";
}
}
/**
* Initializes Sessions, ofc needs to be called at a point where there are Transports registered in
* transportSessions
*/
public void initializeSessions() {
Log.info("initializing Sessions.");
for (String transport : transportSessions.keySet()) {
adminManager.getOnlineUsersOf(transport);
} }
} }
......
...@@ -33,10 +33,6 @@ ...@@ -33,10 +33,6 @@
<meta name="pageID" content="gojaraSessions" /> <meta name="pageID" content="gojaraSessions" />
</head> </head>
<body> <body>
<center>Please be aware that currently only users that connect
AFTER GoJara has been started are considered for these Sessions. This
affects Plugin-restarts.</center>
<br>
<h4> <h4>
Current number of active Gateway Sessions: &emsp; Current number of active Gateway Sessions: &emsp;
<%=transportManager.getNumberOfActiveSessions()%> <%=transportManager.getNumberOfActiveSessions()%>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment