001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008 Sun Microsystems, Inc. 015 * Portions Copyright 2012-2015 ForgeRock AS. 016 */ 017package org.opends.server.core; 018 019import org.forgerock.i18n.LocalizableMessage; 020 021import org.opends.server.api.ClientConnection; 022import org.opends.server.api.ConnectionHandler; 023import org.opends.server.api.DirectoryThread; 024import org.opends.server.api.ServerShutdownListener; 025import org.forgerock.i18n.slf4j.LocalizedLogger; 026import org.opends.server.types.DisconnectReason; 027 028import static org.opends.messages.CoreMessages.*; 029import static org.opends.server.util.StaticUtils.*; 030 031/** 032 * This class defines a thread that will be used to terminate client 033 * connections if they have been idle for too long. 034 */ 035public class IdleTimeLimitThread 036 extends DirectoryThread 037 implements ServerShutdownListener 038{ 039 /** The debug log tracer for this object. */ 040 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 041 042 043 044 /** Shutdown monitor state. */ 045 private volatile boolean shutdownRequested; 046 private final Object shutdownLock = new Object(); 047 048 049 050 /** 051 * Creates a new instance of this idle time limit thread. 052 */ 053 public IdleTimeLimitThread() 054 { 055 super("Idle Time Limit Thread"); 056 setDaemon(true); 057 058 shutdownRequested = false; 059 DirectoryServer.registerShutdownListener(this); 060 } 061 062 063 064 /** 065 * Operates in a loop, teriminating any client connections that have been idle 066 * for too long. 067 */ 068 public void run() 069 { 070 LocalizableMessage disconnectMessage = INFO_IDLETIME_LIMIT_EXCEEDED.get(); 071 072 long sleepTime = 5000L; 073 074 while (! shutdownRequested) 075 { 076 try 077 { 078 synchronized (shutdownLock) 079 { 080 if (!shutdownRequested) 081 { 082 try 083 { 084 shutdownLock.wait(sleepTime); 085 } 086 catch (InterruptedException e) 087 { 088 // Server shutdown monitor may interrupt slow threads. 089 logger.traceException(e); 090 shutdownRequested = true; 091 break; 092 } 093 } 094 } 095 096 sleepTime = 5000L; 097 for (ConnectionHandler<?> ch : DirectoryServer.getConnectionHandlers()) 098 { 099 for (ClientConnection c : ch.getClientConnections()) 100 { 101 if (c==null) { 102 logger.trace("Null client connection found in \"" + ch.getConnectionHandlerName() + "\""); 103 continue; 104 } 105 106 long idleTime = c.getIdleTime(); 107 if (idleTime > 0) 108 { 109 long idleTimeLimit = c.getIdleTimeLimit(); 110 if (idleTimeLimit > 0) 111 { 112 if (idleTime >= idleTimeLimit) 113 { 114 if (logger.isTraceEnabled()) 115 { 116 logger.trace("Terminating client connection " + 117 c.getConnectionID() + 118 " due to the idle time limit"); 119 } 120 121 try 122 { 123 c.disconnect(DisconnectReason.IDLE_TIME_LIMIT_EXCEEDED, 124 true, disconnectMessage); 125 } 126 catch (Exception e) 127 { 128 logger.traceException(e); 129 130 logger.error(ERR_IDLETIME_DISCONNECT_ERROR, c.getConnectionID(), 131 stackTraceToSingleLineString(e) 132 ); 133 } 134 } 135 else 136 { 137 long shouldSleepTime = idleTimeLimit - idleTime; 138 if (shouldSleepTime < sleepTime) 139 { 140 sleepTime = shouldSleepTime; 141 } 142 } 143 } 144 } 145 } 146 } 147 } 148 catch (Exception e) 149 { 150 logger.traceException(e); 151 152 logger.error(ERR_IDLETIME_UNEXPECTED_ERROR, stackTraceToSingleLineString(e)); 153 } 154 } 155 } 156 157 158 159 /** {@inheritDoc} */ 160 public String getShutdownListenerName() 161 { 162 return "Idle Time Limit Thread"; 163 } 164 165 166 167 /** {@inheritDoc} */ 168 public void processServerShutdown(LocalizableMessage reason) 169 { 170 synchronized (shutdownLock) 171 { 172 shutdownRequested = true; 173 shutdownLock.notifyAll(); 174 } 175 } 176} 177