/*
* Created on 02-Jan-2005
* Created by Paul Gardner
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* 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 2
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.tracker.server.impl.tcp.blocking;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.security.SESecurityManager;
import org.gudy.azureus2.core3.tracker.server.TRTrackerServerException;
import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.Debug;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
/**
* @author parg
*
*/
public class
TRBlockingServer
extends TRTrackerServerTCP
{
private static final LogIDs LOGID = LogIDs.TRACKER;
private InetAddress current_bind_ip;
private ServerSocket server_socket;
private volatile boolean closed;
public
TRBlockingServer(
String _name,
int _port,
InetAddress _bind_ip,
boolean _ssl,
boolean _apply_ip_filter,
boolean _start_up_ready )
throws TRTrackerServerException
{
super( _name, _port, _ssl, _apply_ip_filter, _start_up_ready );
boolean ok = false;
try{
InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress();
String tr_bind_ip = COConfigurationManager.getStringParameter("Bind IP for Tracker", "");
if ( tr_bind_ip.length() >= 7 ){
try{
bind_ip = InetAddress.getByName(tr_bind_ip);
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
if ( _ssl ){
if ( _port == 0 ){
throw( new TRTrackerServerException( "port of 0 not currently supported for SSL"));
}
try {
SSLServerSocketFactory factory = SESecurityManager.getSSLServerSocketFactory();
if ( factory == null ){
throw( new TRTrackerServerException( "TRTrackerServer: failed to get SSL factory" ));
}else{
SSLServerSocket ssl_server_socket;
if ( _bind_ip != null ){
current_bind_ip = _bind_ip;
ssl_server_socket = (SSLServerSocket)factory.createServerSocket( getPort(), 128, _bind_ip );
}else if ( bind_ip == null ){
ssl_server_socket = (SSLServerSocket)factory.createServerSocket( getPort(), 128 );
}else{
current_bind_ip = bind_ip;
ssl_server_socket = (SSLServerSocket)factory.createServerSocket( getPort(), 128, bind_ip );
}
String cipherSuites[] = ssl_server_socket.getSupportedCipherSuites();
ssl_server_socket.setEnabledCipherSuites(cipherSuites);
ssl_server_socket.setNeedClientAuth(false);
ssl_server_socket.setReuseAddress(true);
server_socket = ssl_server_socket;
Thread accept_thread =
new AEThread("TRTrackerServer:accept.loop(ssl)")
{
public void
runSupport()
{
acceptLoop( server_socket );
}
};
accept_thread.setDaemon( true );
accept_thread.start();
Logger.log(new LogEvent(LOGID,
"TRTrackerServer: SSL listener established on port "
+ getPort()));
ok = true;
}
}catch( Throwable e){
Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { ""
+ getPort() });
Logger.log(new LogEvent(LOGID,
"TRTrackerServer: SSL listener failed on port " + getPort(), e));
if ( e instanceof TRTrackerServerException ){
throw((TRTrackerServerException)e);
}else{
throw( new TRTrackerServerException( "TRTrackerServer: accept fails: " + e.toString()));
}
}
}else{
try{
ServerSocket ss;
int port = getPort();
if ( _bind_ip != null ){
current_bind_ip = _bind_ip;
ss = new ServerSocket( port, 1024, _bind_ip );
}else if ( bind_ip == null ){
ss = new ServerSocket( port, 1024 );
}else{
current_bind_ip = bind_ip;
ss = new ServerSocket( port, 1024, bind_ip );
}
if ( port == 0 ){
setPort( ss.getLocalPort());
}
ss.setReuseAddress(true);
server_socket = ss;
Thread accept_thread =
new AEThread("TRTrackerServer:accept.loop")
{
public void
runSupport()
{
acceptLoop( server_socket );
}
};
accept_thread.setDaemon( true );
accept_thread.start();
Logger.log(new LogEvent(LOGID, "TRTrackerServer: "
+ "listener established on port " + getPort()));
ok = true;
}catch( Throwable e){
Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
LogAlert.AT_ERROR, "Tracker.alert.listenfail"), new String[] { ""
+ getPort() });
throw( new TRTrackerServerException( "TRTrackerServer: accept fails", e ));
}
}
}finally{
if ( !ok ){
destroySupport();
}
}
}
public InetAddress
getBindIP()
{
return( current_bind_ip );
}
protected void
acceptLoop(
ServerSocket ss )
{
long successfull_accepts = 0;
long failed_accepts = 0;
while( !closed ){
try{
Socket socket = ss.accept();
successfull_accepts++;
String ip = socket.getInetAddress().getHostAddress();
if ( (!isIPFilterEnabled()) || (!ip_filter.isInRange( ip, "Tracker", null ))){
runProcessor( new TRBlockingServerProcessor( this, socket ));
}else{
socket.close();
}
}catch( Throwable e ){
if ( !closed ){
failed_accepts++;
Logger.log(new LogEvent(LOGID,
"TRTrackerServer: listener failed on port " + getPort(), e));
if ( failed_accepts > 100 && successfull_accepts == 0 ){
// looks like its not going to work...
// some kind of socket problem
Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] {
"" + getPort(), "TCP" });
break;
}
}
}
}
}
protected void
closeSupport()
{
closed = true;
try{
server_socket.close();
}catch( Throwable e ){
}
destroySupport();
}
}