#
# \brief  Test for the SSH terminal
#

assert_spec x86

if {[have_spec linux]} {
	puts "Run script is not supported on this platform."
	exit 0
}

# Build
#


source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components

lappend build_components test/exec_terminal

build $build_components

create_boot_directory

import_from_depot [depot_user]/src/[base_src] \
                  [depot_user]/src/bash \
                  [depot_user]/src/coreutils-minimal \
                  [depot_user]/src/exec_terminal \
                  [depot_user]/src/init \
                  [depot_user]/src/ipxe_nic_drv \
                  [depot_user]/src/libc \
                  [depot_user]/src/openssl \
                  [depot_user]/src/libssh \
                  [depot_user]/src/platform_drv \
                  [depot_user]/src/posix \
                  [depot_user]/src/fs_rom \
                  [depot_user]/src/nic_router \
                  [depot_user]/src/rtc_drv \
                  [depot_user]/src/ssh_terminal \
                  [depot_user]/src/vfs \
                  [depot_user]/src/vfs_jitterentropy \
                  [depot_user]/src/vfs_lxip \
                  [depot_user]/src/vfs_pipe \
                  [depot_user]/src/vim-minimal \
                  [depot_user]/src/zlib

#
# Generate config
#

set config {
<config verbose="no">
	<parent-provides>
		<service name="CPU"/>
		<service name="IO_MEM"/>
		<service name="IO_PORT"/>
		<service name="IRQ"/>
		<service name="LOG"/>
		<service name="PD"/>
		<service name="RAM"/>
		<service name="RM"/>
		<service name="ROM"/>
	</parent-provides>

	<default caps="100"/>

	<start name="timer">
		<resource name="RAM" quantum="1M"/>
		<provides> <service name="Timer"/> </provides>
		<route>
			<any-service> <parent/> <any-child/> </any-service>
		</route>
	</start>

	<start name="nic_drv" caps="120">
		<binary name="ipxe_nic_drv"/>
		<resource name="RAM" quantum="8M"/>
		<route>
			<service name="Uplink"> <child name="nic_router"/> </service>
			<any-service> <parent/> <any-child/> </any-service>
		</route>
	</start>

	<start name="nic_router" caps="200">
		<resource name="RAM" quantum="10M"/>
		<provides>
			<service name="Nic"/>
			<service name="Uplink"/>
		</provides>
		<config verbose_domain_state="yes">

			<policy label_prefix="ssh_terminal" domain="downlink"/>
			<policy label_prefix="nic_drv"      domain="uplink"/>

			<domain name="uplink">

				<nat domain="downlink"
				     tcp-ports="16384"
				     udp-ports="16384"
				     icmp-ids="16384"/>

				<tcp-forward port="22" domain="downlink" to="10.0.3.2"/>

			</domain>

			<domain name="downlink" interface="10.0.3.1/24">

				<dhcp-server ip_first="10.0.3.2" ip_last="10.0.3.2" dns_config_from="uplink"/>

				<tcp dst="0.0.0.0/0"><permit-any domain="uplink" /></tcp>
				<udp dst="0.0.0.0/0"><permit-any domain="uplink" /></udp>
				<icmp dst="0.0.0.0/0" domain="uplink"/>

			</domain>

		</config>
		<route>
			<service name="Timer"> <child name="timer"/> </service>
			<service name="CPU"> <parent/> </service>
			<service name="LOG"> <parent/> </service>
			<service name="PD"> <parent/> </service>
			<service name="RM"> <parent/> </service>
			<service name="ROM"> <parent/> </service>
		</route>
	</start>

	<start name="rtc_drv">
		<resource name="RAM" quantum="1M"/>
		<provides> <service name="Rtc"/> </provides>
		<route>
			<any-service> <parent/> <any-child/> </any-service>
		</route>
	</start>

	<start name="ram_fs">
		<resource name="RAM" quantum="8M"/>
		<binary name="vfs"/>
		<provides> <service name="File_system"/> </provides>
		<config>
			<vfs> <ram/> </vfs>
			<default-policy root="/" writeable="yes"/>
		</config>
		<route>
			<any-service> <parent/> <any-child/> </any-service>
		</route>
	</start>

	<start name="ssh_terminal" caps="250">
		<resource name="RAM" quantum="32M"/>
		<provides> <service name="Terminal"/> </provides>

		<config port="22" allow_password="yes" show_password="yes" ed25519_key="/etc/ssh/ed25519_key">

			<policy label_prefix="dynamic" user="noux" password="xuon" multi_login="yes" request_terminal="yes"/>
			<policy label_prefix="always-running-noux" user="charlie" password="xuon"/>

			<libc stdout="/dev/log" stderr="/dev/log" socket="/socket" pipe="/pipe" rtc="/dev/rtc"/>

			<vfs>
				<dir name="dev">
					<log/>
					<jitterentropy name="random"/>
					<jitterentropy name="urandom"/>
					<inline name="rtc">2000-01-01 00:00</inline>
				</dir>
				<dir name="etc">
					<dir name="ssh">
						<rom name="ed25519_key"/>
					</dir>
				</dir>
				<dir name="socket"> <lxip dhcp="yes"/> </dir>
				<dir name="pipe"> <pipe/> </dir>
			</vfs>
		</config>
		<route>
			<service name="Nic"> <child name="nic_router"/> </service>
			<service name="Report"> <child name="report_rom"/> </service>
			<service name="Timer"> <child name="timer"/> </service>
			<service name="CPU"> <parent/> </service>
			<service name="LOG"> <parent/> </service>
			<service name="PD"> <parent/> </service>
			<service name="RM"> <parent/> </service>
			<service name="ROM"> <parent/> </service>
		</route>
	</start>

	<start name="report_rom" caps="100">
		<resource name="RAM" quantum="4M"/>
		<provides>
			<service name="Report"/>
			<service name="ROM"/>
		</provides>
		<config verbose="no">
			<policy label="exec_terminal -> exec_terminal.config" report="ssh_terminal -> request_terminal"/>
			<policy label="dynamic -> config" report="exec_terminal -> config"/>
		</config>
		<route>
			<service name="CPU"> <parent/> </service>
			<service name="LOG"> <parent/> </service>
			<service name="PD"> <parent/> </service>
			<service name="RM"> <parent/> </service>
			<service name="ROM"> <parent/> </service>
		</route>
	</start>

	<start name="exec_terminal" caps="100">
		<resource name="RAM" quantum="4M"/>
		<route>
			<service name="ROM" label="exec_terminal.config"> <child name="report_rom"/> </service>
			<service name="Report" label="config"> <child name="report_rom"/> </service>
			<service name="Timer"> <child name="timer"/> </service>
			<service name="CPU"> <parent/> </service>
			<service name="LOG"> <parent/> </service>
			<service name="PD"> <parent/> </service>
			<service name="RM"> <parent/> </service>
			<service name="ROM"> <parent/> </service>
		</route>
	</start>

	<start name="dynamic" caps="1000">
		<binary name="init"/>
		<resource name="RAM" quantum="80M"/>
		<route>
			<service name="File_system"> <child name="ram_fs"/> </service>
			<service name="ROM" label="config"> <child name="report_rom"/> </service>
			<service name="ROM" label_last="coreutils-minimal.tar"> <parent label="coreutils-minimal.tar"/> </service>
			<service name="ROM" label_last="vim-minimal.tar"> <parent label="vim-minimal.tar"/> </service>
			<service name="Terminal"> <child name="ssh_terminal"/> </service>
			<service name="Timer"> <child name="timer"/> </service>
			<service name="CPU"> <parent/> </service>
			<service name="LOG"> <parent/> </service>
			<service name="PD"> <parent/> </service>
			<service name="RM"> <parent/> </service>
			<service name="ROM"> <parent/> </service>
		</route>
	</start>
}

