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 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();
}
This diff is collapsed.
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;
}
}
}
This diff is collapsed.
<%@ 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