# achat - reliable point-to-point chat over /net/aether
#
# A tiny rc front-end to the Æther reliable-datagram interface.  Unlike the
# built-in `chat` (best-effort LoRa broadcast), this is a reliable, ordered
# conversation with one peer, carried by the /net/aether 9P server.
#
# Because rc is single-threaded, sending and receiving run in two shells:
#
#   achat <peer>      talk to <peer>: a mesh addr (aa:bb or full 6-byte)
#                     or a node name learned from beacons (see `who` /
#                     /net/aether/peers; ambiguous names are refused).
#                     Type a line + Enter to send it; Ctrl-D to quit.
#                     Prints the conversation number N.
#   achat -r <N>      in a second shell: watch conversation N — incoming
#                     messages print as they arrive (Ctrl-C to stop).
#   achat -l          listen-only: open + announce a fresh conversation and
#                     watch it for datagrams from ANY peer (source-prefixed).
#                     Use this to receive without starting a talk session.
#
# Example, chatting from this deck (peer's address is bb:cc):
#   shell 1>  achat bb:cc          ... "conversation 0"
#   shell 2>  achat -r 0
#
# Needs /net/aether present: the LoRa mesh on a deck, or — for testing on
# native_sim — the host mock wired in over 9P (no radio):
#   host>  make -C tools/mock_aether && ./tools/mock_aether/mock_aether 5640
#   sim >  srv tcp!127.0.0.1!5640 aeth
#          mount /srv/aeth /n/aeth
#          bind  /n/aeth/net/aether /net/aether   # keeps /net/tcp intact

# --- receive mode -------------------------------------------------
# Kept flat (no nested if) on purpose: when this script is sourced, a nested
# if/{} inside this block mis-fires.  cat reports a bad conversation itself.
if (~ $1 -r) {
    echo 'achat: watching conversation '$2' - Ctrl-C to stop'
    cat /net/aether/$2/data
    exit 0
}

# --- listen mode (any peer) ---------------------------------------
# Open a fresh conversation, announce it, and watch.  Unlike -r <N>, this
# sets the conversation up itself, so you can receive without starting a
# talk session first.  Incoming datagrams are prefixed with the 6-byte
# sender address.  Kept flat (no nested if) for the sourced .-fold.
if (~ $1 -l) {
    n=`{cat /net/aether/clone}
    echo announce >/net/aether/$n/ctl
    echo 'achat: listening on conversation '$n' for any peer - Ctrl-C to stop'
    cat /net/aether/$n/data
    exit 0
}

# --- talk mode ----------------------------------------------------
if (~ $#1 0) {
    echo 'usage: achat <peer>         (talk; addr or name from `who`)'
    echo '       achat -r <number>    (watch, in another shell)'
    echo '       achat -l             (listen for any peer)'
    exit 1
}

peer=$1
if (test ! -e /net/aether/clone) {
    echo 'achat: /net/aether not available - is the LoRa mesh up?'
    exit 1
}
n=`{cat /net/aether/clone}
if (~ $n '') {
    echo 'achat: could not open a conversation'
    exit 1
}

echo 'connect '$peer >/net/aether/$n/ctl
echo 'Chatting with '$peer' on conversation '$n'.'
echo 'Watch replies in another shell:  achat -r '$n
echo 'Type a message and press Enter; Ctrl-D to quit.'

# Each console line becomes one reliable datagram.  read returns non-zero
# on Ctrl-D (EOF), ending the loop.
while (read line) {
    echo $line >/net/aether/$n/data
}

echo hangup >/net/aether/$n/ctl
echo 'Chat closed.'
