package services import ( "git.saqut.com/saqut/mwse/internal/protocol" "git.saqut.com/saqut/mwse/internal/ws" ) // handshakeResult returns the optional acknowledgement for a relay handler. When // the caller did not ask for a handshake the relay is fire-and-forget (nil), so // the generic dispatcher sends no reply. func handshakeResult(m protocol.Message, success bool) any { if !m.Truthy("handshake") { return nil } if success { return map[string]any{"type": "success"} } return map[string]any{"type": "fail"} } func registerDataTransfer(hub *ws.Hub) { // pack/to: relay a data pack to another peer, honouring both peers' relay // flags and the target's pairing policy. When the target does not require // pairing, an implicit pairing is established so subsequent traffic flows. hub.Register("pack/to", func(c *ws.Client, m protocol.Message) any { if !c.PackReadable() { return handshakeResult(m, false) } to := m.Str("to") other, ok := hub.Client(to) if !ok { return handshakeResult(m, false) } if other.RequiredPair() { if !other.HasPair(c.ID) { return handshakeResult(m, false) } } else if !other.HasPair(c.ID) { other.AddPair(c.ID) c.AddPair(other.ID) } if !other.PackWriteable() { return handshakeResult(m, false) } other.Signal("pack", map[string]any{"from": c.ID, "pack": m.Get("pack")}) return handshakeResult(m, true) }) // request/to: relay a request to a peer. The reply travels back later via // response/to, carrying the original request id, so this handler itself does // not produce the answer. hub.Register("request/to", func(c *ws.Client, m protocol.Message) any { other, ok := hub.Client(m.Str("to")) if !ok { return nil } if other.RequiredPair() { if !other.HasPair(c.ID) { return nil } } else { other.AddPair(c.ID) c.AddPair(other.ID) } other.Signal("request", map[string]any{"from": c.ID, "pack": m.Get("pack")}) return nil }) // response/to: deliver a peer's response back to the original requester. The // frame uses the numeric request id in the signal slot so the requester's // event pool resolves the pending promise. hub.Register("response/to", func(c *ws.Client, m protocol.Message) any { other, ok := hub.Client(m.Str("to")) if !ok { return nil } if other.RequiredPair() && !other.HasPair(c.ID) { return nil } other.Send([]any{map[string]any{"from": c.ID, "pack": m.Get("pack")}, m.Get("id")}) return nil }) // pack/room: relay a data pack to every writable member of a room the sender // belongs to. "wom" (without me) excludes the sender. hub.Register("pack/room", func(c *ws.Client, m protocol.Message) any { if !c.PackReadable() { return handshakeResult(m, false) } to := m.Str("to") room, ok := hub.Room(to) if !ok { return handshakeResult(m, false) } if !c.InRoom(to) { return handshakeResult(m, false) } except := "" if m.Truthy("wom") { except = c.ID } room.Broadcast( "pack/room", map[string]any{"from": to, "pack": m.Get("pack"), "sender": c.ID}, except, (*ws.Client).PackWriteable, ) return handshakeResult(m, true) }) }