// 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 rdpclient;

import java.net.InetAddress;
import java.net.UnknownHostException;

import rdpclient.adapter.AwtRdpKeyboardAdapter;
import rdpclient.adapter.AwtRdpMouseAdapter;
import rdpclient.hyperv.ClientPreConnectionBlob;
import rdpclient.ntlmssp.ClientNtlmsspNegotiate;
import rdpclient.ntlmssp.ClientNtlmsspPubKeyAuth;
import rdpclient.ntlmssp.ClientNtlmsspUserCredentials;
import rdpclient.ntlmssp.NtlmState;
import rdpclient.ntlmssp.ServerNtlmsspChallenge;
import rdpclient.ntlmssp.ServerNtlmsspPubKeyPlus1;
import rdpclient.rdp.ClientConfirmActivePDU;
import rdpclient.rdp.ClientFastPathPDU;
import rdpclient.rdp.ClientInfoPDU;
import rdpclient.rdp.ClientMCSAttachUserRequest;
import rdpclient.rdp.ClientMCSChannelJoinRequestServerMCSChannelConfirmPDUs;
import rdpclient.rdp.ClientMCSConnectInitial;
import rdpclient.rdp.ClientMCSErectDomainRequest;
import rdpclient.rdp.ClientTpkt;
import rdpclient.rdp.ClientX224ConnectionRequestPDU;
import rdpclient.rdp.ClientX224DataPDU;
import rdpclient.rdp.RdpConstants;
import rdpclient.rdp.RdpState;
import rdpclient.rdp.ServerBitmapUpdate;
import rdpclient.rdp.ServerDemandActivePDU;
import rdpclient.rdp.ServerFastPath;
import rdpclient.rdp.ServerIOChannelRouter;
import rdpclient.rdp.ServerLicenseErrorPDUValidClient;
import rdpclient.rdp.ServerMCSAttachUserConfirmPDU;
import rdpclient.rdp.ServerMCSConnectResponse;
import rdpclient.rdp.ServerMCSPDU;
import rdpclient.rdp.ServerPaletteUpdate;
import rdpclient.rdp.ServerX224ConnectionConfirmPDU;
import rdpclient.rdp.ServerX224DataPdu;
import streamer.PipelineImpl;
import streamer.Queue;
import streamer.ssl.SSLState;
import streamer.ssl.UpgradeSocketToSSL;
import common.AwtKeyEventSource;
import common.AwtMouseEventSource;
import common.BufferedImageCanvas;
import common.ScreenDescription;
import common.adapter.AwtCanvasAdapter;

public class RdpClient extends PipelineImpl {

    AwtMouseEventSource mouseEventSource = null;
    AwtKeyEventSource keyEventSource = null;

    /**
     * Name of last OneTimePacket in handshake sequence.
     */
    private static final String HANDSHAKE_END = "server_valid_client";

    /**
     * Create new RDP or HyperV cli
     *
     * @param id
     *          id of this element
     * @param userName
     *          user name
     * @param password
     *          password
     * @param pcb
     *          pre-connection blob for HyperV server or null/empty string to
     *          disable. Usually, HyperV VM ID, e.g.
     *          "39418F90-6D03-468E-B796-91C60DD6653A".
     * @param screen
     *          screen description to fill
     * @param canvas
     *          canvas to draw on
     * @param sslState
     */
    public RdpClient(String id, String serverHostName, String domain, String userName, String password, String pcb, ScreenDescription screen,
            BufferedImageCanvas canvas, SSLState sslState) {
        super(id);
        assembleRDPPipeline(serverHostName, domain, userName, password, pcb, screen, canvas, sslState);
    }

