fix websocket messaging, renamed http functions, start sending message via http
This commit is contained in:
@@ -87,7 +87,7 @@ func HttpHandleNewUser(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpHandleLogin(response http.ResponseWriter, request *http.Request) {
|
func HttpHandleNewToken(response http.ResponseWriter, request *http.Request) {
|
||||||
if !isMethodAllowed(&response, request) {
|
if !isMethodAllowed(&response, request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ func HttpHandleLogin(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpHandleGroupCreate(response http.ResponseWriter, request *http.Request) {
|
func HttpHandeNewGroup(response http.ResponseWriter, request *http.Request) {
|
||||||
if !isMethodAllowed(&response, request) {
|
if !isMethodAllowed(&response, request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,11 @@ func HttpHandleGroupCreate(response http.ResponseWriter, request *http.Request)
|
|||||||
binary.BigEndian.PutUint32(groupIdBytes, group.Id)
|
binary.BigEndian.PutUint32(groupIdBytes, group.Id)
|
||||||
|
|
||||||
response.WriteHeader(http.StatusCreated)
|
response.WriteHeader(http.StatusCreated)
|
||||||
response.Write(groupIdBytes)
|
_, err = response.Write(groupIdBytes)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpHandleGroupAddClient(response http.ResponseWriter, request *http.Request) {
|
func HttpHandleGroupAddClient(response http.ResponseWriter, request *http.Request) {
|
||||||
@@ -288,3 +292,27 @@ func HttpHandleGroupAddClient(response http.ResponseWriter, request *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HttpHandleNewMessage(response http.ResponseWriter, request *http.Request) {
|
||||||
|
token := request.FormValue("token")
|
||||||
|
if token == "" {
|
||||||
|
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject := request.FormValue("subject")
|
||||||
|
if subject == "" {
|
||||||
|
http.Error(response, "invalid subject", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
content := request.FormValue("content")
|
||||||
|
if content == "" {
|
||||||
|
http.Error(response, "invalid content", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientId, err := TokenValidateGetId(token)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ func main() {
|
|||||||
DbInit(ctx)
|
DbInit(ctx)
|
||||||
|
|
||||||
http.HandleFunc("/new/client", withCORS(HttpHandleNewUser))
|
http.HandleFunc("/new/client", withCORS(HttpHandleNewUser))
|
||||||
http.HandleFunc("/new/token", withCORS(HttpHandleLogin))
|
http.HandleFunc("/new/token", withCORS(HttpHandleNewToken))
|
||||||
http.HandleFunc("/new/group", withCORS(HttpHandleGroupCreate))
|
http.HandleFunc("/new/group", withCORS(HttpHandeNewGroup))
|
||||||
http.HandleFunc("/mod/group/addclients", withCORS(HttpHandleGroupAddClient))
|
http.HandleFunc("/mod/group/addclients", withCORS(HttpHandleGroupAddClient))
|
||||||
http.HandleFunc("/ws", ServeWsConnection)
|
http.HandleFunc("/ws", ServeWsConnection)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
TOKEN1=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzc0ODYzMTYxLCJpYXQiOjE3NzQ4NTk1NjF9.Xc2AdvB-OppMH_Xbudlf7roy81mLJW_OkZwriVP6tck
|
TOKEN1=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzc0ODY2MjE2LCJpYXQiOjE3NzQ4NjI2MTZ9.hxU-qpJ1Grz4yglr5TD_7ik5cIOU7_fkaIskoNdML0I
|
||||||
USER1_ID=1
|
USER1_ID=1
|
||||||
TOKEN2=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyIiwiZXhwIjoxNzc0ODYzMTYxLCJpYXQiOjE3NzQ4NTk1NjF9.EOY84pt8UUrIsGWAVgVUDUJdGxdll6Db-lFFKw4HeA4
|
TOKEN2=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyIiwiZXhwIjoxNzc0ODY2MjE3LCJpYXQiOjE3NzQ4NjI2MTd9.trOFcMUeFNrR2H9VlaM9vDYaupZq_ysGzCb1iz3Gxc0
|
||||||
USER2_ID=2
|
USER2_ID=2
|
||||||
GROUP_ID=1
|
GROUP_ID=1
|
||||||
|
|||||||
+64
-54
@@ -1,68 +1,78 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Send a message on the group via WebSocket (requires websocat)
|
# Send message from user_one to the group, verify user_two receives it
|
||||||
source "$(dirname "$0")/config.sh"
|
source "$(dirname "$0")/config.sh"
|
||||||
|
|
||||||
TOKEN1=$(load_state "TOKEN1")
|
TOKEN1=$(load_state "TOKEN1")
|
||||||
|
TOKEN2=$(load_state "TOKEN2")
|
||||||
GROUP_ID=$(load_state "GROUP_ID")
|
GROUP_ID=$(load_state "GROUP_ID")
|
||||||
|
|
||||||
echo "=== Debug: loaded state ==="
|
if [[ -z "$TOKEN1" || -z "$TOKEN2" || -z "$GROUP_ID" ]]; then
|
||||||
echo " TOKEN1: ${TOKEN1:0:20}..."
|
|
||||||
echo " GROUP_ID: $GROUP_ID"
|
|
||||||
|
|
||||||
if [[ -z "$TOKEN1" || -z "$GROUP_ID" ]]; then
|
|
||||||
echo "ERROR: Missing state. Run previous scripts first."
|
echo "ERROR: Missing state. Run previous scripts first."
|
||||||
|
echo " TOKEN1=$TOKEN1"
|
||||||
|
echo " TOKEN2=$TOKEN2"
|
||||||
|
echo " GROUP_ID=$GROUP_ID"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v websocat &>/dev/null; then
|
MESSAGE="Hello from user_one!"
|
||||||
echo "ERROR: websocat is not installed."
|
|
||||||
echo "Install it with: cargo install websocat"
|
echo "=== Sending message from user_one to group $GROUP_ID ==="
|
||||||
echo " or: pacman -S websocat"
|
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
|
echo "[DEBUG] tmpdir: $TMPDIR"
|
||||||
|
echo "[DEBUG] TOKEN1: ${TOKEN1:0:20}..."
|
||||||
|
echo "[DEBUG] TOKEN2: ${TOKEN2:0:20}..."
|
||||||
|
echo "[DEBUG] GROUP_ID: $GROUP_ID"
|
||||||
|
|
||||||
|
# Receiver (user_two): authenticate then wait for messages
|
||||||
|
echo "[DEBUG] starting receiver (user_two)..."
|
||||||
|
{ echo '{"token":"'"$TOKEN2"'"}'; sleep 5; } \
|
||||||
|
| stdbuf -oL websocat ws://localhost:8080/ws > "$TMPDIR/received" 2>"$TMPDIR/recv_err" &
|
||||||
|
RECV_PID=$!
|
||||||
|
echo "[DEBUG] receiver PID: $RECV_PID"
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
# Sender (user_one): authenticate, send message
|
||||||
|
SEND_PAYLOAD='{"subject":'"$GROUP_ID"',"content":"'"$MESSAGE"'"}'
|
||||||
|
echo "[DEBUG] starting sender (user_one)..."
|
||||||
|
echo "[DEBUG] send payload: $SEND_PAYLOAD"
|
||||||
|
{ echo '{"token":"'"$TOKEN1"'"}'; sleep 0.5; echo "$SEND_PAYLOAD"; sleep 0.5; } \
|
||||||
|
| websocat ws://localhost:8080/ws > "$TMPDIR/send_out" 2>"$TMPDIR/send_err" &
|
||||||
|
SEND_PID=$!
|
||||||
|
echo "[DEBUG] sender PID: $SEND_PID"
|
||||||
|
|
||||||
|
echo "[DEBUG] waiting 2s for message delivery..."
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
echo "[DEBUG] killing connections..."
|
||||||
|
kill $RECV_PID $SEND_PID 2>/dev/null
|
||||||
|
wait $RECV_PID 2>/dev/null
|
||||||
|
RECV_EXIT=$?
|
||||||
|
wait $SEND_PID 2>/dev/null
|
||||||
|
SEND_EXIT=$?
|
||||||
|
echo "[DEBUG] receiver exit: $RECV_EXIT, sender exit: $SEND_EXIT"
|
||||||
|
|
||||||
|
RECV_ERR=$(cat "$TMPDIR/recv_err")
|
||||||
|
SEND_ERR=$(cat "$TMPDIR/send_err")
|
||||||
|
SEND_OUT=$(cat "$TMPDIR/send_out")
|
||||||
|
[[ -n "$RECV_ERR" ]] && echo "[DEBUG] receiver stderr: $RECV_ERR"
|
||||||
|
[[ -n "$SEND_ERR" ]] && echo "[DEBUG] sender stderr: $SEND_ERR"
|
||||||
|
[[ -n "$SEND_OUT" ]] && echo "[DEBUG] sender received: $SEND_OUT"
|
||||||
|
|
||||||
|
RESPONSE=$(cat "$TMPDIR/received")
|
||||||
|
echo "user_two received: $RESPONSE"
|
||||||
|
|
||||||
|
if [[ -z "$RESPONSE" ]]; then
|
||||||
|
echo "[DEBUG] EMPTY response - no data received by user_two"
|
||||||
|
echo "FAIL: message not received"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AUTH_MSG="{\"token\":\"$TOKEN1\"}"
|
if echo "$RESPONSE" | grep -q "$MESSAGE"; then
|
||||||
CHAT_MSG="{\"subject\":$GROUP_ID,\"content\":\"Hello from user1!\"}"
|
echo "PASS"
|
||||||
|
else
|
||||||
echo ""
|
echo "FAIL: message not received"
|
||||||
echo "=== Sending message to group $GROUP_ID as user1 ==="
|
exit 1
|
||||||
echo " Auth payload: $AUTH_MSG"
|
|
||||||
echo " Chat payload: $CHAT_MSG"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "[*] Connecting to ws://localhost:8080/ws ..."
|
|
||||||
|
|
||||||
# Use a temp file to capture all ws output
|
|
||||||
WS_OUT=$(mktemp)
|
|
||||||
trap "rm -f $WS_OUT" EXIT
|
|
||||||
|
|
||||||
(
|
|
||||||
echo "[>] Sending auth message..." >&2
|
|
||||||
echo "$AUTH_MSG"
|
|
||||||
sleep 2
|
|
||||||
echo "[>] Auth sent. Sending chat message..." >&2
|
|
||||||
echo "$CHAT_MSG"
|
|
||||||
sleep 2
|
|
||||||
echo "[>] Chat message sent. Closing..." >&2
|
|
||||||
) | websocat -v ws://localhost:8080/ws 2>&1 | tee "$WS_OUT" &
|
|
||||||
|
|
||||||
WS_PID=$!
|
|
||||||
|
|
||||||
# Wait for websocat to finish or timeout after 10s
|
|
||||||
WAITED=0
|
|
||||||
while kill -0 $WS_PID 2>/dev/null && [[ $WAITED -lt 10 ]]; do
|
|
||||||
sleep 1
|
|
||||||
WAITED=$((WAITED + 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
if kill -0 $WS_PID 2>/dev/null; then
|
|
||||||
echo "[!] websocat still running after ${WAITED}s, killing..."
|
|
||||||
kill $WS_PID 2>/dev/null
|
|
||||||
wait $WS_PID 2>/dev/null
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== WebSocket output ==="
|
|
||||||
cat "$WS_OUT"
|
|
||||||
echo ""
|
|
||||||
echo "=== Done ==="
|
|
||||||
|
|||||||
Executable
+78
@@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Send message from user_two to the group, verify user_one receives it
|
||||||
|
source "$(dirname "$0")/config.sh"
|
||||||
|
|
||||||
|
TOKEN1=$(load_state "TOKEN1")
|
||||||
|
TOKEN2=$(load_state "TOKEN2")
|
||||||
|
GROUP_ID=$(load_state "GROUP_ID")
|
||||||
|
|
||||||
|
if [[ -z "$TOKEN1" || -z "$TOKEN2" || -z "$GROUP_ID" ]]; then
|
||||||
|
echo "ERROR: Missing state. Run previous scripts first."
|
||||||
|
echo " TOKEN1=$TOKEN1"
|
||||||
|
echo " TOKEN2=$TOKEN2"
|
||||||
|
echo " GROUP_ID=$GROUP_ID"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MESSAGE="Hello from user_two!"
|
||||||
|
|
||||||
|
echo "=== Sending message from user_two to group $GROUP_ID ==="
|
||||||
|
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
|
echo "[DEBUG] tmpdir: $TMPDIR"
|
||||||
|
echo "[DEBUG] TOKEN1: ${TOKEN1:0:20}..."
|
||||||
|
echo "[DEBUG] TOKEN2: ${TOKEN2:0:20}..."
|
||||||
|
echo "[DEBUG] GROUP_ID: $GROUP_ID"
|
||||||
|
|
||||||
|
# Receiver (user_one): authenticate then wait for messages
|
||||||
|
echo "[DEBUG] starting receiver (user_one)..."
|
||||||
|
{ echo '{"token":"'"$TOKEN1"'"}'; sleep 5; } \
|
||||||
|
| stdbuf -oL websocat ws://localhost:8080/ws > "$TMPDIR/received" 2>"$TMPDIR/recv_err" &
|
||||||
|
RECV_PID=$!
|
||||||
|
echo "[DEBUG] receiver PID: $RECV_PID"
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
# Sender (user_two): authenticate, send message
|
||||||
|
SEND_PAYLOAD='{"subject":'"$GROUP_ID"',"content":"'"$MESSAGE"'"}'
|
||||||
|
echo "[DEBUG] starting sender (user_two)..."
|
||||||
|
echo "[DEBUG] send payload: $SEND_PAYLOAD"
|
||||||
|
{ echo '{"token":"'"$TOKEN2"'"}'; sleep 0.5; echo "$SEND_PAYLOAD"; sleep 0.5; } \
|
||||||
|
| websocat ws://localhost:8080/ws > "$TMPDIR/send_out" 2>"$TMPDIR/send_err" &
|
||||||
|
SEND_PID=$!
|
||||||
|
echo "[DEBUG] sender PID: $SEND_PID"
|
||||||
|
|
||||||
|
echo "[DEBUG] waiting 2s for message delivery..."
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
echo "[DEBUG] killing connections..."
|
||||||
|
kill $RECV_PID $SEND_PID 2>/dev/null
|
||||||
|
wait $RECV_PID 2>/dev/null
|
||||||
|
RECV_EXIT=$?
|
||||||
|
wait $SEND_PID 2>/dev/null
|
||||||
|
SEND_EXIT=$?
|
||||||
|
echo "[DEBUG] receiver exit: $RECV_EXIT, sender exit: $SEND_EXIT"
|
||||||
|
|
||||||
|
RECV_ERR=$(cat "$TMPDIR/recv_err")
|
||||||
|
SEND_ERR=$(cat "$TMPDIR/send_err")
|
||||||
|
SEND_OUT=$(cat "$TMPDIR/send_out")
|
||||||
|
[[ -n "$RECV_ERR" ]] && echo "[DEBUG] receiver stderr: $RECV_ERR"
|
||||||
|
[[ -n "$SEND_ERR" ]] && echo "[DEBUG] sender stderr: $SEND_ERR"
|
||||||
|
[[ -n "$SEND_OUT" ]] && echo "[DEBUG] sender received: $SEND_OUT"
|
||||||
|
|
||||||
|
RESPONSE=$(cat "$TMPDIR/received")
|
||||||
|
echo "user_one received: $RESPONSE"
|
||||||
|
|
||||||
|
if [[ -z "$RESPONSE" ]]; then
|
||||||
|
echo "[DEBUG] EMPTY response - no data received by user_one"
|
||||||
|
echo "FAIL: message not received"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | grep -q "$MESSAGE"; then
|
||||||
|
echo "PASS"
|
||||||
|
else
|
||||||
|
echo "FAIL: message not received"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -37,6 +37,12 @@ echo "============================="
|
|||||||
bash "$DIR/05_send_message.sh"
|
bash "$DIR/05_send_message.sh"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
echo "============================="
|
||||||
|
echo " Step 6: Send message reverse"
|
||||||
|
echo "============================="
|
||||||
|
bash "$DIR/06_send_message_reverse.sh"
|
||||||
|
echo ""
|
||||||
|
|
||||||
echo "============================="
|
echo "============================="
|
||||||
echo " Cleanup"
|
echo " Cleanup"
|
||||||
echo "============================="
|
echo "============================="
|
||||||
|
|||||||
+17
-8
@@ -78,13 +78,15 @@ func sendToAllMessageCloseIfTimeout(message *map[string]any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleAuthenticatedMessage(client *Client, clientMessage *map[string]any) bool {
|
func handleAuthenticatedMessage(client *Client, clientMessage *map[string]any) bool {
|
||||||
subject, ok := (*clientMessage)["subject"].(uint32)
|
subjectFlt, ok := (*clientMessage)["subject"].(float64)
|
||||||
|
subject := uint32(subjectFlt)
|
||||||
if !ok {
|
if !ok {
|
||||||
var msg = map[string]any{
|
var msg = map[string]any{
|
||||||
"from": "server",
|
"from": "server",
|
||||||
"error": "subject invalid",
|
"error": "subject invalid",
|
||||||
}
|
}
|
||||||
sendMessageCloseIfTimeout(client, &msg)
|
sendMessageCloseIfTimeout(client, &msg)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
content, ok := (*clientMessage)["content"].(string)
|
content, ok := (*clientMessage)["content"].(string)
|
||||||
@@ -94,6 +96,7 @@ func handleAuthenticatedMessage(client *Client, clientMessage *map[string]any) b
|
|||||||
"error": "content invalid",
|
"error": "content invalid",
|
||||||
}
|
}
|
||||||
sendMessageCloseIfTimeout(client, &msg)
|
sendMessageCloseIfTimeout(client, &msg)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
group, err := CacheGetGroup(subject)
|
group, err := CacheGetGroup(subject)
|
||||||
@@ -103,23 +106,29 @@ func handleAuthenticatedMessage(client *Client, clientMessage *map[string]any) b
|
|||||||
"error": "subject invalid",
|
"error": "subject invalid",
|
||||||
}
|
}
|
||||||
sendMessageCloseIfTimeout(client, &msg)
|
sendMessageCloseIfTimeout(client, &msg)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
for groupClientId, _ := range group.Clients {
|
for groupClientId := range group.Clients {
|
||||||
|
groupClient, err := CacheGetClientById(groupClientId)
|
||||||
|
if err != nil || groupClient.Id == client.Id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var msg = map[string]any{
|
var msg = map[string]any{
|
||||||
"from": "group",
|
"from": "group",
|
||||||
"group": group.Id,
|
"group": group.Id,
|
||||||
"sender": client.Name,
|
"sender": client.Name,
|
||||||
"content": content,
|
"content": content,
|
||||||
}
|
}
|
||||||
|
sendMessageCloseIfTimeout(groupClient, &msg)
|
||||||
var groupClient *Client
|
|
||||||
groupClient, err = CacheGetClientById(groupClientId)
|
|
||||||
if err != nil {
|
|
||||||
sendMessageCloseIfTimeout(groupClient, &msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var msg = map[string]any{
|
||||||
|
"from": "server",
|
||||||
|
}
|
||||||
|
sendMessageCloseIfTimeout(client)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user