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-2016 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 /** Shutdown monitor state. */ 043 private volatile boolean shutdownRequested; 044 private final Object shutdownLock = new Object(); 045 046 /** Creates a new instance of this idle time limit thread. */ 047 public IdleTimeLimitThread() 048 { 049 super("Idle Time Limit Thread"); 050 setDaemon(true); 051 052 shutdownRequested = false; 053 DirectoryServer.registerShutdownListener(this); 054 } 055 056 /** Operates in a loop, teriminating any client connections that have been idle for too long. */ 057 @Override 058 public void run() 059 { 060 LocalizableMessage disconnectMessage = INFO_IDLETIME_LIMIT_EXCEEDED.get(); 061 062 long sleepTime = 5000L; 063 064 while (! shutdownRequested) 065 { 066 try 067 { 068 synchronized (shutdownLock) 069 { 070 if (!shutdownRequested) 071 { 072 try 073 { 074 shutdownLock.wait(sleepTime); 075 } 076 catch (InterruptedException e) 077 { 078 // Server shutdown monitor may interrupt slow threads. 079 logger.traceException(e); 080 shutdownRequested = true; 081 break; 082 } 083 } 084 } 085 086 sleepTime = 5000L; 087 for (ConnectionHandler<?> ch : DirectoryServer.getConnectionHandlers()) 088 { 089 for (ClientConnection c : ch.getClientConnections()) 090 { 091 if (c==null) { 092 logger.trace("Null client connection found in \"" + ch.getConnectionHandlerName() + "\""); 093 continue; 094 } 095 096 long idleTime = c.getIdleTime(); 097 if (idleTime > 0) 098 { 099 long idleTimeLimit = c.getIdleTimeLimit(); 100 if (idleTimeLimit > 0) 101 { 102 if (idleTime >= idleTimeLimit) 103 { 104 if (logger.isTraceEnabled()) 105 { 106 logger.trace("Terminating client connection " + 107 c.getConnectionID() + 108 " due to the idle time limit"); 109 } 110 111 try 112 { 113 c.disconnect(DisconnectReason.IDLE_TIME_LIMIT_EXCEEDED, 114 true, disconnectMessage); 115 } 116 catch (Exception e) 117 { 118 logger.traceException(e); 119 120 logger.error(ERR_IDLETIME_DISCONNECT_ERROR, c.getConnectionID(), 121 stackTraceToSingleLineString(e) 122 ); 123 } 124 } 125 else 126 { 127 long shouldSleepTime = idleTimeLimit - idleTime; 128 if (shouldSleepTime < sleepTime) 129 { 130 sleepTime = shouldSleepTime; 131 } 132 } 133 } 134 } 135 } 136 } 137 } 138 catch (Exception e) 139 { 140 logger.traceException(e); 141 142 logger.error(ERR_IDLETIME_UNEXPECTED_ERROR, stackTraceToSingleLineString(e)); 143 } 144 } 145 } 146 147 @Override 148 public String getShutdownListenerName() 149 { 150 return "Idle Time Limit Thread"; 151 } 152 153 @Override 154 public void processServerShutdown(LocalizableMessage reason) 155 { 156 synchronized (shutdownLock) 157 { 158 shutdownRequested = true; 159 shutdownLock.notifyAll(); 160 } 161 } 162}