/* * Copyright (C) 2005-2010 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jinglenodes; import org.dom4j.Element; import org.dom4j.DocumentHelper; import org.jivesoftware.openfire.XMPPServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xmpp.component.AbstractComponent; import org.xmpp.jnodes.RelayChannel; import org.xmpp.jnodes.RelayPublicMask; import org.xmpp.jnodes.nio.LocalIPResolver; import org.xmpp.jnodes.smack.JingleChannelIQ; import org.xmpp.jnodes.smack.JingleTrackerIQ; import org.xmpp.jnodes.smack.TrackerEntry; import org.xmpp.packet.IQ; import org.xmpp.packet.PacketError; import java.util.List; import java.util.ArrayList; class JingleNodesComponent extends AbstractComponent { private static final Logger Log = LoggerFactory.getLogger(JingleNodesComponent.class); private static final String UDP = "udp"; private static final String PROTOCOL = "protocol"; private static final String HOST = "host"; private static final String LOCAL_PORT = "localport"; private static final String REMOTE_PORT = "remoteport"; private final JingleNodesPlugin plugin; public JingleNodesComponent(final JingleNodesPlugin plugin) { this.plugin = plugin; } public String getName() { return "JingleRelayNode"; } public String getDescription() { return "Jingle Relay Service"; } @Override protected String[] discoInfoFeatureNamespaces() { return new String[]{JingleChannelIQ.NAMESPACE, JingleTrackerIQ.NAMESPACE}; } @Override protected String discoInfoIdentityCategoryType() { return "relay"; } @Override protected IQ handleIQGet(IQ iq) throws Exception { final IQ reply = IQ.createResultIQ(iq); final Element element = iq.getChildElement(); final String namespace = element.getNamespaceURI(); if (JingleChannelIQ.NAME.equals(element.getName()) && JingleChannelIQ.NAMESPACE.equals(namespace) && UDP.equals(element.attributeValue(PROTOCOL))) { final Element childElement = iq.getChildElement().createCopy(); final RelayChannel channel = plugin.createRelayChannel(); if (channel != null) { childElement.addAttribute(HOST, plugin.getPublicIP()); childElement.addAttribute(LOCAL_PORT, Integer.toString(channel.getPortA())); childElement.addAttribute(REMOTE_PORT, Integer.toString(channel.getPortB())); reply.setChildElement(childElement); Log.debug("Created relay channel {}:{}, {}:{}, {}:{}", new Object[]{HOST, plugin.getPublicIP(), LOCAL_PORT, Integer.toString(channel.getPortA()), REMOTE_PORT, Integer.toString(channel.getPortB())}); } else { reply.setError(PacketError.Condition.internal_server_error); } return reply; } else if (JingleTrackerIQ.NAME.equals(element.getName()) && JingleTrackerIQ.NAMESPACE.equals(namespace)) { final List<TrackerEntry> entries = new ArrayList<TrackerEntry>(); entries.add(new TrackerEntry(TrackerEntry.Type.relay, TrackerEntry.Policy._roster, plugin.getServiceName() + "." + getDomain(), UDP)); final String elements = getChildElementXML(entries); final Element e = DocumentHelper.parseText(elements).getRootElement(); reply.setChildElement(e); return reply; } return null; // feature not implemented. } public String getChildElementXML(final List<TrackerEntry> entries) { final StringBuilder str = new StringBuilder(); str.append("<").append(JingleTrackerIQ.NAME).append(" xmlns='").append(JingleTrackerIQ.NAMESPACE).append("'>"); for (final TrackerEntry entry : entries) { str.append("<").append(entry.getType().toString()); str.append(" policy='").append(entry.getPolicy().toString()).append("'"); str.append(" address='").append(entry.getJid()).append("'"); str.append(" protocol='").append(entry.getProtocol()).append("'"); if (entry.isVerified()) { str.append(" verified='").append(entry.isVerified()).append("'"); } str.append("/>"); } str.append("</").append(JingleTrackerIQ.NAME).append(">"); return str.toString(); } @Override public String getDomain() { return XMPPServer.getInstance().getServerInfo().getXMPPDomain(); } }