/*
* Copyright 2004 - 2008 Christian Sprajc. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: Controller.java 6331 2009-01-03 18:40:42Z tot $
*/
package de.dal33t.powerfolder.net;
import java.util.Date;
import de.dal33t.powerfolder.Constants;
import de.dal33t.powerfolder.Controller;
import de.dal33t.powerfolder.PFComponent;
import de.dal33t.powerfolder.util.Profiling;
import de.dal33t.powerfolder.util.ProfilingEntry;
/**
* An acceptor is a task to fully handshake a new incoming connection.
*
* @author Christian Sprajc
* @version $Revision$
*/
public abstract class AbstractAcceptor extends PFComponent implements Runnable {
private Date startTime;
private ConnectionHandler handler;
protected AbstractAcceptor(Controller controller) {
super(controller);
}
/**
* @return information about the connection, e.g. remote address
*/
public abstract String getConnectionInfo();
/**
* Shuts the acceptor down and closes the socket
*/
protected abstract void shutdown();
/**
* Overriding behavior. Performs the actual work. If Exception occurs the
* acceptor gets shut down.
*/
protected abstract void accept() throws ConnectionException;
/**
* @return if this acceptor has a timeout
*/
boolean hasTimeout() {
if (startTime == null) {
// Not started yet
return false;
}
Date lastKeepAlive = handler != null ? handler
.getLastKeepaliveMessageTime() : null;
if (lastKeepAlive == null) {
// No handler/We cannot check the last keepalive message.
return System.currentTimeMillis() > startTime.getTime()
+ (1000L * Constants.CONNECTION_KEEP_ALIVE_TIMOUT);
}
// Check if the last keepalive timeout
return System.currentTimeMillis() > lastKeepAlive.getTime()
+ (1000L * Constants.CONNECTION_KEEP_ALIVE_TIMOUT);
}
boolean isShutdown() {
return handler != null && !handler.isConnected();
}
public final void run() {
if (!getController().getNodeManager().isStarted()) {
logWarning("NodeManager already shut down. "
+ "Closing incoming connection attempt: " + this);
return;
}
ProfilingEntry pe = Profiling.start();
startTime = new Date();
try {
accept();
} catch (ConnectionException e) {
logFiner("Unable to accept incoming connection handler " + this, e);
shutdown();
} catch (RuntimeException e) {
if (e.getCause() instanceof InterruptedException) {
logFiner("Acceptor interrupted, closing. " + this);
shutdown();
} else {
throw e;
}
} finally {
// Remove from acceptors list
getController().getNodeManager().acceptors.remove(this);
Profiling.end(pe);
}
}
/**
* Convenience method to accept the new Connection Handler.
*
* @param handler
*/
protected void acceptConnection(ConnectionHandler handler) {
try {
this.handler = handler;
getController().getNodeManager().acceptConnection(handler);
} catch (ConnectionException e) {
logFiner("Unable to accept incoming connection handler " + handler,
e);
handler.shutdown();
shutdown();
// Remove from acceptors list
getController().getNodeManager().acceptors.remove(this);
}
}
public String toString() {
return getClass().getSimpleName() + ":" + getConnectionInfo();
}
}