/*-
* Copyright Bogdan Mocanu, 2010
*
* This program 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; either version 3
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package ro.bmocanu.trafficproxy.input;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import ro.bmocanu.trafficproxy.Constants;
import ro.bmocanu.trafficproxy.base.Manageable;
import ro.bmocanu.trafficproxy.base.ManageableThread;
/**
* A server thread that listens to a specified port and spawns new workers (see
* {@link InputConnectorWorker}) to serve each new connection that it receives.
*
* @author mocanu
* @see InputConnector
* @see InputConnectorWorker
* @see ManageableThread
*/
@Component
@Scope( Constants.PROTOTYPE )
public class InputConnectorServer extends ManageableThread {
private static final Logger LOG = Logger.getLogger( InputConnectorServer.class );
/**
* The connector object that describes this server.
*/
private InputConnector connector;
/**
* The socket used for listening for incoming requests.
*/
private ServerSocket serverSocket;
// -------------------------------------------------------------------------------------------------
/**
* @param connector
*/
public InputConnectorServer(InputConnector connector) {
this.connector = connector;
}
/**
* {@inheritDoc}
*
* @throws IOException
*/
@Override
public void init() throws IOException {
serverSocket = new ServerSocket( connector.getPort() );
serverSocket.setSoTimeout( Constants.INPUT_CONNECTOR_SOCKET_TIMEOUT );
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() throws Exception {
if ( serverSocket != null && !serverSocket.isClosed() ) {
serverSocket.close();
}
}
// -------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
protected void internalRun() {
try {
Socket clientSocket = serverSocket.accept();
InputConnectorWorker newWorker = new InputConnectorWorker( connector, generateWorkerId(), clientSocket );
//ProxyKernel.getInstance().registerConnectorWorker( connector.getId(), newWorker.getWorkerId(), newWorker );
startWorker( newWorker );
} catch ( SocketTimeoutException exception ) {
// this is ok, it means that we finished a session of listening
// return the control to the thread core
} catch ( IOException exception ) {
LOG.error( exception );
}
}
// -------------------------------------------------------------------------------------------------
private int generateWorkerId() throws IOException {
for ( int possibleId = 0; possibleId < Integer.MAX_VALUE; possibleId++ ) {
boolean found = false;
for ( Manageable worker : workers ) {
if ( ((InputConnectorWorker) worker).getWorkerId() == possibleId ) {
found = true;
break;
}
}
if ( !found ) {
return possibleId;
}
}
throw new IOException( "The max number of " + Integer.MAX_VALUE + " of workers for connector id="
+ connector.getId() + " has been reached. Cannot generate more workers" );
}
}