You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by dl...@apache.org on 2010/05/10 10:58:54 UTC
svn commit: r942689 - in /mina/ftpserver/branches/1.0.x/core/src:
main/java/org/apache/ftpserver/impl/FtpIoSession.java
test/java/org/apache/ftpserver/clienttests/LoginTest.java
Author: dlat
Date: Mon May 10 08:58:54 2010
New Revision: 942689
URL: http://svn.apache.org/viewvc?rev=942689&view=rev
Log:
FTPSERVER-369 maxLogin is reached immediately. REIN command is not decreasing the login count.
Modified:
mina/ftpserver/branches/1.0.x/core/src/main/java/org/apache/ftpserver/impl/FtpIoSession.java
mina/ftpserver/branches/1.0.x/core/src/test/java/org/apache/ftpserver/clienttests/LoginTest.java
Modified: mina/ftpserver/branches/1.0.x/core/src/main/java/org/apache/ftpserver/impl/FtpIoSession.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/branches/1.0.x/core/src/main/java/org/apache/ftpserver/impl/FtpIoSession.java?rev=942689&r1=942688&r2=942689&view=diff
==============================================================================
--- mina/ftpserver/branches/1.0.x/core/src/main/java/org/apache/ftpserver/impl/FtpIoSession.java (original)
+++ mina/ftpserver/branches/1.0.x/core/src/main/java/org/apache/ftpserver/impl/FtpIoSession.java Mon May 10 08:58:54 2010
@@ -51,803 +51,829 @@ import org.apache.mina.core.session.IoSe
import org.apache.mina.core.write.WriteRequest;
import org.apache.mina.core.write.WriteRequestQueue;
import org.apache.mina.filter.ssl.SslFilter;
+import org.slf4j.LoggerFactory;
/**
* <strong>Internal class, do not use directly.</strong>
- *
+ *
* @author <a href="http://mina.apache.org">Apache MINA Project</a> *
*/
public class FtpIoSession implements IoSession {
- /**
- * Contains user name between USER and PASS commands
- */
- public static final String ATTRIBUTE_PREFIX = "org.apache.ftpserver.";
-
- private static final String ATTRIBUTE_USER_ARGUMENT = ATTRIBUTE_PREFIX
- + "user-argument";
-
- private static final String ATTRIBUTE_SESSION_ID = ATTRIBUTE_PREFIX
- + "session-id";
-
- private static final String ATTRIBUTE_USER = ATTRIBUTE_PREFIX + "user";
-
- private static final String ATTRIBUTE_LANGUAGE = ATTRIBUTE_PREFIX
- + "language";
-
- private static final String ATTRIBUTE_LOGIN_TIME = ATTRIBUTE_PREFIX
- + "login-time";
-
- private static final String ATTRIBUTE_DATA_CONNECTION = ATTRIBUTE_PREFIX
- + "data-connection";
-
- private static final String ATTRIBUTE_FILE_SYSTEM = ATTRIBUTE_PREFIX
- + "file-system";
-
- private static final String ATTRIBUTE_RENAME_FROM = ATTRIBUTE_PREFIX
- + "rename-from";
-
- private static final String ATTRIBUTE_FILE_OFFSET = ATTRIBUTE_PREFIX
- + "file-offset";
-
- private static final String ATTRIBUTE_DATA_TYPE = ATTRIBUTE_PREFIX
- + "data-type";
-
- private static final String ATTRIBUTE_STRUCTURE = ATTRIBUTE_PREFIX
- + "structure";
-
- private static final String ATTRIBUTE_FAILED_LOGINS = ATTRIBUTE_PREFIX
- + "failed-logins";
-
- private static final String ATTRIBUTE_LISTENER = ATTRIBUTE_PREFIX
- + "listener";
-
- private static final String ATTRIBUTE_MAX_IDLE_TIME = ATTRIBUTE_PREFIX
- + "max-idle-time";
-
- private static final String ATTRIBUTE_LAST_ACCESS_TIME = ATTRIBUTE_PREFIX
- + "last-access-time";
-
- private static final String ATTRIBUTE_CACHED_REMOTE_ADDRESS = ATTRIBUTE_PREFIX
- + "cached-remote-address";
-
- private IoSession wrappedSession;
-
- private FtpServerContext context;
-
- /**
- * Last reply that was sent to the client, if any.
- */
- private FtpReply lastReply = null;
-
- /* Begin wrapped IoSession methods */
-
- /**
- * @see IoSession#close()
- */
- public CloseFuture close() {
- return wrappedSession.close();
- }
-
- /**
- * @see IoSession#close(boolean)
- */
- public CloseFuture close(boolean immediately) {
- return wrappedSession.close(immediately);
- }
-
- /**
- * @see IoSession#containsAttribute(Object)
- */
- public boolean containsAttribute(Object key) {
- return wrappedSession.containsAttribute(key);
- }
-
- /**
- * @see IoSession#getAttachment()
- */
- @SuppressWarnings("deprecation")
- public Object getAttachment() {
- return wrappedSession.getAttachment();
- }
-
- /**
- * @see IoSession#getAttribute(Object)
- */
- public Object getAttribute(Object key) {
- return wrappedSession.getAttribute(key);
- }
-
- /**
- * @see IoSession#getAttribute(Object, Object)
- */
- public Object getAttribute(Object key, Object defaultValue) {
- return wrappedSession.getAttribute(key, defaultValue);
- }
-
- /**
- * @see IoSession#getAttributeKeys()
- */
- public Set<Object> getAttributeKeys() {
- return wrappedSession.getAttributeKeys();
- }
-
- /**
- * @see IoSession#getBothIdleCount()
- */
- public int getBothIdleCount() {
- return wrappedSession.getBothIdleCount();
- }
-
- /**
- * @see IoSession#getCloseFuture()
- */
- public CloseFuture getCloseFuture() {
- return wrappedSession.getCloseFuture();
- }
-
- /**
- * @see IoSession#getConfig()
- */
- public IoSessionConfig getConfig() {
- return wrappedSession.getConfig();
- }
-
- /**
- * @see IoSession#getCreationTime()
- */
- public long getCreationTime() {
- return wrappedSession.getCreationTime();
- }
-
- /**
- * @see IoSession#getFilterChain()
- */
- public IoFilterChain getFilterChain() {
- return wrappedSession.getFilterChain();
- }
-
- /**
- * @see IoSession#getHandler()
- */
- public IoHandler getHandler() {
- return wrappedSession.getHandler();
- }
-
- /**
- * @see IoSession#getId()
- */
- public long getId() {
- return wrappedSession.getId();
- }
-
- /**
- * @see IoSession#getIdleCount(IdleStatus)
- */
- public int getIdleCount(IdleStatus status) {
- return wrappedSession.getIdleCount(status);
- }
-
- /**
- * @see IoSession#getLastBothIdleTime()
- */
- public long getLastBothIdleTime() {
- return wrappedSession.getLastBothIdleTime();
- }
-
- /**
- * @see IoSession#getLastIdleTime(IdleStatus)
- */
- public long getLastIdleTime(IdleStatus status) {
- return wrappedSession.getLastIdleTime(status);
- }
-
- /**
- * @see IoSession#getLastIoTime()
- */
- public long getLastIoTime() {
- return wrappedSession.getLastIoTime();
- }
-
- /**
- * @see IoSession#getLastReadTime()
- */
- public long getLastReadTime() {
- return wrappedSession.getLastReadTime();
- }
-
- /**
- * @see IoSession#getLastReaderIdleTime()
- */
- public long getLastReaderIdleTime() {
- return wrappedSession.getLastReaderIdleTime();
- }
-
- /**
- * @see IoSession#getLastWriteTime()
- */
- public long getLastWriteTime() {
- return wrappedSession.getLastWriteTime();
- }
-
- /**
- * @see IoSession#getLastWriterIdleTime()
- */
- public long getLastWriterIdleTime() {
- return wrappedSession.getLastWriterIdleTime();
- }
-
- /**
- * @see IoSession#getLocalAddress()
- */
- public SocketAddress getLocalAddress() {
- return wrappedSession.getLocalAddress();
- }
-
- /**
- * @see IoSession#getReadBytes()
- */
- public long getReadBytes() {
- return wrappedSession.getReadBytes();
- }
-
- /**
- * @see IoSession#getReadBytesThroughput()
- */
- public double getReadBytesThroughput() {
- return wrappedSession.getReadBytesThroughput();
- }
-
- /**
- * @see IoSession#getReadMessages()
- */
- public long getReadMessages() {
- return wrappedSession.getReadMessages();
- }
-
- /**
- * @see IoSession#getReadMessagesThroughput()
- */
- public double getReadMessagesThroughput() {
- return wrappedSession.getReadMessagesThroughput();
- }
-
- /**
- * @see IoSession#getReaderIdleCount()
- */
- public int getReaderIdleCount() {
- return wrappedSession.getReaderIdleCount();
- }
-
- /**
- * @see IoSession#getRemoteAddress()
- */
- public SocketAddress getRemoteAddress() {
- // when closing a socket, the remote address might be reset to null
- // therefore, we attempt to keep a cached copy around
-
- SocketAddress address = wrappedSession.getRemoteAddress();
- if (address == null
- && containsAttribute(ATTRIBUTE_CACHED_REMOTE_ADDRESS)) {
- return (SocketAddress) getAttribute(ATTRIBUTE_CACHED_REMOTE_ADDRESS);
- } else {
- setAttribute(ATTRIBUTE_CACHED_REMOTE_ADDRESS, address);
- return address;
- }
- }
-
- /**
- * @see IoSession#getScheduledWriteBytes()
- */
- public long getScheduledWriteBytes() {
- return wrappedSession.getScheduledWriteBytes();
- }
-
- /**
- * @see IoSession#getScheduledWriteMessages()
- */
- public int getScheduledWriteMessages() {
- return wrappedSession.getScheduledWriteMessages();
- }
-
- /**
- * @see IoSession#getService()
- */
- public IoService getService() {
- return wrappedSession.getService();
- }
-
- /**
- * @see IoSession#getServiceAddress()
- */
- public SocketAddress getServiceAddress() {
- return wrappedSession.getServiceAddress();
- }
-
- /**
- * @see IoSession#getTransportMetadata()
- */
- public TransportMetadata getTransportMetadata() {
- return wrappedSession.getTransportMetadata();
- }
-
- /**
- * @see IoSession#getWriterIdleCount()
- */
- public int getWriterIdleCount() {
- return wrappedSession.getWriterIdleCount();
- }
-
- /**
- * @see IoSession#getWrittenBytes()
- */
- public long getWrittenBytes() {
- return wrappedSession.getWrittenBytes();
- }
-
- /**
- * @see IoSession#getWrittenBytesThroughput()
- */
- public double getWrittenBytesThroughput() {
- return wrappedSession.getWrittenBytesThroughput();
- }
-
- /**
- * @see IoSession#getWrittenMessages()
- */
- public long getWrittenMessages() {
- return wrappedSession.getWrittenMessages();
- }
-
- /**
- * @see IoSession#getWrittenMessagesThroughput()
- */
- public double getWrittenMessagesThroughput() {
- return wrappedSession.getWrittenMessagesThroughput();
- }
-
- /**
- * @see IoSession#isClosing()
- */
- public boolean isClosing() {
- return wrappedSession.isClosing();
- }
-
- /**
- * @see IoSession#isConnected()
- */
- public boolean isConnected() {
- return wrappedSession.isConnected();
- }
-
- /**
- * @see IoSession#isIdle(IdleStatus)
- */
- public boolean isIdle(IdleStatus status) {
- return wrappedSession.isIdle(status);
- }
-
- /**
- * @see IoSession#read()
- */
- public ReadFuture read() {
- return wrappedSession.read();
- }
-
- /**
- * @see IoSession#removeAttribute(Object)
- */
- public Object removeAttribute(Object key) {
- return wrappedSession.removeAttribute(key);
- }
-
- /**
- * @see IoSession#removeAttribute(Object, Object)
- */
- public boolean removeAttribute(Object key, Object value) {
- return wrappedSession.removeAttribute(key, value);
- }
-
- /**
- * @see IoSession#replaceAttribute(Object, Object, Object)
- */
- public boolean replaceAttribute(Object key, Object oldValue, Object newValue) {
- return wrappedSession.replaceAttribute(key, oldValue, newValue);
- }
-
- /**
- * @see IoSession#resumeRead()
- */
- public void resumeRead() {
- wrappedSession.resumeRead();
- }
-
- /**
- * @see IoSession#resumeWrite()
- */
- public void resumeWrite() {
- wrappedSession.resumeWrite();
- }
-
- /**
- * @see IoSession#setAttachment(Object)
- */
- @SuppressWarnings("deprecation")
- public Object setAttachment(Object attachment) {
- return wrappedSession.setAttachment(attachment);
- }
-
- /**
- * @see IoSession#setAttribute(Object)
- */
- public Object setAttribute(Object key) {
- return wrappedSession.setAttribute(key);
- }
-
- /**
- * @see IoSession#setAttribute(Object, Object)
- */
- public Object setAttribute(Object key, Object value) {
- return wrappedSession.setAttribute(key, value);
- }
-
- /**
- * @see IoSession#setAttributeIfAbsent(Object)
- */
- public Object setAttributeIfAbsent(Object key) {
- return wrappedSession.setAttributeIfAbsent(key);
- }
-
- /**
- * @see IoSession#setAttributeIfAbsent(Object, Object)
- */
- public Object setAttributeIfAbsent(Object key, Object value) {
- return wrappedSession.setAttributeIfAbsent(key, value);
- }
-
- /**
- * @see IoSession#suspendRead()
- */
- public void suspendRead() {
- wrappedSession.suspendRead();
- }
-
- /**
- * @see IoSession#suspendWrite()
- */
- public void suspendWrite() {
- wrappedSession.suspendWrite();
- }
-
- /**
- * @see IoSession#write(Object)
- */
- public WriteFuture write(Object message) {
- WriteFuture future = wrappedSession.write(message);
- this.lastReply = (FtpReply) message;
- return future;
- }
-
- /**
- * @see IoSession#write(Object, SocketAddress)
- */
- public WriteFuture write(Object message, SocketAddress destination) {
- WriteFuture future = wrappedSession.write(message, destination);
- this.lastReply = (FtpReply) message;
- return future;
- }
-
- /* End wrapped IoSession methods */
-
- public void resetState() {
- removeAttribute(ATTRIBUTE_RENAME_FROM);
- removeAttribute(ATTRIBUTE_FILE_OFFSET);
- }
-
- public synchronized ServerDataConnectionFactory getDataConnection() {
- if (containsAttribute(ATTRIBUTE_DATA_CONNECTION)) {
- return (ServerDataConnectionFactory) getAttribute(ATTRIBUTE_DATA_CONNECTION);
- } else {
- IODataConnectionFactory dataCon = new IODataConnectionFactory(
- context, this);
- dataCon
- .setServerControlAddress(((InetSocketAddress) getLocalAddress())
- .getAddress());
- setAttribute(ATTRIBUTE_DATA_CONNECTION, dataCon);
-
- return dataCon;
- }
- }
-
- public FileSystemView getFileSystemView() {
- return (FileSystemView) getAttribute(ATTRIBUTE_FILE_SYSTEM);
- }
-
- public User getUser() {
- return (User) getAttribute(ATTRIBUTE_USER);
- }
-
- /**
- * Is logged-in
- */
- public boolean isLoggedIn() {
- return containsAttribute(ATTRIBUTE_USER);
- }
-
- public Listener getListener() {
- return (Listener) getAttribute(ATTRIBUTE_LISTENER);
- }
-
- public void setListener(Listener listener) {
- setAttribute(ATTRIBUTE_LISTENER, listener);
- }
-
- public FtpSession getFtpletSession() {
- return new DefaultFtpSession(this);
- }
-
- public String getLanguage() {
- return (String) getAttribute(ATTRIBUTE_LANGUAGE);
- }
-
- public void setLanguage(String language) {
- setAttribute(ATTRIBUTE_LANGUAGE, language);
-
- }
-
- public String getUserArgument() {
- return (String) getAttribute(ATTRIBUTE_USER_ARGUMENT);
- }
-
- public void setUser(User user) {
- setAttribute(ATTRIBUTE_USER, user);
-
- }
-
- public void setUserArgument(String userArgument) {
- setAttribute(ATTRIBUTE_USER_ARGUMENT, userArgument);
-
- }
-
- public int getMaxIdleTime() {
- return (Integer) getAttribute(ATTRIBUTE_MAX_IDLE_TIME, 0);
- }
-
- public void setMaxIdleTime(int maxIdleTime) {
- setAttribute(ATTRIBUTE_MAX_IDLE_TIME, maxIdleTime);
-
- int listenerTimeout = getListener().getIdleTimeout();
-
- // the listener timeout should be the upper limit, unless set to unlimited
- // if the user limit is set to be unlimited, use the listener value is the threshold
- // (already used as the default for all sessions)
- // else, if the user limit is less than the listener idle time, use the user limit
- if(listenerTimeout <= 0 ||
- (maxIdleTime > 0 && maxIdleTime < listenerTimeout)) {
- wrappedSession.getConfig().setBothIdleTime(maxIdleTime);
- }
- }
-
- public synchronized void increaseFailedLogins() {
- int failedLogins = (Integer) getAttribute(ATTRIBUTE_FAILED_LOGINS, 0);
- failedLogins++;
- setAttribute(ATTRIBUTE_FAILED_LOGINS, failedLogins);
- }
-
- public int getFailedLogins() {
- return (Integer) getAttribute(ATTRIBUTE_FAILED_LOGINS, 0);
- }
-
- public void setLogin(FileSystemView fsview) {
- setAttribute(ATTRIBUTE_LOGIN_TIME, new Date());
- setAttribute(ATTRIBUTE_FILE_SYSTEM, fsview);
- }
-
- public void reinitialize() {
- removeAttribute(ATTRIBUTE_USER);
- removeAttribute(ATTRIBUTE_USER_ARGUMENT);
- removeAttribute(ATTRIBUTE_LOGIN_TIME);
- removeAttribute(ATTRIBUTE_FILE_SYSTEM);
- removeAttribute(ATTRIBUTE_RENAME_FROM);
- removeAttribute(ATTRIBUTE_FILE_OFFSET);
- }
-
- public void setFileOffset(long fileOffset) {
- setAttribute(ATTRIBUTE_FILE_OFFSET, fileOffset);
-
- }
-
- public void setRenameFrom(FtpFile renFr) {
- setAttribute(ATTRIBUTE_RENAME_FROM, renFr);
-
- }
-
- public FtpFile getRenameFrom() {
- return (FtpFile) getAttribute(ATTRIBUTE_RENAME_FROM);
- }
-
- public long getFileOffset() {
- return (Long) getAttribute(ATTRIBUTE_FILE_OFFSET, 0L);
- }
-
- public void setStructure(Structure structure) {
- setAttribute(ATTRIBUTE_STRUCTURE, structure);
- }
-
- public void setDataType(DataType dataType) {
- setAttribute(ATTRIBUTE_DATA_TYPE, dataType);
-
- }
-
- /**
- * @see FtpSession#getSessionId()
- */
- public UUID getSessionId() {
- synchronized (wrappedSession) {
- if(!wrappedSession.containsAttribute(ATTRIBUTE_SESSION_ID)) {
- wrappedSession.setAttribute(ATTRIBUTE_SESSION_ID, UUID.randomUUID());
- }
- return (UUID) wrappedSession.getAttribute(ATTRIBUTE_SESSION_ID);
- }
- }
-
- public FtpIoSession(IoSession wrappedSession, FtpServerContext context) {
- this.wrappedSession = wrappedSession;
- this.context = context;
- }
-
- public Structure getStructure() {
- return (Structure) getAttribute(ATTRIBUTE_STRUCTURE, Structure.FILE);
- }
-
- public DataType getDataType() {
- return (DataType) getAttribute(ATTRIBUTE_DATA_TYPE, DataType.ASCII);
- }
-
- public Date getLoginTime() {
- return (Date) getAttribute(ATTRIBUTE_LOGIN_TIME);
- }
-
- public Date getLastAccessTime() {
- return (Date) getAttribute(ATTRIBUTE_LAST_ACCESS_TIME);
- }
-
- public Certificate[] getClientCertificates() {
- if (getFilterChain().contains(SslFilter.class)) {
- SslFilter sslFilter = (SslFilter) getFilterChain().get(
- SslFilter.class);
-
- SSLSession sslSession = sslFilter.getSslSession(this);
-
- if (sslSession != null) {
- try {
- return sslSession.getPeerCertificates();
- } catch (SSLPeerUnverifiedException e) {
- // ignore, certificate will not be available to the session
- }
- }
-
- }
-
- // no certificates available
- return null;
-
- }
-
- public void updateLastAccessTime() {
- setAttribute(ATTRIBUTE_LAST_ACCESS_TIME, new Date());
-
- }
-
- /**
- * @see IoSession#getCurrentWriteMessage()
- */
- public Object getCurrentWriteMessage() {
- return wrappedSession.getCurrentWriteMessage();
- }
-
- /**
- * @see IoSession#getCurrentWriteRequest()
- */
- public WriteRequest getCurrentWriteRequest() {
- return wrappedSession.getCurrentWriteRequest();
- }
-
- /**
- * @see IoSession#isBothIdle()
- */
- public boolean isBothIdle() {
- return wrappedSession.isBothIdle();
- }
-
- /**
- * @see IoSession#isReaderIdle()
- */
- public boolean isReaderIdle() {
- return wrappedSession.isReaderIdle();
- }
-
- /**
- * @see IoSession#isWriterIdle()
- */
- public boolean isWriterIdle() {
- return wrappedSession.isWriterIdle();
- }
-
- /**
- * Indicates whether the control socket for this session is secure, that is,
- * running over SSL/TLS
- *
- * @return true if the control socket is secured
- */
- public boolean isSecure() {
- return getFilterChain().contains(SslFilter.class);
- }
-
- /**
- * Increase the number of bytes written on the data connection
- * @param increment The number of bytes written
- */
- public void increaseWrittenDataBytes(int increment) {
- if (wrappedSession instanceof AbstractIoSession) {
- ((AbstractIoSession) wrappedSession)
- .increaseScheduledWriteBytes(increment);
- ((AbstractIoSession) wrappedSession).increaseWrittenBytes(
- increment, System.currentTimeMillis());
- }
- }
-
- /**
- * Increase the number of bytes read on the data connection
- * @param increment The number of bytes written
- */
- public void increaseReadDataBytes(int increment) {
- if (wrappedSession instanceof AbstractIoSession) {
- ((AbstractIoSession) wrappedSession).increaseReadBytes(increment,
- System.currentTimeMillis());
- }
- }
-
- /**
- * Returns the last reply that was sent to the client.
- * @return the last reply that was sent to the client.
- */
- public FtpReply getLastReply() {
- return lastReply;
- }
-
- /**
- * @see IoSession#getWriteRequestQueue()
- */
- public WriteRequestQueue getWriteRequestQueue() {
- return wrappedSession.getWriteRequestQueue();
- }
-
- /**
- * @see IoSession#isReadSuspended()
- */
- public boolean isReadSuspended() {
- return wrappedSession.isReadSuspended();
- }
-
- /**
- * @see IoSession#isWriteSuspended()
- */
- public boolean isWriteSuspended() {
- return wrappedSession.isWriteSuspended();
- }
-
- /**
- * @see IoSession#setCurrentWriteRequest(WriteRequest)
- */
- public void setCurrentWriteRequest(WriteRequest currentWriteRequest) {
- wrappedSession.setCurrentWriteRequest(currentWriteRequest);
- }
-
- /**
- * @see IoSession#updateThroughput(long, boolean)
- */
- public void updateThroughput(long currentTime, boolean force) {
- wrappedSession.updateThroughput(currentTime, force);
- }
+ /**
+ * Contains user name between USER and PASS commands
+ */
+ public static final String ATTRIBUTE_PREFIX = "org.apache.ftpserver.";
+
+ private static final String ATTRIBUTE_USER_ARGUMENT = ATTRIBUTE_PREFIX
+ + "user-argument";
+
+ private static final String ATTRIBUTE_SESSION_ID = ATTRIBUTE_PREFIX
+ + "session-id";
+
+ private static final String ATTRIBUTE_USER = ATTRIBUTE_PREFIX + "user";
+
+ private static final String ATTRIBUTE_LANGUAGE = ATTRIBUTE_PREFIX
+ + "language";
+
+ private static final String ATTRIBUTE_LOGIN_TIME = ATTRIBUTE_PREFIX
+ + "login-time";
+
+ private static final String ATTRIBUTE_DATA_CONNECTION = ATTRIBUTE_PREFIX
+ + "data-connection";
+
+ private static final String ATTRIBUTE_FILE_SYSTEM = ATTRIBUTE_PREFIX
+ + "file-system";
+
+ private static final String ATTRIBUTE_RENAME_FROM = ATTRIBUTE_PREFIX
+ + "rename-from";
+
+ private static final String ATTRIBUTE_FILE_OFFSET = ATTRIBUTE_PREFIX
+ + "file-offset";
+
+ private static final String ATTRIBUTE_DATA_TYPE = ATTRIBUTE_PREFIX
+ + "data-type";
+
+ private static final String ATTRIBUTE_STRUCTURE = ATTRIBUTE_PREFIX
+ + "structure";
+
+ private static final String ATTRIBUTE_FAILED_LOGINS = ATTRIBUTE_PREFIX
+ + "failed-logins";
+
+ private static final String ATTRIBUTE_LISTENER = ATTRIBUTE_PREFIX
+ + "listener";
+
+ private static final String ATTRIBUTE_MAX_IDLE_TIME = ATTRIBUTE_PREFIX
+ + "max-idle-time";
+
+ private static final String ATTRIBUTE_LAST_ACCESS_TIME = ATTRIBUTE_PREFIX
+ + "last-access-time";
+
+ private static final String ATTRIBUTE_CACHED_REMOTE_ADDRESS = ATTRIBUTE_PREFIX
+ + "cached-remote-address";
+
+ private IoSession wrappedSession;
+
+ private FtpServerContext context;
+
+ /**
+ * Last reply that was sent to the client, if any.
+ */
+ private FtpReply lastReply = null;
+
+ /* Begin wrapped IoSession methods */
+
+ /**
+ * @see IoSession#close()
+ */
+ public CloseFuture close() {
+ return wrappedSession.close();
+ }
+
+ /**
+ * @see IoSession#close(boolean)
+ */
+ public CloseFuture close(boolean immediately) {
+ return wrappedSession.close(immediately);
+ }
+
+ /**
+ * @see IoSession#containsAttribute(Object)
+ */
+ public boolean containsAttribute(Object key) {
+ return wrappedSession.containsAttribute(key);
+ }
+
+ /**
+ * @see IoSession#getAttachment()
+ */
+ @SuppressWarnings("deprecation")
+ public Object getAttachment() {
+ return wrappedSession.getAttachment();
+ }
+
+ /**
+ * @see IoSession#getAttribute(Object)
+ */
+ public Object getAttribute(Object key) {
+ return wrappedSession.getAttribute(key);
+ }
+
+ /**
+ * @see IoSession#getAttribute(Object, Object)
+ */
+ public Object getAttribute(Object key, Object defaultValue) {
+ return wrappedSession.getAttribute(key, defaultValue);
+ }
+
+ /**
+ * @see IoSession#getAttributeKeys()
+ */
+ public Set<Object> getAttributeKeys() {
+ return wrappedSession.getAttributeKeys();
+ }
+
+ /**
+ * @see IoSession#getBothIdleCount()
+ */
+ public int getBothIdleCount() {
+ return wrappedSession.getBothIdleCount();
+ }
+
+ /**
+ * @see IoSession#getCloseFuture()
+ */
+ public CloseFuture getCloseFuture() {
+ return wrappedSession.getCloseFuture();
+ }
+
+ /**
+ * @see IoSession#getConfig()
+ */
+ public IoSessionConfig getConfig() {
+ return wrappedSession.getConfig();
+ }
+
+ /**
+ * @see IoSession#getCreationTime()
+ */
+ public long getCreationTime() {
+ return wrappedSession.getCreationTime();
+ }
+
+ /**
+ * @see IoSession#getFilterChain()
+ */
+ public IoFilterChain getFilterChain() {
+ return wrappedSession.getFilterChain();
+ }
+
+ /**
+ * @see IoSession#getHandler()
+ */
+ public IoHandler getHandler() {
+ return wrappedSession.getHandler();
+ }
+
+ /**
+ * @see IoSession#getId()
+ */
+ public long getId() {
+ return wrappedSession.getId();
+ }
+
+ /**
+ * @see IoSession#getIdleCount(IdleStatus)
+ */
+ public int getIdleCount(IdleStatus status) {
+ return wrappedSession.getIdleCount(status);
+ }
+
+ /**
+ * @see IoSession#getLastBothIdleTime()
+ */
+ public long getLastBothIdleTime() {
+ return wrappedSession.getLastBothIdleTime();
+ }
+
+ /**
+ * @see IoSession#getLastIdleTime(IdleStatus)
+ */
+ public long getLastIdleTime(IdleStatus status) {
+ return wrappedSession.getLastIdleTime(status);
+ }
+
+ /**
+ * @see IoSession#getLastIoTime()
+ */
+ public long getLastIoTime() {
+ return wrappedSession.getLastIoTime();
+ }
+
+ /**
+ * @see IoSession#getLastReadTime()
+ */
+ public long getLastReadTime() {
+ return wrappedSession.getLastReadTime();
+ }
+
+ /**
+ * @see IoSession#getLastReaderIdleTime()
+ */
+ public long getLastReaderIdleTime() {
+ return wrappedSession.getLastReaderIdleTime();
+ }
+
+ /**
+ * @see IoSession#getLastWriteTime()
+ */
+ public long getLastWriteTime() {
+ return wrappedSession.getLastWriteTime();
+ }
+
+ /**
+ * @see IoSession#getLastWriterIdleTime()
+ */
+ public long getLastWriterIdleTime() {
+ return wrappedSession.getLastWriterIdleTime();
+ }
+
+ /**
+ * @see IoSession#getLocalAddress()
+ */
+ public SocketAddress getLocalAddress() {
+ return wrappedSession.getLocalAddress();
+ }
+
+ /**
+ * @see IoSession#getReadBytes()
+ */
+ public long getReadBytes() {
+ return wrappedSession.getReadBytes();
+ }
+
+ /**
+ * @see IoSession#getReadBytesThroughput()
+ */
+ public double getReadBytesThroughput() {
+ return wrappedSession.getReadBytesThroughput();
+ }
+
+ /**
+ * @see IoSession#getReadMessages()
+ */
+ public long getReadMessages() {
+ return wrappedSession.getReadMessages();
+ }
+
+ /**
+ * @see IoSession#getReadMessagesThroughput()
+ */
+ public double getReadMessagesThroughput() {
+ return wrappedSession.getReadMessagesThroughput();
+ }
+
+ /**
+ * @see IoSession#getReaderIdleCount()
+ */
+ public int getReaderIdleCount() {
+ return wrappedSession.getReaderIdleCount();
+ }
+
+ /**
+ * @see IoSession#getRemoteAddress()
+ */
+ public SocketAddress getRemoteAddress() {
+ // when closing a socket, the remote address might be reset to null
+ // therefore, we attempt to keep a cached copy around
+
+ SocketAddress address = wrappedSession.getRemoteAddress();
+ if (address == null
+ && containsAttribute(ATTRIBUTE_CACHED_REMOTE_ADDRESS)) {
+ return (SocketAddress) getAttribute(ATTRIBUTE_CACHED_REMOTE_ADDRESS);
+ } else {
+ setAttribute(ATTRIBUTE_CACHED_REMOTE_ADDRESS, address);
+ return address;
+ }
+ }
+
+ /**
+ * @see IoSession#getScheduledWriteBytes()
+ */
+ public long getScheduledWriteBytes() {
+ return wrappedSession.getScheduledWriteBytes();
+ }
+
+ /**
+ * @see IoSession#getScheduledWriteMessages()
+ */
+ public int getScheduledWriteMessages() {
+ return wrappedSession.getScheduledWriteMessages();
+ }
+
+ /**
+ * @see IoSession#getService()
+ */
+ public IoService getService() {
+ return wrappedSession.getService();
+ }
+
+ /**
+ * @see IoSession#getServiceAddress()
+ */
+ public SocketAddress getServiceAddress() {
+ return wrappedSession.getServiceAddress();
+ }
+
+ /**
+ * @see IoSession#getTransportMetadata()
+ */
+ public TransportMetadata getTransportMetadata() {
+ return wrappedSession.getTransportMetadata();
+ }
+
+ /**
+ * @see IoSession#getWriterIdleCount()
+ */
+ public int getWriterIdleCount() {
+ return wrappedSession.getWriterIdleCount();
+ }
+
+ /**
+ * @see IoSession#getWrittenBytes()
+ */
+ public long getWrittenBytes() {
+ return wrappedSession.getWrittenBytes();
+ }
+
+ /**
+ * @see IoSession#getWrittenBytesThroughput()
+ */
+ public double getWrittenBytesThroughput() {
+ return wrappedSession.getWrittenBytesThroughput();
+ }
+
+ /**
+ * @see IoSession#getWrittenMessages()
+ */
+ public long getWrittenMessages() {
+ return wrappedSession.getWrittenMessages();
+ }
+
+ /**
+ * @see IoSession#getWrittenMessagesThroughput()
+ */
+ public double getWrittenMessagesThroughput() {
+ return wrappedSession.getWrittenMessagesThroughput();
+ }
+
+ /**
+ * @see IoSession#isClosing()
+ */
+ public boolean isClosing() {
+ return wrappedSession.isClosing();
+ }
+
+ /**
+ * @see IoSession#isConnected()
+ */
+ public boolean isConnected() {
+ return wrappedSession.isConnected();
+ }
+
+ /**
+ * @see IoSession#isIdle(IdleStatus)
+ */
+ public boolean isIdle(IdleStatus status) {
+ return wrappedSession.isIdle(status);
+ }
+
+ /**
+ * @see IoSession#read()
+ */
+ public ReadFuture read() {
+ return wrappedSession.read();
+ }
+
+ /**
+ * @see IoSession#removeAttribute(Object)
+ */
+ public Object removeAttribute(Object key) {
+ return wrappedSession.removeAttribute(key);
+ }
+
+ /**
+ * @see IoSession#removeAttribute(Object, Object)
+ */
+ public boolean removeAttribute(Object key, Object value) {
+ return wrappedSession.removeAttribute(key, value);
+ }
+
+ /**
+ * @see IoSession#replaceAttribute(Object, Object, Object)
+ */
+ public boolean replaceAttribute(Object key, Object oldValue, Object newValue) {
+ return wrappedSession.replaceAttribute(key, oldValue, newValue);
+ }
+
+ /**
+ * @see IoSession#resumeRead()
+ */
+ public void resumeRead() {
+ wrappedSession.resumeRead();
+ }
+
+ /**
+ * @see IoSession#resumeWrite()
+ */
+ public void resumeWrite() {
+ wrappedSession.resumeWrite();
+ }
+
+ /**
+ * @see IoSession#setAttachment(Object)
+ */
+ @SuppressWarnings("deprecation")
+ public Object setAttachment(Object attachment) {
+ return wrappedSession.setAttachment(attachment);
+ }
+
+ /**
+ * @see IoSession#setAttribute(Object)
+ */
+ public Object setAttribute(Object key) {
+ return wrappedSession.setAttribute(key);
+ }
+
+ /**
+ * @see IoSession#setAttribute(Object, Object)
+ */
+ public Object setAttribute(Object key, Object value) {
+ return wrappedSession.setAttribute(key, value);
+ }
+
+ /**
+ * @see IoSession#setAttributeIfAbsent(Object)
+ */
+ public Object setAttributeIfAbsent(Object key) {
+ return wrappedSession.setAttributeIfAbsent(key);
+ }
+
+ /**
+ * @see IoSession#setAttributeIfAbsent(Object, Object)
+ */
+ public Object setAttributeIfAbsent(Object key, Object value) {
+ return wrappedSession.setAttributeIfAbsent(key, value);
+ }
+
+ /**
+ * @see IoSession#suspendRead()
+ */
+ public void suspendRead() {
+ wrappedSession.suspendRead();
+ }
+
+ /**
+ * @see IoSession#suspendWrite()
+ */
+ public void suspendWrite() {
+ wrappedSession.suspendWrite();
+ }
+
+ /**
+ * @see IoSession#write(Object)
+ */
+ public WriteFuture write(Object message) {
+ WriteFuture future = wrappedSession.write(message);
+ this.lastReply = (FtpReply) message;
+ return future;
+ }
+
+ /**
+ * @see IoSession#write(Object, SocketAddress)
+ */
+ public WriteFuture write(Object message, SocketAddress destination) {
+ WriteFuture future = wrappedSession.write(message, destination);
+ this.lastReply = (FtpReply) message;
+ return future;
+ }
+
+ /* End wrapped IoSession methods */
+
+ public void resetState() {
+ removeAttribute(ATTRIBUTE_RENAME_FROM);
+ removeAttribute(ATTRIBUTE_FILE_OFFSET);
+ }
+
+ public synchronized ServerDataConnectionFactory getDataConnection() {
+ if (containsAttribute(ATTRIBUTE_DATA_CONNECTION)) {
+ return (ServerDataConnectionFactory) getAttribute(ATTRIBUTE_DATA_CONNECTION);
+ } else {
+ IODataConnectionFactory dataCon = new IODataConnectionFactory(
+ context, this);
+ dataCon
+ .setServerControlAddress(((InetSocketAddress) getLocalAddress())
+ .getAddress());
+ setAttribute(ATTRIBUTE_DATA_CONNECTION, dataCon);
+
+ return dataCon;
+ }
+ }
+
+ public FileSystemView getFileSystemView() {
+ return (FileSystemView) getAttribute(ATTRIBUTE_FILE_SYSTEM);
+ }
+
+ public User getUser() {
+ return (User) getAttribute(ATTRIBUTE_USER);
+ }
+
+ /**
+ * Is logged-in
+ */
+ public boolean isLoggedIn() {
+ return containsAttribute(ATTRIBUTE_USER);
+ }
+
+ public Listener getListener() {
+ return (Listener) getAttribute(ATTRIBUTE_LISTENER);
+ }
+
+ public void setListener(Listener listener) {
+ setAttribute(ATTRIBUTE_LISTENER, listener);
+ }
+
+ public FtpSession getFtpletSession() {
+ return new DefaultFtpSession(this);
+ }
+
+ public String getLanguage() {
+ return (String) getAttribute(ATTRIBUTE_LANGUAGE);
+ }
+
+ public void setLanguage(String language) {
+ setAttribute(ATTRIBUTE_LANGUAGE, language);
+
+ }
+
+ public String getUserArgument() {
+ return (String) getAttribute(ATTRIBUTE_USER_ARGUMENT);
+ }
+
+ public void setUser(User user) {
+ setAttribute(ATTRIBUTE_USER, user);
+
+ }
+
+ public void setUserArgument(String userArgument) {
+ setAttribute(ATTRIBUTE_USER_ARGUMENT, userArgument);
+
+ }
+
+ public int getMaxIdleTime() {
+ return (Integer) getAttribute(ATTRIBUTE_MAX_IDLE_TIME, 0);
+ }
+
+ public void setMaxIdleTime(int maxIdleTime) {
+ setAttribute(ATTRIBUTE_MAX_IDLE_TIME, maxIdleTime);
+
+ int listenerTimeout = getListener().getIdleTimeout();
+
+ // the listener timeout should be the upper limit, unless set to
+ // unlimited
+ // if the user limit is set to be unlimited, use the listener value is
+ // the threshold
+ // (already used as the default for all sessions)
+ // else, if the user limit is less than the listener idle time, use the
+ // user limit
+ if (listenerTimeout <= 0
+ || (maxIdleTime > 0 && maxIdleTime < listenerTimeout)) {
+ wrappedSession.getConfig().setBothIdleTime(maxIdleTime);
+ }
+ }
+
+ public synchronized void increaseFailedLogins() {
+ int failedLogins = (Integer) getAttribute(ATTRIBUTE_FAILED_LOGINS, 0);
+ failedLogins++;
+ setAttribute(ATTRIBUTE_FAILED_LOGINS, failedLogins);
+ }
+
+ public int getFailedLogins() {
+ return (Integer) getAttribute(ATTRIBUTE_FAILED_LOGINS, 0);
+ }
+
+ public void setLogin(FileSystemView fsview) {
+ setAttribute(ATTRIBUTE_LOGIN_TIME, new Date());
+ setAttribute(ATTRIBUTE_FILE_SYSTEM, fsview);
+ }
+
+ public void reinitialize() {
+ logoutUser();
+ removeAttribute(ATTRIBUTE_USER);
+ removeAttribute(ATTRIBUTE_USER_ARGUMENT);
+ removeAttribute(ATTRIBUTE_LOGIN_TIME);
+ removeAttribute(ATTRIBUTE_FILE_SYSTEM);
+ removeAttribute(ATTRIBUTE_RENAME_FROM);
+ removeAttribute(ATTRIBUTE_FILE_OFFSET);
+ }
+
+ public void logoutUser() {
+ ServerFtpStatistics stats = ((ServerFtpStatistics) context
+ .getFtpStatistics());
+ if (stats != null) {
+ stats.setLogout(this);
+ LoggerFactory.getLogger(this.getClass()).debug(
+ "Statistics login decreased due to user logout");
+ } else {
+ LoggerFactory
+ .getLogger(this.getClass())
+ .warn(
+ "Statistics not available in session, can not decrease login count");
+ }
+ }
+
+ public void setFileOffset(long fileOffset) {
+ setAttribute(ATTRIBUTE_FILE_OFFSET, fileOffset);
+
+ }
+
+ public void setRenameFrom(FtpFile renFr) {
+ setAttribute(ATTRIBUTE_RENAME_FROM, renFr);
+
+ }
+
+ public FtpFile getRenameFrom() {
+ return (FtpFile) getAttribute(ATTRIBUTE_RENAME_FROM);
+ }
+
+ public long getFileOffset() {
+ return (Long) getAttribute(ATTRIBUTE_FILE_OFFSET, 0L);
+ }
+
+ public void setStructure(Structure structure) {
+ setAttribute(ATTRIBUTE_STRUCTURE, structure);
+ }
+
+ public void setDataType(DataType dataType) {
+ setAttribute(ATTRIBUTE_DATA_TYPE, dataType);
+
+ }
+
+ /**
+ * @see FtpSession#getSessionId()
+ */
+ public UUID getSessionId() {
+ synchronized (wrappedSession) {
+ if (!wrappedSession.containsAttribute(ATTRIBUTE_SESSION_ID)) {
+ wrappedSession.setAttribute(ATTRIBUTE_SESSION_ID, UUID
+ .randomUUID());
+ }
+ return (UUID) wrappedSession.getAttribute(ATTRIBUTE_SESSION_ID);
+ }
+ }
+
+ public FtpIoSession(IoSession wrappedSession, FtpServerContext context) {
+ this.wrappedSession = wrappedSession;
+ this.context = context;
+ }
+
+ public Structure getStructure() {
+ return (Structure) getAttribute(ATTRIBUTE_STRUCTURE, Structure.FILE);
+ }
+
+ public DataType getDataType() {
+ return (DataType) getAttribute(ATTRIBUTE_DATA_TYPE, DataType.ASCII);
+ }
+
+ public Date getLoginTime() {
+ return (Date) getAttribute(ATTRIBUTE_LOGIN_TIME);
+ }
+
+ public Date getLastAccessTime() {
+ return (Date) getAttribute(ATTRIBUTE_LAST_ACCESS_TIME);
+ }
+
+ public Certificate[] getClientCertificates() {
+ if (getFilterChain().contains(SslFilter.class)) {
+ SslFilter sslFilter = (SslFilter) getFilterChain().get(
+ SslFilter.class);
+
+ SSLSession sslSession = sslFilter.getSslSession(this);
+
+ if (sslSession != null) {
+ try {
+ return sslSession.getPeerCertificates();
+ } catch (SSLPeerUnverifiedException e) {
+ // ignore, certificate will not be available to the session
+ }
+ }
+
+ }
+
+ // no certificates available
+ return null;
+
+ }
+
+ public void updateLastAccessTime() {
+ setAttribute(ATTRIBUTE_LAST_ACCESS_TIME, new Date());
+
+ }
+
+ /**
+ * @see IoSession#getCurrentWriteMessage()
+ */
+ public Object getCurrentWriteMessage() {
+ return wrappedSession.getCurrentWriteMessage();
+ }
+
+ /**
+ * @see IoSession#getCurrentWriteRequest()
+ */
+ public WriteRequest getCurrentWriteRequest() {
+ return wrappedSession.getCurrentWriteRequest();
+ }
+
+ /**
+ * @see IoSession#isBothIdle()
+ */
+ public boolean isBothIdle() {
+ return wrappedSession.isBothIdle();
+ }
+
+ /**
+ * @see IoSession#isReaderIdle()
+ */
+ public boolean isReaderIdle() {
+ return wrappedSession.isReaderIdle();
+ }
+
+ /**
+ * @see IoSession#isWriterIdle()
+ */
+ public boolean isWriterIdle() {
+ return wrappedSession.isWriterIdle();
+ }
+
+ /**
+ * Indicates whether the control socket for this session is secure, that is,
+ * running over SSL/TLS
+ *
+ * @return true if the control socket is secured
+ */
+ public boolean isSecure() {
+ return getFilterChain().contains(SslFilter.class);
+ }
+
+ /**
+ * Increase the number of bytes written on the data connection
+ *
+ * @param increment
+ * The number of bytes written
+ */
+ public void increaseWrittenDataBytes(int increment) {
+ if (wrappedSession instanceof AbstractIoSession) {
+ ((AbstractIoSession) wrappedSession)
+ .increaseScheduledWriteBytes(increment);
+ ((AbstractIoSession) wrappedSession).increaseWrittenBytes(
+ increment, System.currentTimeMillis());
+ }
+ }
+
+ /**
+ * Increase the number of bytes read on the data connection
+ *
+ * @param increment
+ * The number of bytes written
+ */
+ public void increaseReadDataBytes(int increment) {
+ if (wrappedSession instanceof AbstractIoSession) {
+ ((AbstractIoSession) wrappedSession).increaseReadBytes(increment,
+ System.currentTimeMillis());
+ }
+ }
+
+ /**
+ * Returns the last reply that was sent to the client.
+ *
+ * @return the last reply that was sent to the client.
+ */
+ public FtpReply getLastReply() {
+ return lastReply;
+ }
+
+ /**
+ * @see IoSession#getWriteRequestQueue()
+ */
+ public WriteRequestQueue getWriteRequestQueue() {
+ return wrappedSession.getWriteRequestQueue();
+ }
+
+ /**
+ * @see IoSession#isReadSuspended()
+ */
+ public boolean isReadSuspended() {
+ return wrappedSession.isReadSuspended();
+ }
+
+ /**
+ * @see IoSession#isWriteSuspended()
+ */
+ public boolean isWriteSuspended() {
+ return wrappedSession.isWriteSuspended();
+ }
+
+ /**
+ * @see IoSession#setCurrentWriteRequest(WriteRequest)
+ */
+ public void setCurrentWriteRequest(WriteRequest currentWriteRequest) {
+ wrappedSession.setCurrentWriteRequest(currentWriteRequest);
+ }
+
+ /**
+ * @see IoSession#updateThroughput(long, boolean)
+ */
+ public void updateThroughput(long currentTime, boolean force) {
+ wrappedSession.updateThroughput(currentTime, force);
+ }
}
Modified: mina/ftpserver/branches/1.0.x/core/src/test/java/org/apache/ftpserver/clienttests/LoginTest.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/branches/1.0.x/core/src/test/java/org/apache/ftpserver/clienttests/LoginTest.java?rev=942689&r1=942688&r2=942689&view=diff
==============================================================================
--- mina/ftpserver/branches/1.0.x/core/src/test/java/org/apache/ftpserver/clienttests/LoginTest.java (original)
+++ mina/ftpserver/branches/1.0.x/core/src/test/java/org/apache/ftpserver/clienttests/LoginTest.java Mon May 10 08:58:54 2010
@@ -24,6 +24,7 @@ import java.io.ByteArrayInputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPConnectionClosedException;
import org.apache.commons.net.ftp.FTPReply;
+import org.apache.ftpserver.ftplet.FtpStatistics;
/**
*
@@ -84,8 +85,8 @@ public class LoginTest extends ClientTes
}
public void testREIN() throws Exception {
- assertTrue(client.login(ADMIN_USERNAME, ADMIN_PASSWORD));
- assertTrue(FTPReply.isPositiveCompletion(client.rein()));
+ assertTrue(client.login(ADMIN_USERNAME, ADMIN_PASSWORD));
+ assertTrue(FTPReply.isPositiveCompletion(client.rein()));
assertTrue(client.login(TESTUSER1_USERNAME, TESTUSER_PASSWORD));
}
@@ -116,6 +117,15 @@ public class LoginTest extends ClientTes
public void testLoginUnknownUser() throws Exception {
assertFalse(client.login(UNKNOWN_USERNAME, UNKNOWN_PASSWORD));
}
+ public void testLoginCount() throws Exception {
+ FtpStatistics stats = server.getServerContext().getFtpStatistics();
+ assertTrue(client.login(ADMIN_USERNAME, ADMIN_PASSWORD));
+ int n =stats.getCurrentLoginNumber();
+ assertEquals(1,n );
+ client.rein();
+ client.logout();
+ assertEquals(0, stats.getCurrentLoginNumber());
+ }
/*
* public void testLoginWithMaxConnectionsPerIp() throws Exception {