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