Commit 9f60c13c authored by Thiago Camargo's avatar Thiago Camargo Committed by thiago

Media Proxy Service embed into Wildfire

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@6516 b35dd754-fafc-0310-a699-88a17e54d16e
parent ed200426
......@@ -43,6 +43,7 @@ import org.jivesoftware.wildfire.transport.TransportHandler;
import org.jivesoftware.wildfire.update.UpdateManager;
import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.vcard.VCardManager;
import org.jivesoftware.wildfire.mediaproxy.MediaProxyService;
import org.xmpp.packet.JID;
import java.io.File;
......@@ -487,6 +488,7 @@ public class XMPPServer {
loadModule(IQPrivacyHandler.class.getName());
loadModule(DefaultFileTransferManager.class.getName());
loadModule(FileTransferProxy.class.getName());
loadModule(MediaProxyService.class.getName());
loadModule(PubSubModule.class.getName());
loadModule(UpdateManager.class.getName());
loadModule(InternalComponentManager.class.getName());
......@@ -1261,6 +1263,17 @@ public class XMPPServer {
return (FileTransferManager) modules.get(DefaultFileTransferManager.class);
}
/**
* Returns the <code>MediaProxyService</code> registered with this server. The
* <code>MediaProxyService</code> was registered with the server as a module while starting up
* the server.
*
* @return the <code>FileTransferProxy</code> registered with this server.
*/
public MediaProxyService getMediaProxyService() {
return (MediaProxyService) modules.get(MediaProxyService.class);
}
/**
* Returns the <code>InternalComponentManager</code> registered with this server. The
* <code>InternalComponentManager</code> was registered with the server as a module while starting up
......
package org.jivesoftware.wildfire.mediaproxy;
import java.net.DatagramPacket;
/**
* Interface to listener datagramReceived events
*/
public interface DatagramListener {
/**
* Called when a datagram is received.
* If method return false the packet MUST NOT be resent from the received Channel.
* @param datagramPacket The received datagram
*/
public boolean datagramReceived(DatagramPacket datagramPacket);
}
package org.jivesoftware.wildfire.mediaproxy;
import java.util.List;
import java.util.ArrayList;
import java.net.InetAddress;
/**
* MediaProxy create and bind relay channels between IP pairs.
* This relay can provite UDP connectivity between two parties that are behind NAT.
* It also work to provide connectivity between two parties that are directly connected to the internet or one party in the internet and another behind a NAT.
* The RTPPRoxy Class add and control the Bridge Agents.
* You can setup a MediaProxy for all your network interfaces with a empty constructor,
* or bind it to an especific interface with MediaProxy(String localhost) constructor.
* <i>This MediaProxy ONLY works if your are Direct Connected to the Internet with a valid IP address.</i>
*/
public class MediaProxy implements SessionListener {
final private List<Session> sessions = new ArrayList<Session>();
private String localhost;
private int minPort = 10000;
private int maxPort = 20000;
private long keepAliveDelay = 90000;
/**
* Contruct a MediaProxy instance that will listen from every Network Interface.
* Recommended.
*/
public MediaProxy() {
this.localhost = "localhost";
}
/**
* Contruct a MediaProxy instance that will listen from an especific Network Interface.
*
* @param localhost The IP of the locahost that will listen for packets.
*/
public MediaProxy(String localhost) {
this.localhost = localhost;
}
/**
* Get the public IP of this RTP Proxy that listen for the incomming packets
*
* @return Your selected localhost that listen for the incomming packets
*/
public String getPublicIP() {
return localhost;
}
/**
* Get time in millis that an Session can stay without receive any packet.
* After this time it is auto closed.
*
* @return Time in millis
*/
public long getKeepAliveDelay() {
return keepAliveDelay;
}
/**
* Set time in millis that an Session can stay without receive any packet.
* After this time it is auto closed.
*
* @return Time in millis
*/
public void setKeepAliveDelay(long keepAliveDelay) {
this.keepAliveDelay = keepAliveDelay;
}
/**
* Get the List of all the current active and running Agents.
*
* @return List of the Agents
*/
public List<Session> getAgents() {
return sessions;
}
/**
* Get Minimal port value to listen from incoming packets.
*
* @return
*/
public int getMinPort() {
return minPort;
}
/**
* Set Minimal port value to listen from incoming packets.
*
* @param minPort
*/
public void setMinPort(int minPort) {
this.minPort = minPort;
}
/**
* Get Maximum port value to listen from incoming packets.
*
* @return
*/
public int getMaxPort() {
return maxPort;
}
/**
* Set Maximum port value to listen from incoming packets.
*
* @param maxPort
*/
public void setMaxPort(int maxPort) {
this.maxPort = maxPort;
}
/**
* Get the agent with an especified ID
*
* @param sid the session ID
*/
public Session getAgent(String sid) {
for (Session session : sessions) {
if (session.getSID().equals(sid)) {
System.out.println("SID: " + sid + " agentSID: " + session.getSID());
return session;
}
}
return null;
}
/**
* Implements Session Listener stopAgent event.
* Remove the stopped session from the sessions list.
*
* @param session
*/
public void agentStopped(Session session) {
System.out.println("Session: " + session.getSID() + " removed: " + sessions.remove(session));
}
/**
* Add a new Static Session to the mediaproxy for defined IPs and ports.
* Create a channel between two IPs. ( Point A - Point B )
*
* @param id id of the candidate returned (Could be a Jingle session ID)
* @param hostA the hostname or IP of the point A of the Channel
* @param portA the port number point A of the Channel
* @param hostB the hostname or IP of the point B of the Channel
* @param portB the port number point B of the Channel
* @return the added ProxyCandidate
*/
public ProxyCandidate addAgent(String id, String creator, String hostA, int portA, String hostB,
int portB) {
final Session session =
new Session(id, creator, localhost, hostA, portA, hostB, portB, minPort, maxPort);
if (session != null) {
sessions.add(session);
session.addKeepAlive(keepAliveDelay);
session.addAgentListener(this);
}
return session;
}
/**
* Add a new Dynamic Session to the mediaproxy for defined IPs and ports.
* The IP and port pairs can change depending of the Senders IP and port.
* Which means that the IP and port values of the points can dynamic change after the Channel is opened.
* When the agent receives a packet from Point A, the channel set the point A IP and port according to the received packet sender IP and port.
* Every packet received from Point B will be relayed to the new Point A IP and port.
* When the agent receives a packet from Point B, the channel set the point B IP and port according to the received packet sender IP and port.
* Every packet received from Point A will be relayed to the new Point B IP and port.
* Create a dynamic channel between two IPs. ( Dynamic Point A - Dynamic Point B )
*
* @param id id of the candidate returned (Could be a Jingle session ID)
* @param hostA the hostname or IP of the point A of the Channel
* @param portA the port number point A of the Channel
* @param hostB the hostname or IP of the point B of the Channel
* @param portB the port number point B of the Channel
* @return the added ProxyCandidate
*/
public ProxyCandidate addSmartAgent(String id, String creator, String hostA, int portA,
String hostB, int portB) {
final SmartSession agent = new SmartSession(id, creator, localhost, hostA, portA, hostB, portB,
minPort, maxPort);
if (agent != null) {
sessions.add(agent);
agent.addKeepAlive(keepAliveDelay);
agent.addAgentListener(this);
}
return agent;
}
/**
* Add a new Dynamic Session to the mediaproxy WITHOUT defined IPs and ports.
* The IP and port pairs WILL change depending of the Senders IP and port.
* Which means that the IP and port values of the points will dynamic change after the Channel is opened and received packet from both points.
* When the agent receives a packet from Point A, the channel set the point A IP and port according to the received packet sender IP and port.
* Every packet received from Point B will be relayed to the new Point A IP and port.
* When the agent receives a packet from Point B, the channel set the point B IP and port according to the received packet sender IP and port.
* Every packet received from Point A will be relayed to the new Point B IP and port.
* Create a dynamic channel between two IPs. ( Dynamic Point A - Dynamic Point B )
*
* @param id id of the candidate returned (Could be a Jingle session ID)
* @return the added ProxyCandidate
*/
public ProxyCandidate addSmartAgent(String id, String creator) {
return addSmartAgent(id, creator, localhost, 40000, localhost, 40004);
}
/**
* Stop every running sessions.
*/
public void stopProxy() {
for (Session session : getAgents()) {
try {
session.clearAgentListeners();
session.stopAgent();
}
catch (Exception e) {
e.printStackTrace();
}
}
sessions.clear();
}
public static void main(String args[]) {
MediaProxy media = new MediaProxy();
ProxyCandidate ag = media.addSmartAgent("abc", "tester", "200.233.136.54", 20001,
"200.233.136.54", 20008);
ag.start();
try {
Thread.sleep(5000);
System.out.println(InetAddress.getByName("0.0.0.0"));
}
catch (Exception e) {
}
ag.stopAgent();
System.out.println("Closed");
}
}
package org.jivesoftware.wildfire.mediaproxy;
import org.dom4j.Attribute;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.container.BasicModule;
import org.jivesoftware.wildfire.disco.DiscoInfoProvider;
import org.jivesoftware.wildfire.disco.DiscoItemsProvider;
import org.jivesoftware.wildfire.disco.DiscoServerItem;
import org.jivesoftware.wildfire.disco.ServerItemsProvider;
import org.jivesoftware.wildfire.forms.spi.XDataFormImpl;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* RTP Bridge Media Proxy service plugin.
* Provides especial relayed Jingle transport candidates to be used for media transmission and receiving of UDP packets.
* Especialy used for behind NAT users to ensure connectivity between parties.
*
* @author Thiago Camargo
*/
public class MediaProxyService extends BasicModule implements ServerItemsProvider, RoutableChannelHandler, DiscoInfoProvider, DiscoItemsProvider {
private String serviceName;
private RoutingTable routingTable;
private PacketRouter router;
private MediaProxy mediaProxy = null;
private String name = "rtpbridge";
private boolean enabled = false;
public static final String NAMESPACE = "http://www.jivesoftware.com/protocol/rtpbridge";
/**
* Constructs a new RTPBridgePlugin plugin.
*/
public MediaProxyService() {
super("Media Proxy Service");
}
/**
* Load config using JiveGlobals
*/
private void loadRTPProxyConfig() {
try {
long keepAliveDelay =
Long.valueOf(JiveGlobals.getProperty("plugin.rtpbridge.keepalivedelay"));
mediaProxy.setKeepAliveDelay(keepAliveDelay);
}
catch (NumberFormatException e) {
// Do nothing let the default values to be used.
}
try {
int minPort = Integer.valueOf(JiveGlobals.getProperty("plugin.rtpbridge.minport"));
mediaProxy.setMinPort(minPort);
}
catch (NumberFormatException e) {
// Do nothing let the default values to be used.
}
try {
int maxPort = Integer.valueOf(JiveGlobals.getProperty("plugin.rtpbridge.maxport"));
mediaProxy.setMaxPort(maxPort);
}
catch (NumberFormatException e) {
// Do nothing let the default values to be used.
}
try {
boolean enabled = Boolean.valueOf(JiveGlobals.getProperty("plugin.rtpbridge.enabled"));
this.enabled = enabled;
}
catch (NumberFormatException e) {
this.enabled = false;
}
}
public void destroy() {
super.destroy();
// Unregister component.
try {
mediaProxy.stopProxy();
}
catch (Exception e) {
Log.error(e);
}
mediaProxy = null;
}
public void initialize(XMPPServer server) {
super.initialize(server);
String hostname = JiveGlobals.getProperty("xmpp.domain",
JiveGlobals.getProperty("network.interface", "localhost"));
mediaProxy = new MediaProxy(hostname);
serviceName = JiveGlobals.getProperty("plugin.rtpbridge.serviceName", name);
serviceName = serviceName == null ? name : serviceName.equals("") ? name : serviceName;
routingTable = server.getRoutingTable();
router = server.getPacketRouter();
loadRTPProxyConfig();
}
public void start() {
if (isEnabled()) {
startProxy();
} else {
XMPPServer.getInstance().getIQDiscoItemsHandler().removeServerItemsProvider(this);
}
}
public void startProxy() {
routingTable.addRoute(getAddress(), this);
XMPPServer server = XMPPServer.getInstance();
server.getIQDiscoItemsHandler().addServerItemsProvider(this);
}
public void stop() {
super.stop();
mediaProxy.stopProxy();
XMPPServer.getInstance().getIQDiscoItemsHandler()
.removeComponentItem(getAddress().toString());
routingTable.removeRoute(getAddress());
}
// Component Interface
public String getName() {
// Get the name from the plugin.xml file.
return serviceName;
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
// A proxy server has no items
return new ArrayList<Element>().iterator();
}
public void process(Packet packet) throws UnauthorizedException, PacketException {
// Check if user is allowed to send packet to this service
Log.debug("TEST");
if (packet instanceof IQ) {
// Handle disco packets
IQ iq = (IQ) packet;
// Ignore IQs of type ERROR or RESULT
if (IQ.Type.error == iq.getType() || IQ.Type.result == iq.getType()) {
return;
}
processIQ(iq);
}
}
private void processIQ(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
Element childElement = iq.getChildElement();
String namespace = childElement.getNamespaceURI();
Element childElementCopy = iq.getChildElement().createCopy();
reply.setChildElement(childElementCopy);
Log.debug("RECEIVED:" + iq.toXML());
if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
try {
reply = XMPPServer.getInstance().getIQDiscoInfoHandler().handleIQ(iq);
router.route(reply);
return;
}
catch (UnauthorizedException e) {
// Do nothing. This error should never happen
}
} else if ("http://jabber.org/protocol/disco#items".equals(namespace)) {
try {
// a component
reply = XMPPServer.getInstance().getIQDiscoItemsHandler().handleIQ(iq);
router.route(reply);
return;
}
catch (UnauthorizedException e) {
// Do nothing. This error should never happen
}
} else if (NAMESPACE.equals(namespace) && enabled) {
Element c = childElementCopy.element("candidate");
if (c != null) {
childElementCopy.remove(c);
Element candidate = childElementCopy.addElement("candidate ");
ProxyCandidate proxyCandidate = mediaProxy.addSmartAgent(
childElementCopy.attribute("sid").getValue() + "-" + iq.getFrom(),
iq.getFrom().toString());
Log.debug(childElementCopy.attribute("sid").getValue() + "-" + iq.getFrom());
proxyCandidate.start();
candidate.addAttribute("name", "voicechannel");
candidate.addAttribute("ip", mediaProxy.getPublicIP());
candidate.addAttribute("porta", String.valueOf(proxyCandidate.getLocalPortA()));
candidate.addAttribute("portb", String.valueOf(proxyCandidate.getLocalPortB()));
candidate.addAttribute("pass", proxyCandidate.getPass());
} else {
c = childElementCopy.element("relay");
if (c != null) {
Session session = mediaProxy.getAgent(
childElementCopy.attribute("sid").getValue() + "-" + iq.getFrom());
Log.debug(
childElementCopy.attribute("sid").getValue() + "-" + iq.getFrom());
if (session != null) {
Attribute pass = c.attribute("pass");
if (pass != null && pass.getValue().trim().equals(session.getPass().trim())) {
Log.debug("RIGHT PASS");
Attribute portA = c.attribute("porta");
Attribute portB = c.attribute("portb");
Attribute hostA = c.attribute("hosta");
Attribute hostB = c.attribute("hostb");
try {
if (hostA != null) {
if (portA != null) {
for (int i = 0; i < 2; i++) {
session.sendFromPortA(hostB.getValue(),
Integer.parseInt(portB.getValue()));
}
}
}
}
catch (Exception e) {
Log.error(e);
}
//System.out.println(session.getLocalPortA() + "->" + session.getPortA());
//System.out.println(session.getLocalPortB() + "->" + session.getPortB());
//componentManager.getLog().debug(session.getLocalPortA() + "->" + session.getPortA());
//componentManager.getLog().debug(session.getLocalPortB() + "->" + session.getPortB());
} else {
Log.debug("WRONG PASS " + session.getPass() + " " + pass.getValue());
reply.setError(PacketError.Condition.forbidden);
}
}
childElementCopy.remove(c);
}
}
} else {
// Answer an error since the server can't handle the requested namespace
reply.setError(PacketError.Condition.service_unavailable);
}
try {
Log.debug("RETURNED:" + reply.toXML());
router.route(reply);
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Returns the fully-qualifed domain name of this chat service.
* The domain is composed by the service name and the
* name of the XMPP server where the service is running.
*
* @return the file transfer server domain (service name + host name).
*/
public String getServiceDomain() {
return serviceName + "." + XMPPServer.getInstance().getServerInfo().getName();
}
public JID getAddress() {
return new JID(null, getServiceDomain(), null);
}
public Iterator<DiscoServerItem> getItems() {
List<DiscoServerItem> items = new ArrayList<DiscoServerItem>();
if (!isEnabled()) {
return items.iterator();
}
items.add(new DiscoServerItem() {
public String getJID() {
return getServiceDomain();
}
public String getName() {
return "Media Proxy Service";
}
public String getAction() {
return null;
}
public String getNode() {
return null;
}
public DiscoInfoProvider getDiscoInfoProvider() {
return MediaProxyService.this;
}
public DiscoItemsProvider getDiscoItemsProvider() {
return MediaProxyService.this;
}
});
return items.iterator();
}
public Iterator<Element> getIdentities(String name, String node, JID senderJID) {
List<Element> identities = new ArrayList<Element>();
// Answer the identity of the proxy
Element identity = DocumentHelper.createElement("identity");
identity.addAttribute("category", "proxy");
identity.addAttribute("name", "Media Proxy Service");
identity.addAttribute("type", "rtpbridge");
identities.add(identity);
return identities.iterator();
}
public Iterator<String> getFeatures(String name, String node, JID senderJID) {
return Arrays.asList(NAMESPACE,
"http://jabber.org/protocol/disco#info").iterator();
}
public XDataFormImpl getExtendedInfo(String name, String node, JID senderJID) {
return null;
}
public boolean hasInfo(String name, String node, JID senderJID) {
return true;
}
/**
* Return the list of active Agents
*
* @return
*/
public List<Session> getAgents() {
return mediaProxy.getAgents();
}
/**
* Set the keep alive delay of the mediaproxy agents.
* When an agent stay more then this delay, the agent is destroyed.
*
* @param delay time in millis
*/
public void setKeepAliveDelay(long delay) {
mediaProxy.setKeepAliveDelay(delay);
}
/**
* Get the keep alive delay of the mediaproxy agents.
* When an agent stay more then this delay, the agent is destroyed.
*
* @return delay time in millis
*/
public long getKeepAliveDelay() {
return mediaProxy.getKeepAliveDelay();
}
/**
* Set Minimal port value to listen from incoming packets.
*
* @param minPort
*/
public void setMinPort(int minPort) {
mediaProxy.setMinPort(minPort);
}
/**
* Set Maximum port value to listen from incoming packets.
*
* @param maxPort
*/
public void setMaxPort(int maxPort) {
mediaProxy.setMaxPort(maxPort);
}
/**
* Get Minimal port value to listen from incoming packets.
*
* @return minPort
*/
public int getMinPort() {
return mediaProxy.getMinPort();
}
/**
* Get Maximum port value to listen from incoming packets.
*
* @return maxPort
*/
public int getMaxPort() {
return mediaProxy.getMaxPort();
}
/**
* Get if the service is enabled.
*
* @return enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Set the service enable status.
*
* @param enabled
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
if (isEnabled()) {
startProxy();
} else {
stop();
}
}
/**
* Stops every running agents
*/
public void stopAgents() {
mediaProxy.stopProxy();
}
}
package org.jivesoftware.wildfire.mediaproxy;
import java.net.InetAddress;
/**
* Basic interface to access a Candidate provided by a Session
*/
public interface ProxyCandidate {
public String getSID();
public String getPass();
public InetAddress getLocalhost();
public InetAddress getHostA();
public InetAddress getHostB();
public void setHostA(InetAddress hostA);
public void setHostB(InetAddress hostB);
public void sendFromPortA(String host, int port);
public void sendFromPortB(String host, int port);
public int getPortA();
public int getPortB();
public void setPortA(int portA);
public void setPortB(int portB);
public int getLocalPortA();
public int getLocalPortB();
public void start();
public void stopAgent();
}
package org.jivesoftware.wildfire.mediaproxy;
import java.util.*;
import java.net.*;
import java.io.IOException;
/**
* A Session Class will control "receive and relay" proccess.
* It creates an UDP channel from Host A to Host B and from Host B to Host A using their specified hosts and ports.
* It has 4 Channels. 2 for data and 2 for control.
*/
public class Session extends Thread implements ProxyCandidate, DatagramListener {
private List<SessionListener> sessionListeners = new ArrayList<SessionListener>();
private String id;
private String pass;
private String creator = "";
private long timestamp = 0;
protected InetAddress localhost;
protected InetAddress hostA;
protected InetAddress hostB;
protected int portA;
protected int portB;
protected int localPortA;
protected int localPortB;
protected DatagramSocket socketA;
protected DatagramSocket socketAControl;
protected DatagramSocket socketB;
protected DatagramSocket socketBControl;
protected Channel channelAtoB;
protected Channel channelAtoBControl;
protected Channel channelBtoA;
protected Channel channelBtoAControl;
protected Thread threadAtoB;
protected Thread threadAtoBControl;
protected Thread threadBtoA;
protected Thread threadBtoAControl;
private Timer keepAliveTimer = null;
private int minPort = 10000;
private int maxPort = 20000;
/**
* Creates a new static UDP channel between Host A and Host B.
*
* @param id of the Session (Could be a Jingle session ID)
* @param localhost The localhost IP that will listen for UDP packets
* @param hostA the hostname or IP of the point A of the Channel
* @param portA the port number point A of the Channel
* @param hostB the hostname or IP of the point B of the Channel
* @param portB the port number point B of the Channel
*/
public Session(String id, String creator, String localhost, String hostA, int portA, String hostB, int portB) {
this(id, creator, localhost, hostA, portA, hostB, portB,10000,20000);
}
/**
* Creates a new static UDP channel between Host A and Host B.
*
* @param id of the Session (Could be a Jingle session ID)
* @param localhost The localhost IP that will listen for UDP packets
* @param hostA the hostname or IP of the point A of the Channel
* @param portA the port number point A of the Channel
* @param hostB the hostname or IP of the point B of the Channel
* @param portB the port number point B of the Channel
*/
public Session(String id, String creator, String localhost, String hostA, int portA, String hostB, int portB, int minPort, int maxPort) {
this.id = id;
this.creator = creator;
this.minPort = minPort;
this.maxPort = maxPort;
this.pass = String.valueOf(Math.abs(new Random().nextLong()));
try {
this.hostA = InetAddress.getByName(hostA);
this.hostB = InetAddress.getByName(hostB);
this.portA = portA;
this.portB = portB;
this.localhost = InetAddress.getByName(localhost);
this.localPortA = getFreePort();
this.socketA = new DatagramSocket(localPortA, this.localhost);
this.socketAControl = new DatagramSocket(localPortA + 1, this.localhost);
this.localPortB = getFreePort();
this.socketB = new DatagramSocket(localPortB, this.localhost);
this.socketBControl = new DatagramSocket(localPortB + 1, this.localhost);
System.out.println("Session Created at: A " + localPortA + " : B " + localPortB);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Obtain a free port with a nested control port we can use.
*
* @return A free port number.
*/
protected int getFreePort() {
ServerSocket ss;
int freePort = 0;
int controlPort = 0;
for (int i = 0; i < 10; i++) {
freePort = (int) (minPort + Math.round(Math.random() * (maxPort - minPort)));
freePort = freePort % 2 == 0 ? freePort : freePort + 1;
try {
ss = new ServerSocket(freePort);
freePort = ss.getLocalPort();
ss.close();
ss = new ServerSocket(freePort + 1);
controlPort = ss.getLocalPort();
ss.close();
if (controlPort == (freePort + 1))
return freePort;
}
catch (IOException e) {
e.printStackTrace();
}
}
try {
ss = new ServerSocket(0);
freePort = ss.getLocalPort();
ss.close();
}
catch (IOException e) {
e.printStackTrace();
} finally {
ss = null;
}
return freePort;
}
/**
* Get the ID of the Session
*
* @return
*/
public String getSID() {
return id;
}
/**
* Get the pass of this Session
* A pass can be used to authorize an Session modification
*/
public String getPass() {
return pass;
}
/**
* Get the agent creator.
* This field is open to MediaProxy users and just can be set in constructor.
*
* @return
*/
public String getCreator() {
return creator;
}
/**
* Get last packet arrived timestamp
*
* @return TimeStamp in Millis
*/
public long getTimestamp() {
return timestamp;
}
/**
* Thread override method
*/
public void run() {
channelAtoB = new Channel(socketA, hostB, portB);
channelAtoBControl = new Channel(socketAControl, hostB, portB + 1);
channelBtoA = new Channel(socketB, hostA, portA);
channelBtoAControl = new Channel(socketBControl, hostA, portA + 1);
threadAtoB = new Thread(channelAtoB);
threadAtoBControl = new Thread(channelAtoBControl);
threadBtoA = new Thread(channelBtoA);
threadBtoAControl = new Thread(channelBtoAControl);
threadAtoB.start();
threadAtoBControl.start();
threadBtoA.start();
threadBtoAControl.start();
channelAtoB.addListener(this);
channelAtoBControl.addListener(this);
channelBtoA.addListener(this);
channelBtoAControl.addListener(this);
//System.out.println("Session running between " + hostA + " and " + hostB);
}
/**
* Stop the Session
*/
public void stopAgent() {
try {
if (keepAliveTimer != null) {
keepAliveTimer.cancel();
keepAliveTimer.purge();
keepAliveTimer = null;
}
} catch (Exception e) {
e.printStackTrace();
}
channelAtoB.removeListener();
channelAtoBControl.removeListener();
channelBtoA.removeListener();
channelBtoAControl.removeListener();
try {
threadAtoB.stop();
threadAtoBControl.stop();
threadBtoA.stop();
threadBtoAControl.stop();
} catch (Exception e) {
e.printStackTrace();
}
socketA.close();
socketAControl.close();
socketB.close();
socketBControl.close();
dispatchAgentStopped();
System.out.println("Session Stopped");
}
/**
* Get localhost of the Session
*
* @return
*/
public InetAddress getLocalhost() {
return localhost;
}
/**
* Get the Host A IP
*
* @return
*/
public InetAddress getHostA() {
return hostA;
}
/**
* Get the Host B IP
*
* @return
*/
public InetAddress getHostB() {
return hostB;
}
/**
* Set port A value
*
* @param portA
*/
public void setPortA(int portA) {
System.out.println("PORT CHANGED(A):" + portA);
this.portA = portA;
}
/**
* Set port B value
*
* @param portB
*/
public void setPortB(int portB) {
System.out.println("PORT CHANGED(B):" + portB);
this.portB = portB;
}
/**
* Set the Host A IP
*
* @param hostA
*/
public void setHostA(InetAddress hostA) {
this.hostA = hostA;
}
/**
* Set the Host B IP
*
* @param hostB
*/
public void setHostB(InetAddress hostB) {
this.hostB = hostB;
}
/**
* Get the Port A IP
*
* @return
*/
public int getPortA() {
return portA;
}
/**
* Get the Port B IP
*
* @return
*/
public int getPortB() {
return portB;
}
/**
* Get the localport that listen for Host A Packets
*
* @return
*/
public int getLocalPortA() {
return localPortA;
}
/**
* Get the localport that listen for Host B Packets
*
* @return
*/
public int getLocalPortB() {
return localPortB;
}
public void sendFromPortA(String host, int port) {
try {
InetAddress address = InetAddress.getByName(host);
channelAtoB.setHost(address);
channelAtoB.setPort(port);
channelAtoBControl.setHost(address);
channelAtoBControl.setPort(port + 1);
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendFromPortB(String host, int port) {
try {
InetAddress address = InetAddress.getByName(host);
channelBtoA.setHost(address);
channelBtoA.setPort(port);
channelBtoAControl.setHost(address);
channelBtoAControl.setPort(port + 1);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Implement DatagramListener to timestamp last packet arrived
*
* @param datagramPacket
*/
public boolean datagramReceived(DatagramPacket datagramPacket) {
timestamp = new GregorianCalendar().getTimeInMillis();
return true;
}
/**
* Add a keep alive detector.
* If the packet still more than the keep alive delay without receiving any packets. The Session is stoped and remove from agents List.
*
* @param delay delay time in millis to check if the channel is inactive
*/
void addKeepAlive(long delay) {
if (keepAliveTimer != null) return;
keepAliveTimer = new Timer();
keepAliveTimer.scheduleAtFixedRate(new TimerTask() {
long lastTimeStamp = getTimestamp();
public void run() {
if (lastTimeStamp == getTimestamp()) {
stopAgent();
return;
}
lastTimeStamp = getTimestamp();
}
}, delay, delay);
}
/**
* Adds a listener for Session events
*
* @param sessionListener
*/
public void addAgentListener(SessionListener sessionListener) {
sessionListeners.add(sessionListener);
}
/**
* Removes an Session events listener
*
* @param sessionListener
*/
public void removeAgentListener(SessionListener sessionListener) {
sessionListeners.remove(sessionListener);
}
/**
* Removes every Session events listeners
*
*/
public void clearAgentListeners() {
sessionListeners.clear();
}
/**
* Dispatch Stop Event
*/
public void dispatchAgentStopped() {
for (SessionListener sessionListener : sessionListeners)
try {
sessionListener.agentStopped(this);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Protected Class Channel.
* Listen packets from defined dataSocket and send packets to the defined host.
*/
protected class Channel implements Runnable {
protected byte[] buf = new byte[5000];
protected DatagramSocket dataSocket;
protected DatagramPacket packet;
List<DatagramListener> listeners = new ArrayList<DatagramListener>();
protected InetAddress host;
protected int port;
/**
* Creates a Channel according to the parameters.
*
* @param dataSocket
* @param host
* @param port
*/
public Channel(DatagramSocket dataSocket, InetAddress host, int port) {
this.dataSocket = dataSocket;
this.host = host;
this.port = port;
}
/**
* Get the host that the packet will be sent to.
*
* @return remote host address
*/
public InetAddress getHost() {
return host;
}
/**
* Set the host that the packet will be sent to.
*/
protected void setHost(InetAddress host) {
this.host = host;
}
/**
* Get the port that the packet will be sent to.
*
* @return The remote port number
*/
public int getPort() {
return port;
}
/**
* Set the port that the packet will be sent to.
*
* @param port
*/
protected void setPort(int port) {
this.port = port;
}
/**
* Adds a DatagramListener to the Channel
*
* @param datagramListener
*/
public void addListener(DatagramListener datagramListener) {
listeners.add(datagramListener);
}
/**
* Remove a DatagramListener from the Channel
*
* @param datagramListener
*/
public void removeListener(DatagramListener datagramListener) {
listeners.remove(datagramListener);
}
/**
* Remove every Listeners
*/
public void removeListener() {
listeners.removeAll(listeners);
}
/**
* Thread override method
*/
public void run() {
try {
long c = 0;
while (true) {
// Block until a datagram appears:
packet = new DatagramPacket(buf, buf.length);
dataSocket.receive(packet);
if (this.getPort() != packet.getPort())
System.out.println(dataSocket.getLocalAddress().getHostAddress() + ":" + dataSocket.getLocalPort() + " relay to: " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
if (c++ < 5){
System.out.println("Received:" + dataSocket.getLocalAddress().getHostAddress() + ":" + dataSocket.getLocalPort());
System.out.println("Addr: "+packet.getAddress().getHostName());
}
boolean resend = true;
for (DatagramListener dl : listeners) {
boolean send = dl.datagramReceived(packet);
if (resend)
if (!send)
resend = false;
}
if (resend) relayPacket(packet);
}
} catch (UnknownHostException e) {
System.err.println("Unknown Host");
}
catch (SocketException e) {
System.err.println("Socket closed");
} catch (IOException e) {
System.err.println("Communication error");
e.printStackTrace();
}
}
public void relayPacket(DatagramPacket packet) {
try {
DatagramPacket echo = new DatagramPacket(packet.getData(), packet.getLength(),
host, port);
//System.out.println("Sent (" + packet.getAddress() + ":" + packet.getPort() + ") " + dataSocket.getLocalAddress() + ":" + dataSocket.getLocalPort() + " to " + host + ":" + port);
dataSocket.send(echo);
} catch (IOException e) {
System.err.println("Communication error");
e.printStackTrace();
}
}
}
public static void main(String args[]) {
try {
byte packet[] = {0, 0, 1, 1, 1, 1, 1};
DatagramSocket ds = new DatagramSocket(14004, InetAddress.getByName("0.0.0.0"));
DatagramPacket echo = new DatagramPacket(packet, packet.length,
InetAddress.getByName("10.1.1.3"), 16736);
for (int i = 0; i < 10; i++) {
System.out.print("\nSent");
ds.send(echo);
}
} catch (Exception e) {
System.out.print(e.toString());
}
}
}
package org.jivesoftware.wildfire.mediaproxy;
/**
* Listen for Session events
*/
public interface SessionListener {
public void agentStopped(Session session);
}
package org.jivesoftware.wildfire.mediaproxy;
import java.net.*;
import java.io.IOException;
/**
* A Session Class will control "receive and relay" proccess.
* It creates UDP channels from Host A to Host B and from Host B to Host A using or NOT the specified hosts and ports.
* The IP and port pairs can change depending of the Senders IP and port.
* Which means that the IP and port values of the points can dynamic change after the Channel is opened.
* When the agent receives a packet from Point A, the channel set the point A IP and port according to the received packet sender IP and port.
* Every packet received from Point B will be relayed to the new Point A IP and port.
* When the agent receives a packet from Point B, the channel set the point B IP and port according to the received packet sender IP and port.
* Every packet received from Point A will be relayed to the new Point B IP and port.
* Create a dynamic channel between two IPs. ( Dynamic Point A - Dynamic Point B )
* It has 4 Channels. 2 for data and 2 for control.
*/
public class SmartSession extends Session {
/**
* Creates a new Smart Session to provide connectivity between Host A and Host B.
*
* @param id of the Session (Could be a Jingle session ID)
* @param localhost The localhost IP that will listen for UDP packets
* @param hostA the hostname or IP of the point A of the Channel
* @param portA the port number point A of the Channel
* @param hostB the hostname or IP of the point B of the Channel
* @param portB the port number point B of the Channel
*/
public SmartSession(String id, String creator, String localhost, String hostA, int portA, String hostB, int portB, int minPort, int maxPort) {
super(id, creator, localhost, hostA, portA, hostB, portB, minPort, maxPort);
}
/**
* Creates a new Smart Session to provide connectivity between Host A and Host B.
*
* @param id of the Session (Could be a Jingle session ID)
* @param localhost The localhost IP that will listen for UDP packets
* @param hostA the hostname or IP of the point A of the Channel
* @param portA the port number point A of the Channel
* @param hostB the hostname or IP of the point B of the Channel
* @param portB the port number point B of the Channel
*/
public SmartSession(String id, String creator, String localhost, String hostA, int portA, String hostB, int portB) {
super(id, creator, localhost, hostA, portA, hostB, portB, 10000, 20000);
}
/**
* Thread override method
*/
public void run() {
channelAtoB = new SmartChannel(socketA, hostB, portB);
channelAtoBControl = new SmartChannel(socketAControl, hostB, portB + 1);
channelBtoA = new SmartChannel(socketB, hostA, portA);
channelBtoAControl = new SmartChannel(socketBControl, hostA, portA + 1);
channelAtoB.addListener((SmartChannel) channelBtoA);
channelAtoBControl.addListener((SmartChannel) channelBtoAControl);
channelBtoA.addListener((SmartChannel) channelAtoB);
channelBtoAControl.addListener((SmartChannel) channelAtoBControl);
threadAtoB = new Thread(channelAtoB);
threadAtoBControl = new Thread(channelAtoBControl);
threadBtoA = new Thread(channelBtoA);
threadBtoAControl = new Thread(channelBtoAControl);
threadAtoB.start();
threadAtoBControl.start();
threadBtoA.start();
threadBtoAControl.start();
channelAtoB.addListener(this);
channelAtoBControl.addListener(this);
channelBtoA.addListener(this);
channelBtoAControl.addListener(this);
}
/**
* Protected Class Channel.
* Listen packets from defined dataSocket and send packets to the defined host.
* But also provides a mechanism to dynamic bind host and port implementing DatagramListener methods to change the host and port values according to the received packets.
*/
protected class SmartChannel extends Channel implements Runnable, DatagramListener {
int c = 0;
/**
* Default Channel Constructor
*
* @param dataSocket
* @param host
* @param port
*/
public SmartChannel(DatagramSocket dataSocket, InetAddress host, int port) {
super(dataSocket, host, port);
}
/**
* Thread override method
*/
public void run() {
try {
long c = 0;
while (true) {
// Block until a datagram appears:
packet = new DatagramPacket(buf, buf.length);
dataSocket.receive(packet);
if (this.getPort() != packet.getPort())
System.out.println(dataSocket.getLocalAddress().getHostAddress() + ":" + dataSocket.getLocalPort() + " relay to: " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
if (c++ < 5){
System.out.println("Received:" + dataSocket.getLocalAddress().getHostAddress() + ":" + dataSocket.getLocalPort());
System.out.println("Addr: "+packet.getAddress().getHostName());
}
this.setHost(packet.getAddress());
this.setPort(packet.getPort());
boolean resend = true;
for (DatagramListener dl : listeners) {
boolean send = dl.datagramReceived(packet);
if (resend)
if (!send)
resend = false;
}
if (resend) relayPacket(packet);
}
} catch (UnknownHostException e) {
System.err.println("Unknown Host");
}
catch (SocketException e) {
System.err.println("Socket closed");
} catch (IOException e) {
System.err.println("Communication error");
e.printStackTrace();
}
}
/**
* Implement DatagramListener method.
* Set the host and port value to the host and port value from the received packet.
*
* @param datagramPacket
*/
public boolean datagramReceived(DatagramPacket datagramPacket) {
//InetAddress host = datagramPacket.getAddress();
//this.setHost(host);
//int port = datagramPacket.getPort();
//this.setPort(port);
this.relayPacket(datagramPacket);
return false;
}
}
}
......@@ -15,38 +15,38 @@
<!-- Server Settings -->
<item id="server-settings" name="${sidebar.server-settings}"
url="index.jsp"
description="${sidebar.server-settings.descr}" />
url="index.jsp"
description="${sidebar.server-settings.descr}"/>
<!-- System Properties -->
<item id="server-props" name="${sidebar.system-props}"
url="server-properties.jsp"
description="${sidebar.system-props.descr}" />
url="server-properties.jsp"
description="${sidebar.system-props.descr}"/>
<!-- System Locale -->
<item id="server-locale" name="${sidebar.server-locale}"
url="server-locale.jsp"
description="${sidebar.server-locale.descr}" />
url="server-locale.jsp"
description="${sidebar.server-locale.descr}"/>
<!-- System Cache -->
<item id="system-cache" name="${sidebar.system-cache}"
url="system-cache.jsp"
description="${sidebar.system-cache.descr}" />
url="system-cache.jsp"
description="${sidebar.system-cache.descr}"/>
<!-- Database -->
<item id="server-db" name="${sidebar.server-db}"
url="server-db.jsp"
description="${sidebar.server-db.descr}" />
url="server-db.jsp"
description="${sidebar.server-db.descr}"/>
<!-- Logs -->
<item id="server-logs" name="${sidebar.server-logs}"
url="logviewer.jsp"
description="${sidebar.server-logs.descr}" />
url="logviewer.jsp"
description="${sidebar.server-logs.descr}"/>
<!-- Email -->
<item id="system-email" name="${sidebar.server-email}"
url="system-email.jsp"
description="${sidebar.server-email.descr}" />
<item id="system-email" name="${sidebar.server-email}"
url="system-email.jsp"
description="${sidebar.server-email.descr}"/>
</sidebar>
<!-- Server Settings -->
......@@ -54,79 +54,95 @@
<!-- Profile Settings -->
<item id="profile-settings" name="${sidebar.profile-settings}"
url="profile-settings.jsp"
description="${sidebar.profile-settings.descr}" />
url="profile-settings.jsp"
description="${sidebar.profile-settings.descr}"/>
<!-- Server to server -->
<item id="server2server-settings" name="${sidebar.server2server-settings}"
url="server2server-settings.jsp"
description="${sidebar.server2server-settings.descr}" />
url="server2server-settings.jsp"
description="${sidebar.server2server-settings.descr}"/>
<!-- External components -->
<item id="external-components-settings" name="${sidebar.external-components-settings}"
url="external-components-settings.jsp"
description="${sidebar.external-components-settings.descr}" />
url="external-components-settings.jsp"
description="${sidebar.external-components-settings.descr}"/>
<!-- External components -->
<item id="connection-managers-settings" name="${sidebar.connection-managers-settings}"
url="connection-managers-settings.jsp"
description="${sidebar.connection-managers-settings.descr}" />
url="connection-managers-settings.jsp"
description="${sidebar.connection-managers-settings.descr}"/>
<!-- HTTP binding -->
<item id="http-bind" name="${sidebar.http-bind}"
url="http-bind.jsp"
description="${sidebar.http-bind.descr}" />
url="http-bind.jsp"
description="${sidebar.http-bind.descr}"/>
<!-- Manage updates -->
<item id="manage-updates" name="${sidebar.manage-updates}"
url="manage-updates.jsp"
description="${sidebar.manage-updates.descr}" />
url="manage-updates.jsp"
description="${sidebar.manage-updates.descr}"/>
<!-- Registration &amp; Login -->
<item id="server-reg-and-login" name="${sidebar.server-reg-and-login}"
url="reg-settings.jsp"
description="${sidebar.server-reg-and-login.descr}" />
url="reg-settings.jsp"
description="${sidebar.server-reg-and-login.descr}"/>
<!-- Resource Policy -->
<item id="server-session-conflict" name="${sidebar.server-session-conflict}"
url="session-conflict.jsp"
description="${sidebar.server-session-conflict.descr}" />
url="session-conflict.jsp"
description="${sidebar.server-session-conflict.descr}"/>
<!-- Offline Messages -->
<item id="server-offline-messages" name="${sidebar.server-offline-messages}"
url="offline-messages.jsp"
description="${sidebar.server-offline-messages.descr}" />
url="offline-messages.jsp"
description="${sidebar.server-offline-messages.descr}"/>
<!-- Message Audit Policy -->
<item id="server-audit-policy" name="${sidebar.server-audit-policy}"
url="audit-policy.jsp"
description="${sidebar.server-audit-policy.descr}" />
url="audit-policy.jsp"
description="${sidebar.server-audit-policy.descr}"/>
<!-- Private Data Storage -->
<item id="server-data-settings" name="${sidebar.server-data-settings}"
url="private-data-settings.jsp"
description="${sidebar.server-data-settings.descr}" />
url="private-data-settings.jsp"
description="${sidebar.server-data-settings.descr}"/>
<!-- SSL Settings -->
<item id="server-ssl" name="${sidebar.server-ssl}"
url="ssl-settings.jsp"
description="${sidebar.server-ssl.descr}" />
url="ssl-settings.jsp"
description="${sidebar.server-ssl.descr}"/>
<!-- SSL Certificates -->
<item id="ssl-certificates" name="${sidebar.ssl-certificates}"
url="ssl-certificates.jsp"
description="${sidebar.ssl-certificates.descr}" />
url="ssl-certificates.jsp"
description="${sidebar.ssl-certificates.descr}"/>
<!-- Compression Settings -->
<item id="server-compression" name="${sidebar.server-compression}"
url="compression-settings.jsp"
description="${sidebar.server-compression.descr}" />
url="compression-settings.jsp"
description="${sidebar.server-compression.descr}"/>
<!-- File Transfer Settings -->
<item id="server-transfer-proxy" name="${sidebar.transfer-proxy}"
url="file-transfer-proxy.jsp"
description="${sidebar.transfer-proxy.descr}"/>
url="file-transfer-proxy.jsp"
description="${sidebar.transfer-proxy.descr}"/>
</sidebar>
<!-- Server Settings -->
<sidebar id="sidebar-media-services" name="Media Services">
<!-- Media Proxy Settings -->
<item id="media-proxy-service" name="Media Proxy Settings"
url="media-proxy-properties.jsp"
description="Media Proxy Settings"/>
<!-- Media Proxy Session Summary -->
<item id="media-proxy-session-summary" name="Media Proxy Sessions"
url="media-proxy-session-summary.jsp"
description="Media Proxy Session Summary"/>
</sidebar>
</tab>
<!-- Users/Groups -->
......@@ -137,38 +153,38 @@
<!-- User Summary -->
<item id="user-summary" name="${sidebar.user-summary}"
url="user-summary.jsp"
description="${sidebar.user-summary.descr}">
url="user-summary.jsp"
description="${sidebar.user-summary.descr}">
<!-- User Options -->
<sidebar id="sidebar-users-options" name="${sidebar.sidebar-users-options}">
<!-- User Properties -->
<item id="user-properties" name="${sidebar.user-properties}"
url="user-properties.jsp"
description="${sidebar.user-properties.descr}" />
url="user-properties.jsp"
description="${sidebar.user-properties.descr}"/>
<!-- Password -->
<item id="user-password" name="${sidebar.user-password}"
url="user-password.jsp"
description="${sidebar.user-password.descr}" />
url="user-password.jsp"
description="${sidebar.user-password.descr}"/>
<!-- Delete User -->
<item id="user-delete" name="${sidebar.user-delete}"
url="user-delete.jsp"
description="${sidebar.user-delete.descr}" />
url="user-delete.jsp"
description="${sidebar.user-delete.descr}"/>
</sidebar>
</item>
<!-- Create New User -->
<item id="user-create" name="${sidebar.user-create}"
url="user-create.jsp"
description="${sidebar.user-create.descr}" />
url="user-create.jsp"
description="${sidebar.user-create.descr}"/>
<!-- User Search -->
<item id="user-search" name="${sidebar.user-search}"
url="user-search.jsp"
description="${sidebar.user-search.descr}" />
url="user-search.jsp"
description="${sidebar.user-search.descr}"/>
</sidebar>
<!-- Groups -->
......@@ -176,28 +192,28 @@
<!-- Group Summary -->
<item id="group-summary" name="${sidebar.group-summary}"
url="group-summary.jsp"
description="${sidebar.group-summary.descr}">
url="group-summary.jsp"
description="${sidebar.group-summary.descr}">
<!-- Group Options -->
<sidebar id="sidebar-group-options" name="${sidebar.sidebar-group-options}">
<!-- Edit Group -->
<item id="group-edit" name="${sidebar.group-edit}"
url="group-edit.jsp"
description="${sidebar.group-edit.descr}" />
url="group-edit.jsp"
description="${sidebar.group-edit.descr}"/>
<!-- Delete Group -->
<item id="group-delete" name="${sidebar.group-delete}"
url="group-delete.jsp"
description="${sidebar.group-delete.descr}" />
url="group-delete.jsp"
description="${sidebar.group-delete.descr}"/>
</sidebar>
</item>
<!-- Create New Group -->
<item id="group-create" name="${sidebar.group-create}"
url="group-create.jsp"
description="${sidebar.group-create.descr}" />
url="group-create.jsp"
description="${sidebar.group-create.descr}"/>
</sidebar>
</tab>
......@@ -208,92 +224,93 @@
<sidebar id="sidebar-session" name="${sidebar.active-sessions}">
<item id="session-summary" name="${sidebar.session-summary}"
url="session-summary.jsp"
description="${sidebar.session-summary.descr}" />
url="session-summary.jsp"
description="${sidebar.session-summary.descr}"/>
<item id="server-session-summary" name="${sidebar.server-session-summary}"
url="server-session-summary.jsp"
description="${sidebar.server-session-summary.descr}" />
url="server-session-summary.jsp"
description="${sidebar.server-session-summary.descr}"/>
<item id="component-session-summary" name="${sidebar.component-session-summary}"
url="component-session-summary.jsp"
description="${sidebar.component-session-summary.descr}" />
url="component-session-summary.jsp"
description="${sidebar.component-session-summary.descr}"/>
</sidebar>
<!-- Tools -->
<sidebar id="sidebar-tools" name="${sidebar.tools}">
<item id="user-message" name="${sidebar.user-message}"
url="user-message.jsp"
description="${sidebar.user-message.descr}" />
url="user-message.jsp"
description="${sidebar.user-message.descr}"/>
</sidebar>
</tab>
<!-- Group Chat -->
<tab id="tab-groupchat" name="${tab.tab-groupchat}" url="muc-server-props-edit-form.jsp" description="${tab.tab-groupchat.descr}">
<tab id="tab-groupchat" name="${tab.tab-groupchat}" url="muc-server-props-edit-form.jsp"
description="${tab.tab-groupchat.descr}">
<!-- Group Chat Settings -->
<sidebar id="sidebar-groupchat-settings" name="${sidebar.sidebar-groupchat-settings}">
<!-- Service Properties -->
<item id="muc-server-props" name="${sidebar.muc-server-props}"
url="muc-server-props-edit-form.jsp"
description="${sidebar.muc-server-props.descr}" />
url="muc-server-props-edit-form.jsp"
description="${sidebar.muc-server-props.descr}"/>
<!-- History Settings -->
<item id="muc-history" name="${sidebar.muc-history}"
url="muc-history-settings.jsp"
description="${sidebar.muc-history.descr}" />
url="muc-history-settings.jsp"
description="${sidebar.muc-history.descr}"/>
<!-- Administrators -->
<item id="muc-sysadmin" name="${sidebar.muc-sysadmin}"
url="muc-sysadmins.jsp"
description="${sidebar.muc-sysadmin.descr}" />
url="muc-sysadmins.jsp"
description="${sidebar.muc-sysadmin.descr}"/>
<!-- Room Creation Permissions -->
<item id="muc-perms" name="${sidebar.muc-perms}"
url="muc-create-permission.jsp"
description="${sidebar.muc-perms.descr}" />
url="muc-create-permission.jsp"
description="${sidebar.muc-perms.descr}"/>
<!-- Other Settings -->
<item id="muc-tasks" name="${sidebar.muc-tasks}"
url="muc-tasks.jsp"
description="${sidebar.muc-tasks.descr}" />
url="muc-tasks.jsp"
description="${sidebar.muc-tasks.descr}"/>
</sidebar>
<!-- Room Administration -->
<sidebar id="sidebar-groupchat-administration" name="${sidebar.sidebar-groupchat-administration}">
<!-- Room Summary -->
<item id="muc-room-summary" name="${sidebar.muc-room-summary}"
url="muc-room-summary.jsp"
description="${sidebar.muc-room-summary.descr}" >
<!-- Room Summary -->
<item id="muc-room-summary" name="${sidebar.muc-room-summary}"
url="muc-room-summary.jsp"
description="${sidebar.muc-room-summary.descr}">
<!-- Room Options -->
<sidebar id="sidebar-groupchat-options" name="${sidebar.sidebar-groupchat-options}">
<!-- Room Options -->
<sidebar id="sidebar-groupchat-options" name="${sidebar.sidebar-groupchat-options}">
<!-- Room Settings -->
<item id="muc-room-edit-form" name="${sidebar.muc-room-edit-form}"
url="muc-room-edit-form.jsp"
description="${sidebar.muc-room-edit-form.descr}" />
<!-- Room Settings -->
<item id="muc-room-edit-form" name="${sidebar.muc-room-edit-form}"
url="muc-room-edit-form.jsp"
description="${sidebar.muc-room-edit-form.descr}"/>
<!-- User Permissions -->
<item id="muc-room-affiliations" name="${sidebar.muc-room-affiliations}"
url="muc-room-affiliations.jsp"
description="${sidebar.muc-room-affiliations.descr}" />
<!-- User Permissions -->
<item id="muc-room-affiliations" name="${sidebar.muc-room-affiliations}"
url="muc-room-affiliations.jsp"
description="${sidebar.muc-room-affiliations.descr}"/>
<!-- Delete Room -->
<item id="muc-room-delete" name="${sidebar.muc-room-delete}"
url="muc-room-delete.jsp"
description="${sidebar.muc-room-delete.descr}" />
</sidebar>
</item>
<!-- Delete Room -->
<item id="muc-room-delete" name="${sidebar.muc-room-delete}"
url="muc-room-delete.jsp"
description="${sidebar.muc-room-delete.descr}"/>
</sidebar>
</item>
<!-- Create New Room -->
<item id="muc-room-create" name="${sidebar.muc-room-create}"
url="muc-room-create.jsp"
description="${sidebar.muc-room-create.descr}" />
<!-- Create New Room -->
<item id="muc-room-create" name="${sidebar.muc-room-create}"
url="muc-room-create.jsp"
description="${sidebar.muc-room-create.descr}"/>
</sidebar>
</tab>
......@@ -305,14 +322,14 @@
<sidebar id="sidebar-plugin-adamin" name="${sidebar.sidebar-plugin-admin}">
<!-- Plugins -->
<item id="plugin-settings" name="${sidebar.plugin-settings}"
url="plugin-admin.jsp"
description="${sidebar.plugin-settings.descr}" />
<item id="plugin-settings" name="${sidebar.plugin-settings}"
url="plugin-admin.jsp"
description="${sidebar.plugin-settings.descr}"/>
<!-- Available Plugins -->
<item id="available-plugins" name="${sidebar.available-plugins}"
url="available-plugins.jsp"
description="${sidebar.available-plugins.descr}" />
<item id="available-plugins" name="${sidebar.available-plugins}"
url="available-plugins.jsp"
description="${sidebar.available-plugins.descr}"/>
</sidebar>
</tab>
......
<%@ page import="org.jivesoftware.util.JiveGlobals" %>
<%@ page import="org.jivesoftware.util.ParamUtils" %>
<%@ page import="org.jivesoftware.wildfire.XMPPServer" %>
<%@ page import="org.jivesoftware.wildfire.mediaproxy.MediaProxyService" %>
<%
MediaProxyService mediaProxyService = XMPPServer.getInstance().getMediaProxyService();
boolean save = request.getParameter("set") != null;
boolean success = false;
long keepAliveDelay = 0;
int minPort = 10000;
int maxPort = 20000;
boolean enabled = false;
if (save) {
keepAliveDelay = ParamUtils.getLongParameter(request, "keepalivedelay", keepAliveDelay);
if (keepAliveDelay > 50) {
mediaProxyService.setKeepAliveDelay(keepAliveDelay);
JiveGlobals
.setProperty("plugin.rtpbridge.keepalivedelay", String.valueOf(keepAliveDelay));
}
minPort = ParamUtils.getIntParameter(request, "minport", minPort);
maxPort = ParamUtils.getIntParameter(request, "maxport", maxPort);
enabled = ParamUtils.getBooleanParameter(request, "enabled", enabled);
JiveGlobals.setProperty("plugin.rtpbridge.enabled", String.valueOf(enabled));
mediaProxyService.setEnabled(enabled);
if (minPort > 0 && maxPort > 0) {
if (maxPort - minPort > 1000) {
mediaProxyService.setMinPort(minPort);
mediaProxyService.setMaxPort(maxPort);
JiveGlobals.setProperty("plugin.rtpbridge.minport", String.valueOf(minPort));
JiveGlobals.setProperty("plugin.rtpbridge.maxport", String.valueOf(maxPort));
}
}
success = true;
}
%>
<html>
<head>
<title>Media Proxy Settings</title>
<meta name="pageID" content="media-proxy-service"/>
</head>
<body>
<p>
Use the form below to manage Media Proxy settings.<br>
</p>
<% if (success) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16"
border="0"></td>
<td class="jive-icon-label">Settings updated successfully.</td>
</tr>
</tbody>
</table>
</div>
<br>
<% } %>
<form action="media-proxy-properties.jsp" method="post">
<fieldset>
<legend>Media Proxy Settings</legend>
<div>
<p>
The settings will just take effects for new created agents.
</p>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody>
<tr>
<td align="left">Keep Alive Delay:&nbsp<input type="text" size="20"
maxlength="100"
name="keepalivedelay"
value="<%=mediaProxyService.getKeepAliveDelay()%>"
align="left">
</td>
</tr>
<tr>
<td align="left">Minimal Port Value:&nbsp<input type="text" size="20"
maxlength="100"
name="minport"
value="<%=mediaProxyService.getMinPort()%>"
align="left">
</td>
</tr>
<tr>
<td align="left">Maximum Port Value:&nbsp<input type="text" size="20"
maxlength="100"
name="maxport"
value="<%=mediaProxyService.getMaxPort()%>"
align="left">
</td>
</tr>
<tr>
<td align="left">Enabled:&nbsp<input type="checkbox"
name="enabled"
<%=mediaProxyService.isEnabled()?"checked":""%>
align="left">
</td>
</tr>
</tbody>
</table>
</div>
<input type="submit" name="set" value="Change">
</fieldset>
</form>
</body>
</html>
\ No newline at end of file
<%--
- $RCSfile$
- $Revision: 3710 $
- $Date: 2006-04-05 11:53:01 -0700 (Wed, 05 Apr 2006) $
-
- Copyright (C) 2004 Jive Software. All rights reserved.
-
- This software is published under the terms of the GNU Public License (GPL),
- a copy of which is included in this distribution.
--%>
<%--
This page summarize every active Session in the RTP Media Proxy
--%>
<%@ page import="java.util.GregorianCalendar,
java.util.List"
%>
<%@ page import="org.jivesoftware.wildfire.mediaproxy.MediaProxyService" %>
<%@ page import="org.jivesoftware.wildfire.XMPPServer" %>
<%@ page import="org.jivesoftware.wildfire.mediaproxy.Session" %>
<%@ page import="org.jivesoftware.wildfire.mediaproxy.SmartSession" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%
MediaProxyService mediaProxyService = XMPPServer.getInstance().getMediaProxyService();
boolean stop = request.getParameter("stop") != null;
if (stop) {
mediaProxyService.stopAgents();
}
%>
<html>
<head>
<title>Active Sessions Summary</title>
<meta name="pageID" content="media-proxy-session-summary"/>
</head>
<body>
<style type="text/css">
.jive-current {
font-weight: bold;
text-decoration: none;
}
</style>
<p>
Sessions are Media Proxy Channels that controls packet relaying.
The list below shows current sessions running and which user created the channel.
</p>
<div class="jive-table">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<thead>
<tr>
<th>&nbsp;</th>
<th nowrap align="left" valign="middle">Creator</th>
<th nowrap align="left" valign="middle">Port A</th>
<th nowrap align="left" valign="middle">Port B</th>
<th nowrap align="left" valign="middle">Server</th>
<th nowrap align="left" valign="middle">Inactivity(secs)</th>
<th nowrap align="left" valign="middle">Type</th>
</tr>
</thead>
<tbody>
<% // Print the list of agents
List<Session> agents = mediaProxyService.getAgents();
if (agents.isEmpty()) {
%>
<tr>
<td align="center" colspan="7">
No active Agents
</td>
</tr>
<%
}
int i = 0;
for (Session proxySession : agents) {
i++;
%>
<tr class="jive-<%= (((i%2)==0) ? "even" : "odd") %>">
<td width="1%">
<%= i %>
</td>
<td width="20%" align="left" valign="middle">
<%=proxySession.getCreator()%>
</td>
<td width="10%" align="left" valign="middle">
<%=proxySession.getLocalPortA()%>
</td>
<td width="10%" align="left" valign="middle">
<%=proxySession.getLocalPortB()%>
</td>
<td width="10%" align="left" valign="middle">
<%=proxySession.getLocalhost()%>
</td>
<td width="20%" align="left" valign="middle">
<%=(new GregorianCalendar().getTimeInMillis() - proxySession.getTimestamp()) / 1000%>
</td>
<td width="10%">
<% if (proxySession instanceof SmartSession) { %>
Smart Session
<% }
else { %>
Fixed Session
<% } %>
</td>
</tr>
<%
}
%>
</tbody>
</table>
<form action="">
<input type="submit" name="stop" value="Stop Active Sessions"/>
</form>
</div>
</body>
</html>
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