package org.maachang.comet.net ;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.ServerSocketChannel;

import org.maachang.comet.net.ssl.SslOption;

/**
 * SSLサーバソケット.
 * 
 * @version 2007/11/17
 * @author  masahito suzuki
 * @since   MaachangComet 1.00
 */
class NetSslServerImpl implements HttpServer {
    
    private static final int DEFAULT_PORT = 3443 ;
    protected static final int MIN_LENGTH = 1 ;
    protected static final int MAX_LENGTH = 5000 ;
    
    private SslOption option = null ;
    private ServerSocketChannel channel = null ;
    
    private NetSslServerImpl() { }
    
    public NetSslServerImpl( SslOption option,int port,int backlog )
        throws Exception {
        this( option,null,port,backlog ) ;
    }
    
    public NetSslServerImpl( SslOption option,InetAddress addr,int port,int backlog )
        throws Exception {
        if( option == null ) {
            throw new IllegalArgumentException( "SslOptionが設定されていません" ) ;
        }
        if( backlog <= MIN_LENGTH ) {
            backlog = MIN_LENGTH ;
        }
        else if( backlog > MAX_LENGTH ) {
            backlog = MAX_LENGTH ;
        }
        if( port <= 0 || port > 65535 ) {
            port = DEFAULT_PORT ;
        }
        ServerSocketChannel channel = ServerSocketChannel.open() ;
        channel.configureBlocking(false);
        ServerSocket soc = channel.socket() ;
        soc.setReuseAddress( true ) ;
        if( addr == null ) {
            soc.bind( new InetSocketAddress( port ),backlog ) ;
        }
        else {
            soc.bind( new InetSocketAddress( addr,port ),backlog ) ;
        }
        this.option = option ;
        this.channel = channel ;
    }
    
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    public void destroy() {
        if( this.channel != null ) {
            try {
                this.channel.close() ;
            } catch( Exception e ) {
            }
        }
        this.channel = null ;
    }
    
    public ServerSocketChannel channel() {
        if( isClosed() ) {
            return null ;
        }
        return channel ;
    }
    
    public Object option() {
        if( isClosed() ) {
            return null ;
        }
        return option ;
    }
    
    public boolean isClosed() {
        boolean ret = false ;
        try {
            if( this.channel == null ||
                this.channel.socket().isBound() == false ||
                this.channel.socket().isClosed() == true ) {
                ret = true ;
            }
        } catch( Exception e ) {
            ret = true ;
        }
        return ret ;
    }
}
