// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.consoleproxy.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

//
// This file is originally from XenConsole with modifications 
//

/**
 * Send an HTTP CONNECT or PUT request to a XenAPI host with a Session ID,
 * return the connected socket and the Task ID. Used for tunnelling VNC
 * connections and import/export operations.
 */
public final class RawHTTP {
    private static final Logger s_logger = Logger.getLogger(RawHTTP.class);

    private static final Pattern END_PATTERN = Pattern.compile("^\r\n$");
    private static final Pattern HEADER_PATTERN = Pattern
            .compile("^([A-Z_a-z0-9-]+):\\s*(.*)\r\n$");
    private static final Pattern HTTP_PATTERN = Pattern
            .compile("^HTTP/\\d+\\.\\d+ (\\d*) (.*)\r\n$");

    /**
     * @uml.property  name="command"
     */
    private final String command;
    /**
     * @uml.property  name="host"
     */
    private final String host;
    /**
     * @uml.property  name="port"
     */
    private final int port;
    /**
     * @uml.property  name="path"
     */
    private final String path;
    /**
     * @uml.property  name="session"
     */
    private final String session;
    /**
     * @uml.property  name="useSSL"
     */
    private final boolean useSSL;

    /**
     * @uml.property  name="responseHeaders"
     * @uml.associationEnd  qualifier="group:java.lang.String java.lang.String"
     */
    private final Map<String, String> responseHeaders = new HashMap<String, String>();

    /**
     * @uml.property  name="ic"
     */
    private InputStream ic;
    /**
     * @uml.property  name="oc"
     */
    private OutputStream oc;
    /**
     * @uml.property  name="s"
     */
    private Socket s;

    public InputStream getInputStream() {
        return ic;
    }

    public OutputStream getOutputStream() {
        return oc;
    }

    public Socket getSocket() {
        return s;
    }

    public RawHTTP(String command, String host, int port, String path,
            String session, boolean useSSL) {
        this.command = command;
        this.host = host;
        this.port = port;
        this.path = path;
        this.session = session;
        this.useSSL = useSSL;
    }

    private static final TrustManager[] trustAllCerts = new TrustManager[] { 
        new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } 
    };

    private Socket _getSocket() throws IOException {
        if (useSSL) {
            SSLContext context = getClientSSLContext();
            if(context == null)
                throw new IOException("Unable to setup SSL context");
            
            SSLSocket ssl = null;
            try {
                context.init(null, trustAllCerts, new SecureRandom());
                SocketFactory factory = context.getSocketFactory();
                ssl = (SSLSocket) factory.createSocket(host, port);
                /* ssl.setSSLParameters(context.getDefaultSSLParameters()); */
            } catch (IOException e) {
                s_logger.error("IOException: " + e.getMessage(), e);
                throw e;
            } catch (KeyManagementException e) {
                s_logger.error("KeyManagementException: " + e.getMessage(), e);
            }
            return ssl;
        } else {
            return new Socket(host, port);
        }
    }

    public Socket connect() throws IOException {
        String[] headers = makeHeaders();
        s = _getSocket();
        try {
            oc = s.getOutputStream();
            for (String header : headers) {
                oc.write(header.getBytes());
                oc.write("\r\n".getBytes());
            }
            oc.flush();
            ic = s.getInputStream();
            while (true) {
                String line = readline(ic);

                Matcher m = END_PATTERN.matcher(line);
                if (m.matches()) {
                    return s;
                }

                m = HEADER_PATTERN.matcher(line);
                if (m.matches()) {
                    responseHeaders.put(m.group(1), m.group(2));
                    continue;
                }

                m = HTTP_PATTERN.matcher(line);
                if (m.matches()) {
                    String status_code = m.group(1);
                    String reason_phrase = m.group(2);
                    if (!"200".equals(status_code)) {
                        throw new IOException("HTTP status " + status_code
                                + " " + reason_phrase);
                    }
                } else {
                    throw new IOException("Unknown HTTP line " + line);
                }
            }
        } catch (IOException exn) {
            s.close();
            throw exn;
        } catch (RuntimeException exn) {
            s.close();
            throw exn;
        }
    }

    public Map<String, String> getResponseHeaders() {
        return responseHeaders;
    }

    private String[] makeHeaders() {
        String[] headers = { String.format("%s %s HTTP/1.0", command, path),
                String.format("Host: %s", host),
                String.format("Cookie: session_id=%s", session), "" };
        return headers;
    }

    private static String readline(InputStream ic) throws IOException {
        String result = "";
        while (true) {
            try {
                int c = ic.read();

                if (c == -1) {
                    return result;
                }
                result = result + (char) c;
                if (c == 0x0a /* LF */) {
                    return result;
                }
            } catch (IOException e) {
                ic.close();
                throw e;
            }
        }
    }
    
    private SSLContext getClientSSLContext() {
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL", "SunJSSE");
        } catch (NoSuchAlgorithmException e) {
            s_logger.error("Unexpected exception ", e);
        } catch (NoSuchProviderException e) {
            s_logger.error("Unexpected exception ", e);
        }
        return sslContext;
    }
}
