# TCP client for the xinetd suite. busybox nc on this image is the MINIMAL applet # (usage is literally "nc [IPADDR PORT]") -- no -w, so a server that holds the # connection open hangs the suite with no way to bound it. tcl's socket + a # bounded [after] gives a real timeout and, just as importantly, lets a case # distinguish "connected and got nothing" (an access-control denial, which is a # clean accept-then-close) from "could not connect at all". # # argv: [timeout-ms] # prints exactly one line: # RESULT connfail -- connect() failed # RESULT ok len= body=[...] -- connected; body has CR/LF made visible proc onread {s} { if {[eof $s]} { set ::done 1; return } append ::buf [read $s] } set port [lindex $argv 0] set payload [lindex $argv 1] set ms [lindex $argv 2] if {$ms eq ""} { set ms 3000 } if {[catch {set s [socket 127.0.0.1 $port]} err]} { puts "RESULT connfail $err" exit 0 } fconfigure $s -translation binary -blocking 0 -buffering none set ::buf "" set ::done 0 fileevent $s readable [list onread $s] if {$payload ne ""} { puts -nonewline $s $payload; flush $s } set t [after $ms {set ::done 1}] vwait ::done after cancel $t catch {close $s} puts "RESULT ok len=[string length $::buf] body=\[[string map {"\r" "" "\n" ""} $::buf]\]"