package com.nms.server.thread.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Calendar;
import java.util.concurrent.Callable;

import javax.net.ssl.SSLServerSocket;

import org.apache.log4j.Logger;

import com.nms.server.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.util.socket.SocketUtils;

/**
 * 用于安全通讯的服务Socket，采用java中的SSLServerSocket
 **/
public class SSLServerManager implements Callable<Object>{
	
	Logger logger = Logger.getLogger(SSLServerManager.class);
	
	//ServerSocket 通讯服务
	private SSLServerSocket sslServer = null;
	
	public SSLServerManager(int port,boolean clientAuth) throws Exception{
		int test = 3;
		while(true){
//			sslServer = (SSLServerSocket) SocketUtils.getSSLContext().getServerSocketFactory().createServerSocket(port,100);
			logger.info("开始绑定端口。。。。。");
			sslServer = (SSLServerSocket) SocketUtils.getSSLContext().getServerSocketFactory().createServerSocket();
			sslServer.setReuseAddress(true);
			sslServer.bind(new InetSocketAddress(port),(int)(Constants.EXECUTOR_SOCKET_THREAD_SIZE*0.8));
			//端口监听状态判断
			if(sslServer != null && sslServer.isBound()){	//启动成功跳出循环
				logger.info("端口["+port+"]绑定成功，通讯服务启动成功");
				Constants.sslServer = sslServer;
				break;
			}else{		//启动是失败，10秒后再次尝试
				if(sslServer!=null){
					sslServer.close();
					sslServer = null;
				}
				//超过最大尝试次数跳出
				if(0 > --test){
					logger.error("The communication service port binding failed, exceeding the maximum number of attempts.");
//					throw new Exception("通讯服务端口绑定失败，且超过最大次数，启动失败");
					throw new Exception("The communication service port binding failed and exceeded the maximum number of times to start failure.");
				}else{
					logger.warn("The port["+port+"]binding failed, and the communication service started again after 10 seconds");
					Thread.sleep(10*1000);
				}
			}
			
		}
		
		sslServer.setNeedClientAuth(clientAuth);		//客户端是否需要认证
		logger.info("本地通讯端口"+port+"监听线程启动成功");
	}
	
	/**
	 * 重载方法：run 处理客户端的请求
	 **/
	public Object call() {
		Thread.currentThread().setName("Receiving communication");
		try {
			while (true) {
				Socket socket = sslServer.accept();
				if(Common.SERVER_UN_UPGRADE_FLAG){	//当SOCKET_FLAG为true时，允许建立通讯，否则放弃通讯，用于NMSServer升级功能
					logger.debug("来自："+socket.getInetAddress().getHostAddress());
					Common.service.submit(new SSLServer(socket));
				}else{	//关闭 放弃的通讯
					logger.debug("Server升级 抛弃通讯："+socket.getInetAddress().getHostAddress());
					socket.close();
				}
			}
		} catch (IOException e) {
			logger.error("Local communication port monitor thread exception termination"+e.getMessage());
			Common.addErrorInfo(Constants.ERROR_CODE_SOCKET_SERVER_RUNTIME,Common.getLocalIp(), Calendar.getInstance().getTime(), Constants.ERROR_INFO_SATAE_ERROR,"");
			
		}finally{
			try {
				sslServer.close();
			} catch (IOException e) {
				logger.error("",e);
			}
		}
		return null;
	}
	
	//测试函数
	public static void main(String args[]) {
		 try {
			Common.service.submit(new SSLServerManager(60702,true));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}