append_platform_drv_config

append config {
</config>}

install_config $config

#
# Generate a new host key
#
if {![file exists bin/ed25519_key]} {
	exec ssh-keygen -t ed25519 -f bin/ed25519_key -q -N ""
}

#
# Boot modules
#

# generic modules
set boot_modules {
	ed25519_key
	exec_terminal
}

# platform-specific modules
append_platform_drv_boot_modules

build_boot_image $boot_modules

#
# Execute test
#

append qemu_args     " -nographic "
append_qemu_nic_args "hostfwd=tcp::5555-:22"

set nic_router_match_string ".uplink. dynamic IP config. interface (\[0-9\]+\.\[0-9\]+\.\[0-9\]+\.\[0-9\]+).*\n"

if {[get_cmd_switch --autopilot]} {
	run_genode_until $nic_router_match_string 60
	set serial_id [output_spawn_id]

	if {[have_include "power_on/qemu"]} {
		set host "localhost"
		set port "5555"
	} else {
		regexp $nic_router_match_string $output all host
		set port "22"
	}
	# wait for ssh_terminal to come up
	run_genode_until "--- SSH terminal started ---.*\n" 15 $serial_id

	for {set index 0} {$index < 3} {incr index} {
		puts "test interactive channel"
		spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port
		set ssh_id $spawn_id
		run_genode_until {/bin/bash] Hello from Genode!.*\n} 15 $serial_id
		send -i $ssh_id "ls\r"
		run_genode_until "bin" 15 $ssh_id
		send -i $ssh_id "exit\r"
		run_genode_until "child \"init\" exited with exit value 0.*\n" 15 $serial_id

		puts "test exec channel echo"
		set echo_text "The quick brown fox jumps over the lazy dog"
		spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port echo "$echo_text"
		set ssh_id $spawn_id
		run_genode_until ".*$echo_text.*\n" 15 $ssh_id
		run_genode_until "child \"init\" exited with exit value 0.*\n" 15 $serial_id

		puts "test exec channel ls"
		spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port "ls"
		set ssh_id $spawn_id
		run_genode_until "bin" 15 $ssh_id
		run_genode_until "child \"init\" exited with exit value 0.*\n" 15 $serial_id

		puts "test exec channel with empty command will not hang"
		spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port " "
		set ssh_id $spawn_id
		run_genode_until "child \"init\" exited with exit value.*\n" 15 $serial_id
	}

	puts ""
	puts ""
} else {
	run_genode_until forever
}

exec rm bin/ed25519_key bin/ed25519_key.pub

# vi: set ft=tcl :