Commit b369394d authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Refactoring to use NIO for c2s.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@6576 b35dd754-fafc-0310-a699-88a17e54d16e
parent 8485752d
......@@ -509,9 +509,8 @@ public class SessionManager extends BasicModule {
*
* @param conn the connection to create the session from.
* @return a newly created session.
* @throws UnauthorizedException
*/
public ClientSession createClientSession(Connection conn) throws UnauthorizedException {
public ClientSession createClientSession(Connection conn) {
return createClientSession(conn, nextStreamID());
}
......@@ -523,10 +522,9 @@ public class SessionManager extends BasicModule {
* @return a newly created session.
* @throws UnauthorizedException
*/
public ClientSession createClientSession(Connection conn, StreamID id)
throws UnauthorizedException {
public ClientSession createClientSession(Connection conn, StreamID id) {
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
throw new IllegalStateException("Server not initialized");
}
ClientSession session = new ClientSession(serverName, conn, id);
conn.init(session);
......
......@@ -19,7 +19,6 @@ import org.jivesoftware.wildfire.Connection;
import org.jivesoftware.wildfire.SessionManager;
import org.jivesoftware.wildfire.StreamID;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.event.SessionEventDispatcher;
import org.jivesoftware.wildfire.event.SessionEventListener;
import org.jivesoftware.wildfire.session.ClientSession;
......@@ -128,7 +127,7 @@ public class ConnectionMultiplexerManager implements SessionEventListener {
* @param streamID the stream ID created by the connection manager for the new session.
*/
public void createClientSession(String connectionManagerDomain, String streamID) {
try {
// TODO Consider that client session may return null when IP address is forbidden
Connection connection = new ClientSessionConnection(connectionManagerDomain);
ClientSession session = SessionManager.getInstance()
.createClientSession(connection, new BasicStreamID(streamID));
......@@ -147,10 +146,6 @@ public class ConnectionMultiplexerManager implements SessionEventListener {
}
sessions.put(streamID, session);
}
catch (UnauthorizedException e) {
Log.error("Error creating virtual client session", e);
}
}
/**
* Closes an existing client session that was established through a connection manager.
......
......@@ -53,6 +53,10 @@ public abstract class StanzaHandler {
// Flag that indicates that the client requested to be authenticated. Once the
// authentication process is over the value will return to false.
private boolean startedSASL = false;
/**
* SASL status based on the last SASL interaction
*/
private SASLAuthentication.Status saslStatus;
// DANIELE: Indicate if a stream:stream is arrived to complete compression
private boolean waitingCompressionACK = false;
......@@ -113,7 +117,7 @@ public abstract class StanzaHandler {
MXParser parser = (MXParser) factory.newPullParser();
parser.setInput(new StringReader(stanza));
createSession(parser);
} else if (startedSASL && session.getStatus() == Session.STATUS_AUTHENTICATED) {
} else if (startedSASL && saslStatus == SASLAuthentication.Status.authenticated) {
startedSASL = false;
saslSuccessful();
} else if (waitingCompressionACK) {
......@@ -151,8 +155,11 @@ public abstract class StanzaHandler {
} else if ("auth".equals(tag)) {
// User is trying to authenticate using SASL
startedSASL = true;
// Forward packet to the server
process(doc);
// Process authentication stanza
saslStatus = SASLAuthentication.handle(session, doc);
} else if (startedSASL && "response".equals(tag)) {
// User is responding to SASL challenge. Process response
saslStatus = SASLAuthentication.handle(session, doc);
} else if ("compress".equals(tag)) {
// Client is trying to initiate compression
if (compressClient(doc)) {
......
......@@ -13,8 +13,8 @@ package org.jivesoftware.wildfire.server;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.ConnectionManager;
import org.jivesoftware.wildfire.SessionManager;
import org.jivesoftware.wildfire.net.SocketAcceptThread;
import org.jivesoftware.wildfire.server.RemoteServerConfiguration.Permission;
import org.jivesoftware.wildfire.session.Session;
......@@ -283,15 +283,13 @@ public class RemoteServerManager {
* @return the remote port to connect for the specified remote server.
*/
public static int getPortForServer(String domain) {
int port = JiveGlobals.getIntProperty("xmpp.server.socket.remotePort",
SocketAcceptThread.DEFAULT_SERVER_PORT);
int port = JiveGlobals.getIntProperty("xmpp.server.socket.remotePort", ConnectionManager.DEFAULT_SERVER_PORT);
RemoteServerConfiguration config = getConfiguration(domain);
if (config != null) {
port = config.getRemotePort();
if (port == 0) {
port =
JiveGlobals.getIntProperty("xmpp.server.socket.remotePort",
SocketAcceptThread.DEFAULT_SERVER_PORT);
port = JiveGlobals
.getIntProperty("xmpp.server.socket.remotePort", ConnectionManager.DEFAULT_SERVER_PORT);
}
}
return port;
......
......@@ -11,7 +11,6 @@
package org.jivesoftware.wildfire.session;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
......@@ -35,8 +34,7 @@ import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import org.xmpp.packet.StreamError;
import java.io.IOException;
import java.io.Writer;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
......@@ -64,16 +62,6 @@ public class ClientSession extends Session {
private static Connection.TLSPolicy tlsPolicy;
private static Connection.CompressionPolicy compressionPolicy;
/**
* Milliseconds a connection has to be idle to be closed. Default is 30 minutes. Sending
* stanzas to the client is not considered as activity. We are only considering the connection
* active when the client sends some data or hearbeats (i.e. whitespaces) to the server.
* The reason for this is that sending data will fail if the connection is closed. And if
* the thread is blocked while sending data (because the socket is closed) then the clean up
* thread will close the socket anyway.
*/
private static long idleTimeout;
/**
* The authentication token for this session.
*/
......@@ -130,9 +118,16 @@ public class ClientSession extends Session {
policyName = JiveGlobals.getProperty("xmpp.client.compression.policy",
Connection.CompressionPolicy.optional.toString());
compressionPolicy = Connection.CompressionPolicy.valueOf(policyName);
}
// Set the default read idle timeout. If none was set then assume 30 minutes
idleTimeout = JiveGlobals.getIntProperty("xmpp.client.idle", 30 * 60 * 1000);
/**
* Returns the list of IP address that are allowed to connect to the server. If the list is
* empty then anyone is allowed to connect to the server.
*
* @return the list of IP address that are allowed to connect to the server.
*/
public static Map<String, String> getAllowedIPs() {
return allowedIPs;
}
/**
......@@ -141,16 +136,13 @@ public class ClientSession extends Session {
* and namespace were provided by the client.
*
* @param serverName the name of the server where the session is connecting to.
* @param reader the reader that is reading the provided XML through the connection.
* @param xpp the parser that is reading the provided XML through the connection.
* @param connection the connection with the client.
* @return a newly created session between the server and a client.
* @throws org.xmlpull.v1.XmlPullParserException if an error occurs while parsing incoming data.
*/
public static Session createSession(String serverName, XMPPPacketReader reader,
SocketConnection connection) throws XmlPullParserException, UnauthorizedException,
IOException
{
XmlPullParser xpp = reader.getXPPParser();
public static Session createSession(String serverName, XmlPullParser xpp, Connection connection)
throws XmlPullParserException {
boolean isFlashClient = xpp.getPrefix().equals("flash");
connection.setFlashClient(isFlashClient);
......@@ -169,9 +161,13 @@ public class ClientSession extends Session {
}
if (!allowedIPs.isEmpty()) {
boolean forbidAccess = false;
String hostAddress = "Unknown";
// The server is using a whitelist so check that the IP address of the client
// is authorized to connect to the server
if (!allowedIPs.containsKey(connection.getInetAddress().getHostAddress())) {
try {
hostAddress = connection.getInetAddress().getHostAddress();
if (!allowedIPs.containsKey(hostAddress)) {
byte[] address = connection.getInetAddress().getAddress();
String range1 = (address[0] & 0xff) + "." + (address[1] & 0xff) + "." +
(address[2] & 0xff) +
......@@ -180,10 +176,16 @@ public class ClientSession extends Session {
String range3 = (address[0] & 0xff) + ".*.*.*";
if (!allowedIPs.containsKey(range1) && !allowedIPs.containsKey(range2) &&
!allowedIPs.containsKey(range3)) {
forbidAccess = true;
}
}
} catch (UnknownHostException e) {
forbidAccess = true;
}
if (forbidAccess) {
// Client cannot connect from this IP address so end the stream and
// TCP connection
Log.debug("Closed connection to client attempting to connect from: " +
connection.getInetAddress().getHostAddress());
Log.debug("Closed connection to client attempting to connect from: " + hostAddress);
// Include the not-authorized error in the response
StreamError error = new StreamError(StreamError.Condition.not_authorized);
connection.deliverRawText(error.toXML());
......@@ -192,7 +194,6 @@ public class ClientSession extends Session {
return null;
}
}
}
// Default language is English ("en").
String language = "en";
......@@ -260,14 +261,9 @@ public class ClientSession extends Session {
// Indicate the compression policy to use for this connection
connection.setCompressionPolicy(compressionPolicy);
// Set the max number of milliseconds the connection may not receive data from the
// client before closing the connection
connection.setIdleTimeout(idleTimeout);
// Create a ClientSession for this user.
Session session = SessionManager.getInstance().createClientSession(connection);
Writer writer = connection.getWriter();
// Build the start packet response
StringBuilder sb = new StringBuilder(200);
sb.append("<?xml version='1.0' encoding='");
......@@ -291,17 +287,11 @@ public class ClientSession extends Session {
sb.append(majorVersion).append(".").append(minorVersion);
}
sb.append("\">");
writer.write(sb.toString());
connection.deliverRawText(sb.toString());
// If this is a "Jabber" connection, the session is now initialized and we can
// return to allow normal packet parsing.
if (majorVersion == 0) {
// If this is a flash client append a special caracter to the response.
if (isFlashClient) {
writer.write('\0');
}
writer.flush();
return session;
}
// Otherwise, this is at least XMPP 1.0 so we need to announce stream features.
......@@ -324,26 +314,10 @@ public class ClientSession extends Session {
}
sb.append("</stream:features>");
writer.write(sb.toString());
if (isFlashClient) {
writer.write('\0');
}
writer.flush();
connection.deliverRawText(sb.toString());
return session;
}
/**
* Returns the list of IP address that are allowed to connect to the server. If the list is
* empty then anyone is allowed to connect to the server.
*
* @return the list of IP address that are allowed to connect to the server.
*/
public static Map<String, String> getAllowedIPs() {
return allowedIPs;
}
/**
* Sets the list of IP address that are allowed to connect to the server. If the list is
* empty then anyone is allowed to connect to the server.
......@@ -456,35 +430,12 @@ public class ClientSession extends Session {
this.defaultList = defaultList;
}
/**
* Returns the number of milliseconds a connection has to be idle to be closed. Default is
* 30 minutes. Sending stanzas to the client is not considered as activity. We are only
* considering the connection active when the client sends some data or hearbeats
* (i.e. whitespaces) to the server.
*
* @return the number of milliseconds a connection has to be idle to be closed.
*/
public static long getIdleTimeout() {
return idleTimeout;
}
/**
* Sets the number of milliseconds a connection has to be idle to be closed. Default is
* 30 minutes. Sending stanzas to the client is not considered as activity. We are only
* considering the connection active when the client sends some data or hearbeats
* (i.e. whitespaces) to the server.
*
* @param timeout the number of milliseconds a connection has to be idle to be closed.
*/
public static void setIdleTimeout(long timeout) {
idleTimeout = timeout;
JiveGlobals.setProperty("xmpp.client.idle", Long.toString(idleTimeout));
}
/**
* Creates a session with an underlying connection and permission protection.
*
* @param connection The connection we are proxying
* @param serverName name of the server.
* @param connection The connection we are proxying.
* @param streamID unique identifier of this session.
*/
public ClientSession(String serverName, Connection connection, StreamID streamID) {
super(serverName, connection, streamID);
......@@ -720,11 +671,12 @@ public class ClientSession extends Session {
StringBuilder sb = new StringBuilder(200);
// Include Stream Compression Mechanism
if (conn.getCompressionPolicy() != Connection.CompressionPolicy.disabled &&
// TODO Fix stream compression when using MINA and then enable this code
/*if (conn.getCompressionPolicy() != Connection.CompressionPolicy.disabled &&
!conn.isCompressed()) {
sb.append(
"<compression xmlns=\"http://jabber.org/features/compress\"><method>zlib</method></compression>");
}
}*/
if (getAuthToken() == null) {
// Advertise that the server supports Non-SASL Authentication
......
......@@ -8,16 +8,14 @@
- a copy of which is included in this distribution.
--%>
<%@ page import="org.jivesoftware.util.*,
org.jivesoftware.admin.AdminPageBean,
java.util.*,
<%@ page import="org.jivesoftware.util.JiveGlobals,
org.jivesoftware.util.ParamUtils,
org.jivesoftware.wildfire.ConnectionManager,
org.jivesoftware.wildfire.XMPPServer,
java.net.InetAddress,
org.jivesoftware.util.JiveGlobals,
org.jivesoftware.wildfire.net.SSLSocketAcceptThread,
org.jivesoftware.wildfire.net.SocketAcceptThread,
org.jivesoftware.wildfire.ConnectionManager"
java.util.HashMap"
%>
<%@ page import="java.util.Map" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
......@@ -30,14 +28,14 @@
<%
// Get parameters
String serverName = ParamUtils.getParameter(request,"serverName");
int port = ParamUtils.getIntParameter(request,"port",-1);
int sslPort = ParamUtils.getIntParameter(request,"sslPort",-1);
int embeddedPort = ParamUtils.getIntParameter(request,"embeddedPort",-1);
int embeddedSecurePort = ParamUtils.getIntParameter(request,"embeddedSecurePort",-1);
boolean sslEnabled = ParamUtils.getBooleanParameter(request,"sslEnabled");
int componentPort = ParamUtils.getIntParameter(request,"componentPort",-1);
int serverPort = ParamUtils.getIntParameter(request,"serverPort",-1);
String serverName = ParamUtils.getParameter(request, "serverName");
int port = ParamUtils.getIntParameter(request, "port", -1);
int sslPort = ParamUtils.getIntParameter(request, "sslPort", -1);
int embeddedPort = ParamUtils.getIntParameter(request, "embeddedPort", -1);
int embeddedSecurePort = ParamUtils.getIntParameter(request, "embeddedSecurePort", -1);
boolean sslEnabled = ParamUtils.getBooleanParameter(request, "sslEnabled");
int componentPort = ParamUtils.getIntParameter(request, "componentPort", -1);
int serverPort = ParamUtils.getIntParameter(request, "serverPort", -1);
boolean save = request.getParameter("save") != null;
boolean defaults = request.getParameter("defaults") != null;
boolean cancel = request.getParameter("cancel") != null;
......@@ -49,10 +47,10 @@
if (defaults) {
serverName = InetAddress.getLocalHost().getHostName();
port = SocketAcceptThread.DEFAULT_PORT;
sslPort = SSLSocketAcceptThread.DEFAULT_PORT;
componentPort = SocketAcceptThread.DEFAULT_COMPONENT_PORT;
serverPort = SocketAcceptThread.DEFAULT_SERVER_PORT;
port = ConnectionManager.DEFAULT_PORT;
sslPort = ConnectionManager.DEFAULT_SSL_PORT;
componentPort = ConnectionManager.DEFAULT_COMPONENT_PORT;
serverPort = ConnectionManager.DEFAULT_SERVER_PORT;
embeddedPort = 9090;
embeddedSecurePort = 9091;
sslEnabled = true;
......@@ -64,40 +62,39 @@
Map<String, String> errors = new HashMap<String, String>();
if (save) {
if (serverName == null) {
errors.put("serverName","");
errors.put("serverName", "");
}
if (port < 1) {
errors.put("port","");
errors.put("port", "");
}
if (sslPort < 1 && sslEnabled) {
errors.put("sslPort","");
errors.put("sslPort", "");
}
if (componentPort < 1) {
errors.put("componentPort","");
errors.put("componentPort", "");
}
if (serverPort < 1) {
errors.put("serverPort","");
errors.put("serverPort", "");
}
if (XMPPServer.getInstance().isStandAlone()) {
if (embeddedPort < 1) {
errors.put("embeddedPort","");
errors.put("embeddedPort", "");
}
if (embeddedSecurePort < 1) {
errors.put("embeddedSecurePort","");
errors.put("embeddedSecurePort", "");
}
if (embeddedPort > 0 && embeddedSecurePort > 0) {
if (embeddedPort == embeddedSecurePort) {
errors.put("embeddedPortsEqual","");
errors.put("embeddedPortsEqual", "");
}
}
}
else {
} else {
embeddedPort = -1;
embeddedSecurePort = -1;
}
if (port > 0 && sslPort > 0) {
if (port == sslPort) {
errors.put("portsEqual","");
errors.put("portsEqual", "");
}
}
if (errors.size() == 0) {
......@@ -121,22 +118,26 @@
}
if (needRestart) {
response.sendRedirect("server-props.jsp?success=true&restart=true");
}
else {
} else {
response.sendRedirect("server-props.jsp?success=true");
}
return;
}
}
else {
} else {
serverName = server.getServerInfo().getName();
sslEnabled = connectionManager.isClientSSLListenerEnabled();
port = connectionManager.getClientListenerPort();
sslPort = connectionManager.getClientSSLListenerPort();
componentPort = connectionManager.getComponentListenerPort();
serverPort = connectionManager.getServerListenerPort();
try { embeddedPort = Integer.parseInt(JiveGlobals.getXMLProperty("adminConsole.port")); } catch (Exception ignored) {}
try { embeddedSecurePort = Integer.parseInt(JiveGlobals.getXMLProperty("adminConsole.securePort")); } catch (Exception ignored) {}
try {
embeddedPort = Integer.parseInt(JiveGlobals.getXMLProperty("adminConsole.port"));
} catch (Exception ignored) {
}
try {
embeddedSecurePort = Integer.parseInt(JiveGlobals.getXMLProperty("adminConsole.securePort"));
} catch (Exception ignored) {
}
}
%>
......@@ -216,7 +217,7 @@
<br>
<span class="jive-error-text">
<fmt:message key="server.props.valid_port" />
<a href="#" onclick="document.editform.serverPort.value='<%=SocketAcceptThread.DEFAULT_SERVER_PORT%>';"
<a href="#" onclick="document.editform.serverPort.value='<%=ConnectionManager.DEFAULT_SERVER_PORT%>';"
><fmt:message key="server.props.valid_port1" /></a>.
</span>
<% } %>
......@@ -233,7 +234,7 @@
<br>
<span class="jive-error-text">
<fmt:message key="server.props.valid_port" />
<a href="#" onclick="document.editform.componentPort.value='<%=SocketAcceptThread.DEFAULT_COMPONENT_PORT%>';"
<a href="#" onclick="document.editform.componentPort.value='<%=ConnectionManager.DEFAULT_COMPONENT_PORT%>';"
><fmt:message key="server.props.valid_port1" /></a>.
</span>
<% } %>
......@@ -250,7 +251,7 @@
<br>
<span class="jive-error-text">
<fmt:message key="server.props.valid_port" />
<a href="#" onclick="document.editform.port.value='<%=SocketAcceptThread.DEFAULT_PORT%>';"
<a href="#" onclick="document.editform.port.value='<%=ConnectionManager.DEFAULT_PORT%>';"
><fmt:message key="server.props.valid_port1" /></a>.
</span>
<% } else if (errors.containsKey("portsEqual")) { %>
......@@ -297,7 +298,7 @@
<br>
<span class="jive-error-text">
<fmt:message key="server.props.ssl_valid" />
<a href="#" onclick="document.editform.sslPort.value='<%=SSLSocketAcceptThread.DEFAULT_PORT%>';"
<a href="#" onclick="document.editform.sslPort.value='<%=ConnectionManager.DEFAULT_SSL_PORT%>';"
><fmt:message key="server.props.ssl_valid1" /></a>.
</span>
<% } %>
......
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