source [file dirname [info script]]/testing.tcl

needs constraint jim
needs cmd socket
needs cmd os.fork
needs cmd load_ssl_certs

# Note that we don't actually need to load certificates with load_ssl_certs
# since the openssl installation should generally automatically load
# root certs

# Let's set up a client and a server where the client
# simply echos everything back to the server

set s [socket stream.server 127.0.0.1:1443]
if {[os.fork] == 0} {
	# child
	set c [[socket stream 127.0.0.1:1443] ssl]
	$s close
	sleep 0.25
	$c readable {
		# when we read we need to also read any pending data,
		# otherwise readable won't retrigger
		set buf [$c read -pending]
		if {[string length $buf] == 0} {
			incr ssldone
			$c close
		} else {
			$c puts -nonewline $buf
		}
	}
	vwait ssldone
	exit 99
}

# Now set up the server
set certpath [file dirname [info script]]
set cs [[$s accept addr] ssl -server $certpath/certificate.pem $certpath/key.pem]
$s close
defer {
	$cs close
}

# At this point, $cs is the server connection to the client in the child process

test ssl-1.1 {puts/gets} {
	$cs puts hello
	$cs gets
} hello

test ssl-1.2 {puts/gets} {
	$cs puts -nonewline again
	lmap p [range 5] {
		set c [$cs read 1]
		set c
	}
} {a g a i n}

test ssl-2.1 {https to google.com, gets} -body {
	set c [[socket stream www.google.com:443] ssl]
	$c puts -nonewline "GET / HTTP/1.0\r\n\r\n"
	$c flush
	set lines {}
	while {[$c gets buf] >= 0} {
		lappend lines $buf
	}
	$c close
	join $lines \n
} -match glob -result {HTTP/1.0 200 OK*</html>}

test ssl-2.2 {https to google.com, read with cert verify} -body {
	# Note that in order to verify the cert, we need sni
	set c [[socket stream www.google.com:443] ssl -sni www.google.com]
	# Verify the cert (note that this does not check CN)
	$c verify
	$c puts -nonewline "GET / HTTP/1.0\r\n\r\n"
	$c flush
	set buf [$c read]
} -match glob -result {HTTP/1.0 200 OK*</html>}

test ssl-2.3 {ssl to google.com on port 80} -body {
	# Try to talk SSL to a non-SSL server
	set c [[socket stream www.google.com:80] ssl]
	$c puts -nonewline "GET / HTTP/1.0\r\n\r\n"
	$c flush
	set buf [$c read]
} -returnCodes error -match glob -result {error:*}

testreport
