package org.maachang.comet.net ;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

import org.maachang.comet.httpd.HttpSocket;

/**
 * SSLサーバソケット.
 * 
 * @version 2007/11/17
 * @author  masahito suzuki
 * @since   MaachangComet 1.00
 */
class NetSslServerImpl implements HttpServer {
    
    private static final int TIMEOUT = 500 ;
    private static final int DEFAULT_PORT = 3334 ;
    protected static final int MIN_LENGTH = 1 ;
    protected static final int MAX_LENGTH = 5000 ;
    private ServerSocket serverSocket = null ;
    
    private NetSslServerImpl() { }
    
    public NetSslServerImpl( SslServerFactory factory,int port,int backlog )
        throws Exception {
        this( factory,null,port,backlog ) ;
    }
    
    public NetSslServerImpl( SslServerFactory factory,InetAddress addr,int port,int backlog )
        throws Exception {
        if( factory == null ) {
            throw new IllegalArgumentException( "SslServerFactoryが設定されていません" ) ;
        }
        if( backlog <= MIN_LENGTH ) {
            backlog = MIN_LENGTH ;
        }
        else if( backlog > MAX_LENGTH ) {
            backlog = MAX_LENGTH ;
        }
        if( port <= 0 || port > 65535 ) {
            port = DEFAULT_PORT ;
        }
        ServerSocket server = factory.serverSocket() ;
        server.setReuseAddress( true ) ;
        server.setSoTimeout( TIMEOUT ) ;
        if( addr == null ) {
            server.bind( new InetSocketAddress( port ),backlog ) ;
        }
        else {
            server.bind( new InetSocketAddress( addr,port ),backlog ) ;
        }
        this.serverSocket = server ;
    }
    
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    public void destroy() {
        if( this.serverSocket != null ) {
            try {
                this.serverSocket.close() ;
            } catch( Exception e ) {
            }
        }
        this.serverSocket = null ;
    }
    
    public HttpSocket accept() throws Exception {
        if( isClosed() == true ) {
            throw new IOException( "サーバソケットは利用出来ません" ) ;
        }
        HttpSocket ret = null ;
        try {
            Socket s = this.serverSocket.accept() ;
            ret = new NetHttpSocketImpl( s ) ;
        } catch( SocketTimeoutException st ) {
            ret = null ;
        } catch( Exception e ) {
            throw e ;
        }
        return ret ;
    }
    
    public ServerSocket serverSocket() {
        if( isClosed() == true ) {
            return null ;
        }
        return this.serverSocket ;
    }
    
    public boolean isClosed() {
        boolean ret = false ;
        try {
            if( this.serverSocket == null ||
                this.serverSocket.isBound() == false ||
                this.serverSocket.isClosed() == true ) {
                ret = true ;
            }
        } catch( Exception e ) {
            ret = true ;
        }
        return ret ;
    }
    
}
