start_client() {
    local in="$TEMPDIR/client.in" out="$TEMPDIR/client.out"
    declare -a strace=()
    mkfifo -- "$in" "$out"
    if [ "${STRACE-n}" = "y" ]; then
        mkfifo -- "$TEMPDIR/client.strace"
        strace=( strace -Dqo "$TEMPDIR/client.strace" -I1 -ze trace="%net" -- )
    fi
    "${strace[@]}" $NC ${NETCAT_DGRAM:+-u} "$@" "127.0.0.1" $PORT <"$in" >"$out" {LISTEN_IN}>&- {LISTEN_OUT}<&- & CLIENT_PID=$!
    exec {CONNECT_IN}>"$in" {CONNECT_OUT}<"$out"
    rm -f -- "$in" "$out"
    if [ "${STRACE-n}" = "y" ]; then
        exec {STRACE_FD}<"$TEMPDIR/client.strace"
        rm -f -- "$TEMPDIR/client.strace"
    fi
}

for s in 0 1 3; do
#######################################################################
# server (-q0 is implies -N but also terminates in UDP)

PORT=$(random_port)
STRACE_LINGER="y" PIPES="y" netcat_listen ${NETCAT_DGRAM:+-u} -q$s "127.0.0.1" $PORT

# connect a client so the server isn't blocking on accept() -- for
# UDP we also need to send some text so the server connect()s
start_client
if [ -n "$NETCAT_DGRAM" ]; then
    greet server
fi

# closing server input yields a shutdown()
exec {LISTEN_IN}>&-
grep -m1 -qE '^shutdown\([0-9]+,\s*SHUT_WR\)\s*=\s*0$' <&$STRACE_FD

kill_and_wait $CLIENT_PID
wait $PID
exec {STRACE_FD}<&- {LISTEN_OUT}<&- {CONNECT_IN}>&- {CONNECT_OUT}<&-


#######################################################################
# client (-q0 is implies -N but also terminates in UDP)

PORT=$(random_port)
PIPES="y" netcat_listen ${NETCAT_DGRAM:+-u} "127.0.0.1" $PORT

STRACE="y" start_client -q$s
if [ -n "$NETCAT_DGRAM" ]; then
    greet server
fi

# closing client input yields a shutdown()
exec {CONNECT_IN}>&-
grep -m1 -qE '^shutdown\([0-9]+,\s*SHUT_WR\)\s*=\s*0$' <&$STRACE_FD

wait $CLIENT_PID
${NETCAT_DGRAM:+kill_and_}wait $PID
exec {STRACE_FD}<&- {LISTEN_OUT}<&- {CONNECT_IN}>&- {CONNECT_OUT}<&-

done;
# vim: set filetype=bash :
