/*  HTTPS-Server
 *
 *  Copyright (C) 2023  Rene Pawlitzek, Robert Schoech
 *  
 *  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 3 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, see <https://www.gnu.org/licenses/>.
 */

import java.io.*;
import java.net.InetSocketAddress;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLContext;

import com.sun.net.httpserver.*;

public class HTTPSServer 
{
    public static void main(String[] args)
    {
       try 
       {
            // setup the socket address
            //InetSocketAddress inetSocketAddress = new InetSocketAddress(9000);
            InetSocketAddress inetSocketAddress = new InetSocketAddress(8080);

            // initialize the HTTPS server
            HttpsServer server = HttpsServer.create(inetSocketAddress, 0);
            SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); // Transport Layer Security

            // initialise the keystore - Java Key Store (JKS)
            String password = "password";
            KeyStore keyStore = KeyStore.getInstance("JKS");
            
            FileInputStream fis = new FileInputStream(".\\testkey.jks");
            
            keyStore.load(fis, password.toCharArray());

            // setup the key manager factory
            KeyManagerFactory keyManager = KeyManagerFactory.getInstance("SunX509");
            keyManager.init(keyStore, password.toCharArray());
 
            // setup the trust manager factory
            TrustManagerFactory trustManager = TrustManagerFactory.getInstance("SunX509");
            trustManager.init(keyStore);

            // setup the HTTPS context and parameters
            sslContext.init(keyManager.getKeyManagers(), trustManager.getTrustManagers(), null);
            server.setHttpsConfigurator(new HttpsConfigurator(sslContext) 
            {
                public void configure(HttpsParameters params) 
                {
                    try 
                    {
                        // initialise the SSL context
                        SSLContext sslContext = getSSLContext();
                        SSLEngine sslEngine = sslContext.createSSLEngine();
                        params.setNeedClientAuth(false);
                        params.setCipherSuites(sslEngine.getEnabledCipherSuites());
                        params.setProtocols(sslEngine.getEnabledProtocols());

                        // set the SSL parameters
                        SSLParameters sslParameters = sslContext.getSupportedSSLParameters();
                        params.setSSLParameters(sslParameters);
                        System.out.println("The HTTPS server is connected to port " + inetSocketAddress.getPort());
                    } 
                    catch (Exception ex) 
                    {
                        System.out.println("Failed to connect the HTTPS server with port " + inetSocketAddress.getPort());
                    }
                } // configure
            });
            server.createContext("/page", new MyTestHandler());
            server.createContext("/secondpage", new MySecondTestHandler());
            server.setExecutor(null); // creates a default executor
            server.start();
            System.out.println("The HTTPS server is started on port "  + inetSocketAddress.getPort());
        } 
        catch (Exception exception) 
        {
            System.out.println("Failed to start HTTPS server on port " + 9000 + " of localhost");
            exception.printStackTrace();
        }
    } // main
    
    public static class MyTestHandler implements HttpHandler 
    {
        @Override
        public void handle(HttpExchange ex) throws IOException 
        {
            // construct a response
            String response = "This is the secured response from my server";
            HttpsExchange httpsEx = (HttpsExchange) ex;
            httpsEx.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
            httpsEx.sendResponseHeaders(200, response.getBytes().length);
            OutputStream os = ex.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    } // MyTestHandler
    
    public static class MySecondTestHandler implements HttpHandler 
    {
        @Override
        public void handle(HttpExchange ex) throws IOException {
            // construct a response with HTML format
            StringBuffer buffer = new StringBuffer(); 
            buffer.append("<HTML>\n");
            buffer.append("<HEAD><TITLE>HTTPS Server</TITLE></HEAD>\n");
            buffer.append("<BODY>\n"); 
            buffer.append("<H1>Success!</H1>\n");
            
            String response = buffer.toString();
            HttpsExchange httpsEx = (HttpsExchange) ex;
            httpsEx.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
            httpsEx.sendResponseHeaders(200, response.getBytes().length);
            OutputStream os = ex.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    } // MySecondTestHandler
}