Files
utun2/tools/chatcli.sh
T
evgeny 38c9f229bc stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
  add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
  exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
  etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
2026-08-07 00:48:27 +03:00

77 lines
2.7 KiB
Bash
Executable File

#!/bin/bash
# chatcli — headless chat CLI client for uTun
#
# Usage:
# chatcli [--host HOST] [--port PORT] <command> [args...]
#
# Commands:
# channels list channels
# members <ch_id> list members with full state
# messages <ch_id> [count] read last messages
# send <ch_id> <content_type> <text> send message
# invite <ch_id> create invite link
# connect <utun://...> join channel via invite link
# create <name> create new channel
# status show connection status
# listen subscribe to events (interactive)
# --help show this help
set -e
HOST="${CHATCLI_HOST:-127.0.0.1}"
PORT="${CHATCLI_PORT:-9999}"
ID=1
NC_TIMEOUT="${CHATCLI_TIMEOUT:-5}"
_send() {
local json="$1"
if command -v socat &>/dev/null; then
echo "$json" | socat -t "$NC_TIMEOUT" - TCP:"$HOST":"$PORT" 2>/dev/null || true
elif command -v nc &>/dev/null; then
if nc -h 2>&1 | grep -q '^BusyBox'; then
echo "$json" | nc "$HOST" "$PORT" 2>/dev/null || true
else
echo "$json" | nc -q "$NC_TIMEOUT" "$HOST" "$PORT" 2>/dev/null || true
fi
else
echo "ERROR: socat or nc required" >&2; exit 1
fi
}
_request() {
local cmd="$1" data="$2"
local json='{"id":'"$ID"',"cmd":"'"$cmd"'"'
if [ -n "$data" ]; then json="$json,$data"; fi
json="$json}"
_send "$json"
ID=$((ID + 1))
}
_show() { local json="$1"; echo "$json" | python3 -m json.tool 2>/dev/null || echo "$json"; }
case "${1:-}" in
channels) r=$(_request channels); _show "$r" ;;
members) r=$(_request members '"ch":"'"$2"'"'); _show "$r" ;;
messages|msgs)
cnt="${3:-20}"
r=$(_request messages '"ch":"'"$2"'","count":'"$cnt"','"offset":0'); _show "$r" ;;
send)
ct="${3:-text}"; text="$4"
r=$(_request send '"ch":"'"$2"'","content_type":"'"$ct"'","data":"'"$text"'"'); _show "$r" ;;
invite) r=$(_request invite '"ch":"'"$2"'"'); _show "$r" ;;
connect|join) r=$(_request connect '"link":"'"$2"'"'); _show "$r" ;;
create) r=$(_request create_channel '"name":"'"$2"'"'); _show "$r" ;;
status|stat) r=$(_request status); _show "$r" ;;
listen)
echo "Connecting to $HOST:$PORT (Ctrl+C to quit)..."
{
printf '{"id":1,"cmd":"subscribe","enable":1}\n'
cat
} | nc "$HOST" "$PORT"
;;
ping) r=$(_request ping); _show "$r" ;;
--help|help|-h|"")
head -20 "$0" | sed 's/^# //' | grep -v '^#'
;;
*) echo "Unknown command: $1"; echo "Use --help for usage" >&2; exit 1 ;;
esac