import java.net.Socket;
import java.net.ServerSocket;
import java.net.SocketException;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ServerSocketFactory;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLServerSocket;

public class Server extends Thread
{
  int port = 5000;
  public Server(int port_)
  {
    port = port_;
  }

  public void run()
  {
      ServerSocketFactory ssocketFactory = SSLServerSocketFactory.getDefault();
      ServerSocket ssocket = null;
      InputStream in = null;
      InputStreamReader isr = null;
      BufferedReader br = null;
      OutputStream out = null;
      OutputStream os = null;
      OutputStreamWriter osw = null;
      BufferedWriter bw = null;
      Socket socketToClient = null;
      try {
        ssocket = ssocketFactory.createServerSocket(port);
      } catch (Exception e) {
	e.printStackTrace();
	System.exit(-1);
      }
      //require the use of MASSL 
      ((SSLServerSocket)ssocket).setNeedClientAuth(true);
    try {
      while(true) {
        socketToClient = ssocket.accept();
        in = socketToClient.getInputStream();
        isr = new InputStreamReader(in);
   	br = new BufferedReader(isr);
	out = socketToClient.getOutputStream();
        osw  = new OutputStreamWriter(out);
        bw = new BufferedWriter(osw);
	handleCommunication(br,bw);
        br.close();
        isr.close();
        in.close();
	bw.close();
	osw.close();
        out.close();
	socketToClient.close();
      }
    } catch(SocketException e) {
      e.printStackTrace();
    } catch(IOException e) {
      e.printStackTrace();
    } catch(Exception e) {
      e.printStackTrace(); 
    } finally {
      try {
        if(br != null) br.close();
        if(isr != null) isr.close();
        if(in != null) in.close();
        if(bw != null) bw.close();
        if(osw != null) osw.close();
        if(out != null) out.close();
        if(socketToClient != null) socketToClient.close();
      } catch (IOException e) {
	e.printStackTrace();
      }
    }
  }

  private void handleCommunication(BufferedReader br, BufferedWriter bw)
	throws IOException,SocketException
  {
    try {
      String line = br.readLine();
      System.out.println("Line: " + line);
      //Begin handshake
      if( line != null && line.equals("<<<<<")) 
      {
        System.out.println("<<<<< encountered as expected.");
      } else {
        throw new IOException("Protocol Violation: leading '<<<<<' not found");
      }
      bw.write(">>>>>\n");
      System.out.println("Handshake completed successfully");
      bw.flush();
      line = null;
      line = br.readLine();
      System.out.println("Line: " + line);
      int numberIterations = 0;
      if( line != null) {
        numberIterations = Integer.parseInt(line);
        System.out.println("Number of iterations: " + numberIterations);
      }
      if(numberIterations > 0) {
  	bw.write("ACCEPT\n");
  	System.out.println("Sending: ACCEPT");
      } else {
  	bw.write("DENIED\n");
	System.out.println("Sending: DENIED");
      }
      bw.flush();
      System.out.println("Counting to " + numberIterations);
      for(int i = 1; i <= numberIterations; i++)
      {
        line = null;
        line = br.readLine();
        System.out.println("Received: " + line);
        bw.write(line + "\n");
        bw.flush();
        System.out.println("Responded: " + line);
      }
    } catch (SocketException e) {
      System.out.println("An error occured while communicating with the client.");
    }
  }

  public static void main(String args[])
  {
    Server ssls = new Server(Integer.parseInt(args[0]));
    ssls.start();
  }
}