    /**
     * Assemble connection sequence and main pipeline.
     *
     * Connection sequence for RDP w/o NLA: cookie(TPKT) SSL x224(TPKT)
     * main(FastPath).
     *
     * Connection sequence for RDP w NLA: cookie(TPKT) SSL credssp x224(TPKT)
     * main(FastPath).
     *
     * Connection sequence for HyperV w NLA: pcb SSL credssp cookie(TPKT)
     * x224(TPKT) main(FastPath).
     */
    protected void assembleRDPPipeline(String serverHostName, String domain, String userName, String password, String pcb, ScreenDescription screen,
            BufferedImageCanvas canvas, SSLState sslState) {
        // If preconnection blob with VM ID is specified, then we are connecting to
        // HyperV server
        boolean hyperv = (pcb != null && !pcb.isEmpty());
        // HyperV server requires NLA (CredSSP/SPNEGO/NTLMSSP) to connect, because
        // it cannot display login screen
        boolean credssp = hyperv || (password != null && !password.isEmpty());

        String workstation;
        try {
            workstation = InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            workstation = "workstation";
        }

        //
        // Handshake chain
        //

        RdpState state = new RdpState();
        NtlmState ntlmState = new NtlmState();

        int[] channelsToJoin = new int[] {RdpConstants.CHANNEL_IO,
                // RdpConstants.CHANNEL_RDPRDR, // RDPRDR channel is not used in current
                // version

                // RdpConstants .CHANNEL_CLIPRDR // Clipboard channel is refused to join :-/
        };

        // Add elements

        // If pre-connection blob is specified, then add element to send it as
        // first packet
        if (hyperv) {
            add(new ClientPreConnectionBlob("pcb", pcb));
        }

        // If password is specified, then use CredSSP/NTLM (NTLMSSP)
        int protocol = RdpConstants.RDP_NEG_REQ_PROTOCOL_SSL;
        if (credssp) {
            protocol = RdpConstants.RDP_NEG_REQ_PROTOCOL_HYBRID;

            add(
                    new ClientNtlmsspNegotiate("client_ntlmssp_nego", ntlmState),

                    new ServerNtlmsspChallenge("server_ntlmssp_challenge", ntlmState),

                    new ClientNtlmsspPubKeyAuth("client_ntlmssp_auth", ntlmState, sslState, serverHostName, domain, workstation, userName, password),

                    new ServerNtlmsspPubKeyPlus1("server_ntlmssp_confirm", ntlmState),

                    new ClientNtlmsspUserCredentials("client_ntlmssp_finish", ntlmState)

                    );
        }

        add(new ClientX224ConnectionRequestPDU("client_connection_req", userName, protocol), new ServerX224ConnectionConfirmPDU("server_connection_conf"),
                new UpgradeSocketToSSL("upgrade_to_ssl"),

                new ClientMCSConnectInitial("client_initial_conference_create"), new ServerMCSConnectResponse("server_initial_conference_create"),

                new ClientMCSErectDomainRequest("client_erect_domain"),

                new ClientMCSAttachUserRequest("client_atach_user"), new ServerMCSAttachUserConfirmPDU("server_atach_user_confirm", state),

                new ClientMCSChannelJoinRequestServerMCSChannelConfirmPDUs("client_channel_join_rdprdr", channelsToJoin, state),

                new ClientInfoPDU("client_info_req", userName),

                new ServerLicenseErrorPDUValidClient("server_valid_client"),

                new ServerFastPath("server_fastpath"),

                // new ServerTpkt("server_tpkt"),

                new ServerX224DataPdu("server_x224_data"),

                // These TPKT and X224 wrappers are connected directly to OUT for
                // handshake sequence
                new ClientTpkt("client_tpkt_ot"),

                new ClientX224DataPDU("client_x224_data_ot")

                );

        // If HyperV VM ID is set, then insert element which will send VM ID as
        // first packet of connection, before other packets
        if (hyperv) {

            // HyperV: pcb SSL credssp cookie x224 main.

            link("IN",

                    // Pre Connection Blob
                    "pcb",

                    // Main (will be used after connection seq) or tpkt (to X224)
                    "server_fastpath >tpkt",

                    // SSL
                    "upgrade_to_ssl",

                    // CredSSP
                    "client_ntlmssp_nego", "server_ntlmssp_challenge", "client_ntlmssp_auth", "server_ntlmssp_confirm", "client_ntlmssp_finish",

                    // Cookie
                    "client_connection_req", "server_connection_conf",

                    // X224
                    "client_initial_conference_create");

            for (String element : new String[] {"pcb", "client_ntlmssp_nego", "server_ntlmssp_challenge", "client_ntlmssp_auth", "server_ntlmssp_confirm",
            "client_ntlmssp_finish"}) {
                link(element + " >otout", element + "< OUT");

            }

        } else {

            // RDP: cookie SSL (credssp) x224 main.

            link("IN",

                    // Main or tpkt
                    "server_fastpath >tpkt",

                    // Cookie
                    "client_connection_req", "server_connection_conf",

                    // SSL
                    "upgrade_to_ssl");

            if (credssp) {
                // SSL
                link("upgrade_to_ssl",

                        // CredSSP
                        "client_ntlmssp_nego", "server_ntlmssp_challenge", "client_ntlmssp_auth", "server_ntlmssp_confirm", "client_ntlmssp_finish",

                        // X224
                        "client_initial_conference_create");

                for (String element : new String[] {"client_ntlmssp_nego", "server_ntlmssp_challenge", "client_ntlmssp_auth", "server_ntlmssp_confirm",
                "client_ntlmssp_finish"}) {
                    link(element + " >otout", element + "< OUT");

                }

            } else {

                link(
                        // SSL
                        "upgrade_to_ssl",

                        // X224
                        "client_initial_conference_create");
            }
        }

        link(
                // X224
                "client_initial_conference_create", "server_initial_conference_create",

                "client_erect_domain",

                "server_x224_data",

                "client_atach_user", "server_atach_user_confirm",

                "client_channel_join_rdprdr",

                "client_info_req",

                "server_valid_client"

                );

        // Chain for direct handshake responses (without involving of queue)
        link("client_x224_data_ot", "client_tpkt_ot", "client_tpkt_ot< OUT");

        // Connect one time outputs to client TPKT input
        String tpkt_peers[] = new String[] {"client_connection_req", "server_connection_conf", "upgrade_to_ssl", "client_x224_data_ot"};
        for (String element : tpkt_peers) {
            link(element + " >otout", element + "< client_tpkt_ot");
        }

        // Connect one time outputs to client X224 input
        String x224_peers[] = new String[] {"client_initial_conference_create", "server_initial_conference_create", "client_erect_domain", "client_atach_user",
                "server_atach_user_confirm", "client_channel_join_rdprdr", "client_info_req", "server_valid_client"};
        for (String element : x224_peers) {
            link(element + " >otout", element + "< client_x224_data_ot");
        }

        //
        // Transition
        //

        add(
                // To transfer packets between input threads and output thread.
                new Queue("queue"),

                // Slow path: MultiChannel Support
                new ServerMCSPDU("server_mcs")

                );

        // Last element of handshake sequence will wake up queue and socket
        // output pull loop, which will switch links, between socket output and
        // queue, from push mode to pull mode.
        link(HANDSHAKE_END + " >queue", "queue", "OUT");

        // Transition from handshake sequence for slow path packets
        link(HANDSHAKE_END, "server_mcs");

        //
        // Main network
        //

        mouseEventSource = new AwtMouseEventSource("mouse");
        keyEventSource = new AwtKeyEventSource("keyboard");

        // Subscribe packet sender to various events
        canvas.addMouseListener(mouseEventSource);
        canvas.addMouseMotionListener(mouseEventSource);
        canvas.addKeyListener(keyEventSource);

        // Add elements
        add(

                new ServerIOChannelRouter("server_io_channel", state),

                new ServerDemandActivePDU("server_demand_active", screen, state),

                new ClientConfirmActivePDU("client_confirm_active", screen, state),

                new ServerBitmapUpdate("server_bitmap_update"),

                new AwtCanvasAdapter("canvas_adapter", canvas, screen),

                new ServerPaletteUpdate("server_palette", screen),

                keyEventSource, new AwtRdpKeyboardAdapter("keyboard_adapter"),

                mouseEventSource, new AwtRdpMouseAdapter("mouse_adapter"),

                // These FastPath, TPKT, and X224 wrappers are connected to queue
                new ClientTpkt("client_tpkt_queue"),

                new ClientX224DataPDU("client_x224_data_queue"),

                new ClientFastPathPDU("client_fastpath_queue"));

        // Server packet handlers
        link("server_mcs >channel_1003", "server_io_channel");
        link("server_fastpath >bitmap", "fastpath< server_bitmap_update", "server_bitmap_update< canvas_adapter");
        link("server_io_channel >bitmap", "slowpath< server_bitmap_update");

        link("server_fastpath >palette", "fastpath< server_palette");
        link("server_io_channel >palette", "slowpath< server_palette");

        link("server_io_channel >demand_active", "slowpath< server_demand_active");
        // link("server_demand_active >confirm_active", "client_confirm_active",
        // "confirm_active< client_channel_1003");
        link("server_demand_active >confirm_active", "client_confirm_active", "confirm_active< client_x224_data_queue");

        // Link mouse and keyboard to socket via adapters and send them using
        // FastPath protocol
        link(mouseEventSource.getId(), "mouse_adapter", "mouse_adapter< client_fastpath_queue");
        link(keyEventSource.getId(), "keyboard_adapter", "keyboard_adapter< client_fastpath_queue");

        // Link packet wrappers to outgoing queue
        link("client_fastpath_queue", "client_fastpath_queue< queue");
        link("client_x224_data_queue", "client_tpkt_queue", "client_tpkt_queue< queue");

    }

    public AwtMouseEventSource getMouseEventSource() {
        return mouseEventSource;
    }

    public AwtKeyEventSource getKeyEventSource() {
        return keyEventSource;
    }
}
