+## WITH_3TRIPES(adir, bdir, cdir, allargs, aargs, bargs, cargs, body)
+m4_define([WITH_3TRIPES],
+ [WITH_TRIPEX([$1], [$4 $5],
+ [WITH_TRIPEX([$2], [$4 $6],
+ [WITH_TRIPEX([$3], [$4 $7],
+ [$8])])])])
+
+## RETRY(n, body)
+m4_define([RETRY], [
+ n=0 rc=1
+ while test $n -lt $1; do
+ if $2
+ then rc=0; break
+ fi
+ n=$(( $n + 1 ))
+ done
+ exit $rc
+])
+
+## COMMS_EPING(adir, aname, bdir, bname, [n])
+m4_define([COMMS_EPING], [
+ AT_CHECK([RETRY([m4_default([$5], [1])],
+ [TRIPECTL -d$1 EPING $4])],, [ignore])
+ AT_CHECK([RETRY([m4_default([$5], [1])],
+ [TRIPECTL -d$3 EPING $2])],, [ignore])
+])
+
+## COMMS_SLIP(adir, aname, bdir, bname)
+m4_define([COMMS_SLIP], [
+ AT_CHECK([echo "from $1" | USLIP -p $1/$4])
+ AT_CHECK([USLIP -g $3/$2],, [from $1[]nl])
+ AT_CHECK([echo "from $3" | USLIP -p $3/$2])
+ AT_CHECK([USLIP -g $1/$4],, [from $3[]nl])
+])
+
+## AWAIT_KXDONE(adir, aname, bdir, bname, body)
+m4_define([AWAIT_KXDONE], [
+
+ ## Ignore some reports caused by races.
+ for i in $1!$4 $3!$2; do
+ d=${i%!*} o=${i#*!}
+ TRIPECTL -d$d WARN test PUSH
+ TRIPECTL -d$d WARN test IGNORE WARN KX $o incorrect cookie
+ TRIPECTL -d$d WARN test IGNORE WARN KX $o unexpected pre-challenge
+ TRIPECTL -d$d WARN test IGNORE WARN KX $o unexpected challenge
+ done
+
+ ## Watch for the key-exchange completion announcement in the background.
+ COPROCESSES([wait-$1], [
+ echo WATCH +n
+ while read line; do
+ set x $line; shift
+ echo >&2 ">>> $line"
+ case "$[]1:$[]2:$[]3" in
+ OK::) ;;
+ NOTE:KXDONE:$4) break ;;
+ NOTE:* | TRACE:* | WARN:*) ;;
+ *) exit 63 ;;
+ esac
+ done
+ ], [
+ TRIPECTL -d$1
+ ]) & waiter_$1=$!
+
+ $5
+
+ ## Collect the completion announcement.
+ wait $waiter_$1; waitrc=$?
+ AT_CHECK([echo $waitrc],, [0[]nl])
+
+ ## Be interested in key-exchange warnings again.
+ for d in $1 $3; do TRIPECTL -d$d WARN test POP; done
+])
+
+## ESTABLISH(adir, aname, aopts, bdir, bname, bopts, [aport], [bport])
+m4_define([ESTABLISH], [
+
+ ## Set up the establishment.
+ AWAIT_KXDONE([$1], [$2], [$4], [$5], [
+ AT_CHECK([TRIPECTL -d$1 ADD -cork $6 $5 INET 127.0.0.1 \
+ m4_if([$8], [], [$(cat $4/port)], [$8])])
+ AT_CHECK([TRIPECTL -d$4 ADD $3 $2 INET 127.0.0.1 \
+ m4_if([$7], [], [$(cat $1/port)], [$7])])
+ ])
+
+ ## Check transport pinging.
+ AT_CHECK([TRIPECTL -d$1 PING $5],, [ignore])
+ AT_CHECK([TRIPECTL -d$4 PING $2],, [ignore])
+
+ ## Check communication works.
+ COMMS_EPING([$1], [$2], [$4], [$5])
+ COMMS_SLIP([$1], [$2], [$4], [$5])
+])
+