📄 iqrouter.java
字号:
routingTable = server.getRoutingTable();
multicastRouter = server.getMulticastRouter();
iqHandlers.addAll(server.getIQHandlers());
sessionManager = server.getSessionManager();
userManager = server.getUserManager();
}
/**
* A JID is considered local if:
* 1) is null or
* 2) has no domain or domain is empty
* or
* if it's not a full JID and it was sent to the server itself.
*
* @param recipientJID address to check.
* @return true if the specified address belongs to the local server.
*/
private boolean isLocalServer(JID recipientJID) {
// Check if no address was specified in the IQ packet
boolean implicitServer =
recipientJID == null || recipientJID.getDomain() == null || "".equals(recipientJID.getDomain());
if (!implicitServer) {
// We found an address. Now check if it's a bare or full JID
if (recipientJID.getNode() == null || recipientJID.getResource() == null) {
// Address is a bare JID so check if it was sent to the server itself
return serverName.equals(recipientJID.getDomain());
}
// Address is a full JID. IQ packets sent to full JIDs are not handle by the server
return false;
}
return true;
}
private void handle(IQ packet) {
JID recipientJID = packet.getTo();
// Check if the packet was sent to the server hostname
if (recipientJID != null && recipientJID.getNode() == null &&
recipientJID.getResource() == null && serverName.equals(recipientJID.getDomain())) {
Element childElement = packet.getChildElement();
if (childElement != null && childElement.element("addresses") != null) {
// Packet includes multicast processing instructions. Ask the multicastRouter
// to route this packet
multicastRouter.route(packet);
return;
}
else if (IQ.Type.result == packet.getType() || IQ.Type.error == packet.getType()) {
// The server got an answer to an IQ packet that was sent from the server
IQResultListener iqResultListener = resultListeners.remove(packet.getID());
resultTimeout.remove(packet.getID());
if (iqResultListener != null) {
try {
iqResultListener.receivedAnswer(packet);
}
catch (Exception e) {
Log.error("Error processing answer of remote entity", e);
}
return;
}
}
}
try {
// Check for registered components, services or remote servers
if (recipientJID != null &&
(routingTable.hasComponentRoute(recipientJID) || routingTable.hasServerRoute(recipientJID))) {
// A component/service/remote server was found that can handle the Packet
routingTable.routePacket(recipientJID, packet, false);
return;
}
if (isLocalServer(recipientJID)) {
// Let the server handle the Packet
Element childElement = packet.getChildElement();
String namespace = null;
if (childElement != null) {
namespace = childElement.getNamespaceURI();
}
if (namespace == null) {
if (packet.getType() != IQ.Type.result && packet.getType() != IQ.Type.error) {
// Do nothing. We can't handle queries outside of a valid namespace
Log.warn("Unknown packet " + packet);
}
}
else {
// Check if communication to local users is allowed
if (recipientJID != null && userManager.isRegisteredUser(recipientJID.getNode())) {
PrivacyList list =
PrivacyListManager.getInstance().getDefaultPrivacyList(recipientJID.getNode());
if (list != null && list.shouldBlockPacket(packet)) {
// Communication is blocked
if (IQ.Type.set == packet.getType() || IQ.Type.get == packet.getType()) {
// Answer that the service is unavailable
sendErrorPacket(packet, PacketError.Condition.service_unavailable);
}
return;
}
}
IQHandler handler = getHandler(namespace);
if (handler == null) {
if (recipientJID == null) {
// Answer an error since the server can't handle the requested namespace
sendErrorPacket(packet, PacketError.Condition.service_unavailable);
}
else if (recipientJID.getNode() == null ||
"".equals(recipientJID.getNode())) {
// Answer an error if JID is of the form <domain>
sendErrorPacket(packet, PacketError.Condition.feature_not_implemented);
}
else {
// JID is of the form <node@domain>
// Answer an error since the server can't handle packets sent to a node
sendErrorPacket(packet, PacketError.Condition.service_unavailable);
}
}
else {
handler.process(packet);
}
}
}
else {
// JID is of the form <node@domain/resource> or belongs to a remote server
// or to an uninstalled component
routingTable.routePacket(recipientJID, packet, false);
}
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
IQ reply = IQ.createResultIQ(packet);
reply.setError(PacketError.Condition.internal_server_error);
session.process(reply);
}
}
}
private void sendErrorPacket(IQ originalPacket, PacketError.Condition condition) {
if (IQ.Type.error == originalPacket.getType()) {
Log.error("Cannot reply an IQ error to another IQ error: " + originalPacket);
return;
}
IQ reply = IQ.createResultIQ(originalPacket);
reply.setChildElement(originalPacket.getChildElement().createCopy());
reply.setError(condition);
// Check if the server was the sender of the IQ
if (serverName.equals(originalPacket.getFrom().toString())) {
// Just let the IQ router process the IQ error reply
handle(reply);
return;
}
// Route the error packet to the original sender of the IQ.
routingTable.routePacket(reply.getTo(), reply, true);
}
private IQHandler getHandler(String namespace) {
IQHandler handler = namespace2Handlers.get(namespace);
if (handler == null) {
for (IQHandler handlerCandidate : iqHandlers) {
IQHandlerInfo handlerInfo = handlerCandidate.getInfo();
if (handlerInfo != null && namespace.equalsIgnoreCase(handlerInfo.getNamespace())) {
handler = handlerCandidate;
namespace2Handlers.put(namespace, handler);
break;
}
}
}
return handler;
}
/**
* Notification message indicating that a packet has failed to be routed to the receipient.
*
* @param receipient address of the entity that failed to receive the packet.
* @param packet IQ packet that failed to be sent to the receipient.
*/
public void routingFailed(JID receipient, Packet packet) {
IQ iq = (IQ) packet;
// If a route to the target address was not found then try to answer a
// service_unavailable error code to the sender of the IQ packet
if (IQ.Type.result != iq.getType() && IQ.Type.error != iq.getType()) {
Log.info("Packet sent to unreachable address " + packet);
sendErrorPacket(iq, PacketError.Condition.service_unavailable);
}
else {
Log.warn("Error or result packet could not be delivered " + packet);
}
}
/**
* Timer task that will remove Listeners that wait for results to IQ stanzas
* that have timed out. Time out values can be set to each listener
* individually by adjusting the timeout value in the third parameter of
* {@link IQRouter#addIQResultListener(String, IQResultListener, long)}.
*
* @author Guus der Kinderen, guus@nimbuzz.com
*/
private class TimeoutTask extends TimerTask {
/**
* Iterates over and removes all timed out results.<p>
*
* The map that keeps track of timeout values is ordered by timeout
* date. This way, iteration can be stopped as soon as the first value
* has been found that didn't timeout yet.
*/
@Override
public void run() {
// Use an Iterator to allow changes to the Map that is backing
// the Iterator.
final Iterator<Map.Entry<String, Long>> it = resultTimeout.entrySet().iterator();
while (it.hasNext()) {
final Map.Entry<String, Long> pointer = it.next();
if (System.currentTimeMillis() < pointer.getValue()) {
// This entry has not expired yet. Ignore it.
continue;
}
final String packetId = pointer.getKey();
// remove this listener from the list
final IQResultListener listener = resultListeners.remove(packetId);
if (listener != null) {
// notify listener of the timeout.
listener.answerTimeout(packetId);
}
// remove the packet from the list that's used to track
// timeouts
it.remove();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -