Documentation
¶
Overview ¶
Package rrc implements the Reticulum Relay Chat protocol.
RRC is a real-time chat protocol built on top of Reticulum's encrypted link layer. It supports rooms, presence, nicknames, actions, pings, and resource transfers.
Index ¶
- Constants
- func DecodeEnvelope(data []byte) (map[any]any, error)
- func EncodeEnvelope(env map[any]any) ([]byte, error)
- func MakeEnvelope(msgType int, src, room, nick []byte, body any, mid []byte, ts int64) map[any]any
- func MentionRegex(nick string) string
- func MsgID() []byte
- func NowMs() int64
- type HubInfo
- type RRCHub
- func (h *RRCHub) AddRoom(room string)
- func (h *RRCHub) ClearMessages(room string)
- func (h *RRCHub) Connect(ts rns.Transport, dest *rns.Destination) error
- func (h *RRCHub) ConnectAsync()
- func (h *RRCHub) Disconnect()
- func (h *RRCHub) DisplayNameFor(peer []byte) string
- func (h *RRCHub) GetEffectiveNick() string
- func (h *RRCHub) GetHubName() string
- func (h *RRCHub) GetHubStatus() int
- func (h *RRCHub) GetMembers(room string) []string
- func (h *RRCHub) GetMessages(room string) []*RRCMessage
- func (h *RRCHub) HandleData(data []byte)
- func (h *RRCHub) JoinRoom(room string, silent bool)
- func (h *RRCHub) JoinedRoomList() []string
- func (h *RRCHub) MarkRead(room string)
- func (h *RRCHub) MentionRoomList() []string
- func (h *RRCHub) MessageRoomList() []string
- func (h *RRCHub) PartRoom(room string)
- func (h *RRCHub) RemoveRoom(room string)
- func (h *RRCHub) SendAction(room, text string) string
- func (h *RRCHub) SendCommand(text, room string) error
- func (h *RRCHub) SendMessage(room, text string) string
- func (h *RRCHub) SendPing(room string)
- func (h *RRCHub) SetAutoList(enabled, save bool)
- func (h *RRCHub) SetAutoReconnect(enabled, save bool)
- func (h *RRCHub) SetAutoWho(enabled, save bool)
- func (h *RRCHub) SetLink(link *rns.Link)
- func (h *RRCHub) SetNickOverride(nick string)
- func (h *RRCHub) SetOnLinkClosed(fn func())
- func (h *RRCHub) SetOnLinkEstablished(fn func())
- func (h *RRCHub) SetStatus(status int, text string)
- func (h *RRCHub) SetTransport(ts rns.Transport)
- func (h *RRCHub) UnreadRoomList() []string
- type RRCManager
- func (m *RRCManager) ActiveRoomFor(hub *RRCHub) string
- func (m *RRCManager) AddHub(hubHash []byte, destName, name string) *RRCHub
- func (m *RRCManager) EphemeralNotices() int
- func (m *RRCManager) FilterLoadedHistory() bool
- func (m *RRCManager) FindHub(hubHash []byte, destName string) *RRCHub
- func (m *RRCManager) GetNickname() string
- func (m *RRCManager) HasUnread() bool
- func (m *RRCManager) HistoryPerRoomCap() int
- func (m *RRCManager) HubsSnapshot() []*RRCHub
- func (m *RRCManager) Identity() *rns.Identity
- func (m *RRCManager) IsStopped() bool
- func (m *RRCManager) Load() error
- func (m *RRCManager) NotifyChange(hub *RRCHub)
- func (m *RRCManager) NotifyMessage(hub *RRCHub, msg *RRCMessage)
- func (m *RRCManager) OnWelcome(hub *RRCHub)
- func (m *RRCManager) RemoveHub(hub *RRCHub)
- func (m *RRCManager) Save() error
- func (m *RRCManager) SetActive(hub *RRCHub, room string)
- func (m *RRCManager) SetChangeCallback(fn func())
- func (m *RRCManager) SetHistoryConfig(perRoomCap int, filterLoaded bool, ephemeralSecs int)
- func (m *RRCManager) SetIdentity(id *rns.Identity)
- func (m *RRCManager) SetMessageCallback(fn func(hub *RRCHub, msg *RRCMessage))
- func (m *RRCManager) SetNickname(nick string)
- func (m *RRCManager) Shutdown()
- type RRCMessage
Constants ¶
const ( KeyVersion = 0 KeyType = 1 KeyMessageID = 2 KeyTimestamp = 3 KeySource = 4 KeyRoom = 5 KeyBody = 6 KeyNick = 7 )
Envelope keys for CBOR-encoded messages.
const ( TypeHello = 1 TypeWelcome = 2 TypeJoin = 10 TypeJoined = 11 TypePart = 12 TypeParted = 13 TypeMsg = 20 TypeNotice = 21 TypeAction = 22 TypePing = 30 TypePong = 31 TypeError = 40 TypeResourceEnvelope = 50 )
Message types.
const ( BHelloName = 0 // client name string ("nomadnet") BHelloVer = 1 // client version string ("0.1") BHelloCaps = 2 // capabilities dict )
Body sub-keys for HELLO messages.
const ( BWelcomeHub = 0 // hub name string BWelcomeVer = 1 // hub version string BWelcomeCaps = 2 // capabilities dict BWelcomeLimits = 3 // limits dict )
Body sub-keys for WELCOME messages.
const ( LMaxNickBytes = 0 LMaxRoomNameBytes = 1 LMaxMsgBodyBytes = 2 LMaxRoomsPerSession = 3 LRateLimitMsgsPerMinute = 4 )
Limit keys in WELCOME body.
const ( CapResourceEnvelope = 0 CapAction = 1 )
Capability flags.
const ( ResKeyID = 0 ResKeyKind = 1 ResKeySize = 2 ResKeySHA256 = 3 ResKeyEncoding = 4 )
Resource envelope body keys.
const ( ResKindNotice = "notice" ResKindMOTD = "motd" ResKindBlob = "blob" )
Resource kinds.
const ( DefaultDestName = "rrc.hub" DefaultMaxNickBytes = 32 DefaultMaxRoomBytes = 64 DefaultMaxMsgBytes = 350 DefaultMaxRooms = 32 DefaultRatePerMinute = 240 )
Default values.
const ( HKind = "k" HSrc = "s" HNick = "n" HText = "t" HTS = "ts" HMention = "m" )
History entry keys for persistence.
const ( StatusDisconnected = 0 StatusConnecting = 1 StatusConnected = 2 StatusFailed = 3 )
Hub connection status.
const ( CleanHistoryInterval = 5 // seconds between history cleanups NoticeTimeout = 600 // seconds before ephemeral notices expire )
Timing constants.
const RRCVersion = 1
Protocol version.
Variables ¶
This section is empty.
Functions ¶
func DecodeEnvelope ¶
DecodeEnvelope deserializes CBOR bytes to an envelope map.
func EncodeEnvelope ¶
EncodeEnvelope serializes an envelope map to CBOR bytes.
func MakeEnvelope ¶
MakeEnvelope constructs a CBOR-encodable envelope for the RRC protocol.
func MentionRegex ¶
MentionRegex returns a simple pattern for detecting @mentions. The actual implementation uses word-boundary-aware matching.
Types ¶
type HubInfo ¶
type HubInfo struct {
Hash []byte `cbor:"hash"`
DestName string `cbor:"dest_name"`
Name string `cbor:"name"`
Rooms []string `cbor:"rooms"`
PartedRooms []string `cbor:"parted_rooms"`
AutoReconnect bool `cbor:"auto_reconnect"`
AutoList bool `cbor:"auto_list"`
AutoWho bool `cbor:"auto_who"`
Nick string `cbor:"nick,omitempty"`
}
HubInfo holds the serialized state of a hub for persistence.
type RRCHub ¶
type RRCHub struct {
Manager *RRCManager
HubHash []byte // hub identity hash
DestName string // RNS destination name
Name string // display name
// Connection state
Status int
StatusText string
Welcomed bool
// Hub-reported info
HubName string
HubVersion string
HubCaps map[any]any
MOTD string
// Limits from WELCOME
MaxNickBytes int
MaxRoomNameBytes int
MaxMsgBodyBytes int
MaxRoomsPerSession int
RateLimitMsgsPerMin int
// Room state
Rooms map[string]bool // joined rooms (lowercased)
Messages map[string][]*RRCMessage // room → messages
Notices []*RRCMessage // global notices
UnreadRooms map[string]bool // rooms with unread messages
MentionRooms map[string]bool // rooms with unread mentions
Members map[string]map[string]bool // room → set of hash hex
Nicks map[string]string // hash hex → nick
AvailableRooms map[string]*string // room → topic or nil
// Auto-connect options
AutoReconnect bool
AutoList bool
AutoWho bool
NickOverride string
// contains filtered or unexported fields
}
RRCHub represents a connection to a single RRC hub server.
func NewHub ¶
func NewHub(manager *RRCManager, hubHash []byte, destName, name string) *RRCHub
NewHub creates a new RRCHub with default values.
func (*RRCHub) ClearMessages ¶
ClearMessages clears the message buffer for a room.
func (*RRCHub) Connect ¶
Connect establishes an RNS link to the hub's destination. The link handshake is asynchronous; use SetOnLinkEstablished to be notified when the link becomes active. After link establishment, a HELLO envelope is sent to the server to initiate the RRC handshake.
func (*RRCHub) ConnectAsync ¶
func (h *RRCHub) ConnectAsync()
ConnectAsync initiates a connection to the hub's destination asynchronously, mirroring Python RRCHub.connect: it is a no-op when already connecting or connected, clears the manual-disconnect flag, cancels any pending reconnect timer, sets the status to Connecting, and launches the connect worker. The transport must have been configured via SetTransport.
func (*RRCHub) Disconnect ¶
func (h *RRCHub) Disconnect()
Disconnect tears down the RNS link and resets hub status, mirroring Python RRCHub.disconnect: it marks the disconnect as manual (so onClosed will not schedule a reconnect), resets the attempt counter, cancels any pending reconnect timer, and tears down the active link.
func (*RRCHub) DisplayNameFor ¶
DisplayNameFor returns the display name for a peer hash.
func (*RRCHub) GetEffectiveNick ¶
GetEffectiveNick returns the override nick or the manager's nick.
func (*RRCHub) GetHubName ¶
GetHubName returns the hub's display name under the hub lock, for the TUI HubView adapter (mirrors Python hub.name in Channels._compose_list_widgets).
func (*RRCHub) GetHubStatus ¶
GetHubStatus returns the hub's connection status under the hub lock, for the TUI HubView adapter (mirrors Python hub.status). The int is the Status* enum (StatusDisconnected … StatusFailed).
func (*RRCHub) GetMembers ¶
GetMembers returns the member list for a room.
func (*RRCHub) GetMessages ¶
func (h *RRCHub) GetMessages(room string) []*RRCMessage
GetMessages returns the message buffer for a room.
func (*RRCHub) HandleData ¶
HandleData decodes a CBOR-encoded RRC envelope and dispatches it to the appropriate handler based on the message type.
func (*RRCHub) JoinedRoomList ¶
JoinedRoomList returns the sorted list of joined room names, for the TUI HubView adapter (mirrors Python hub.rooms).
func (*RRCHub) MentionRoomList ¶
MentionRoomList returns the sorted list of rooms with unread mentions, for the TUI HubView adapter (mirrors Python hub.mention_rooms).
func (*RRCHub) MessageRoomList ¶
MessageRoomList returns the sorted list of rooms that have message buffers (joined rooms get an empty buffer on AddRoom), for the TUI HubView adapter (mirrors Python set(hub.messages.keys())).
func (*RRCHub) RemoveRoom ¶
RemoveRoom removes a room and its history.
func (*RRCHub) SendAction ¶
SendAction sends a T_ACTION to a room.
func (*RRCHub) SendCommand ¶
SendCommand mirrors Python RRCHub.send_command: it sends a raw command string (which must begin with "/") to the hub as a T_MSG envelope. Unlike SendMessage it does not normalize the room, record the message locally, or track the message ID for dedup — it is a thin send of the command text.
func (*RRCHub) SendMessage ¶
SendMessage sends a T_MSG to a room and records it locally.
func (*RRCHub) SetAutoList ¶
SetAutoList toggles the auto-list option, persisting and notifying, mirroring Python RRCHub.set_auto_list.
func (*RRCHub) SetAutoReconnect ¶
SetAutoReconnect toggles automatic reconnection, mirroring Python RRCHub.set_auto_reconnect: when disabled it cancels any pending reconnect timer, persists the change to disk when save is true, and notifies the manager of the change.
func (*RRCHub) SetAutoWho ¶
SetAutoWho toggles the auto-who option, persisting and notifying, mirroring Python RRCHub.set_auto_who.
func (*RRCHub) SetLink ¶
SetLink sets the RNS link used by this hub for sending data. This is used by server-side hubs that receive incoming links.
func (*RRCHub) SetNickOverride ¶
SetNickOverride sets a per-hub nick override.
func (*RRCHub) SetOnLinkClosed ¶
func (h *RRCHub) SetOnLinkClosed(fn func())
SetOnLinkClosed registers a callback invoked when the RNS link closes.
func (*RRCHub) SetOnLinkEstablished ¶
func (h *RRCHub) SetOnLinkEstablished(fn func())
SetOnLinkEstablished registers a callback invoked when the RNS link to the hub becomes active.
func (*RRCHub) SetTransport ¶
SetTransport configures the RNS transport used by the async connection worker (ConnectAsync). The synchronous Connect entry takes its transport argument directly; this setter is for the parameterless Python-style path.
func (*RRCHub) UnreadRoomList ¶
UnreadRoomList returns the sorted list of rooms with unread messages, for the TUI HubView adapter (mirrors Python hub.unread_rooms).
type RRCManager ¶
type RRCManager struct {
Hubs []*RRCHub
// contains filtered or unexported fields
}
RRCManager manages multiple RRC hub connections and persistence.
func NewManager ¶
func NewManager(storagePath string, identityHashFn func() []byte) *RRCManager
NewManager creates a new RRCManager rooted at the given storage path.
func (*RRCManager) ActiveRoomFor ¶
func (m *RRCManager) ActiveRoomFor(hub *RRCHub) string
ActiveRoomFor returns the active room for the given hub.
func (*RRCManager) AddHub ¶
func (m *RRCManager) AddHub(hubHash []byte, destName, name string) *RRCHub
AddHub creates or returns an existing hub for the given hash.
func (*RRCManager) EphemeralNotices ¶
func (m *RRCManager) EphemeralNotices() int
EphemeralNotices returns the age in seconds after which ephemeral system/notice messages are removed by the periodic cleanup.
func (*RRCManager) FilterLoadedHistory ¶
func (m *RRCManager) FilterLoadedHistory() bool
FilterLoadedHistory reports whether system/notice messages are dropped when loading history from disk.
func (*RRCManager) FindHub ¶
func (m *RRCManager) FindHub(hubHash []byte, destName string) *RRCHub
FindHub looks up a hub by hash and destination name.
func (*RRCManager) GetNickname ¶
func (m *RRCManager) GetNickname() string
GetNickname returns the display nickname.
func (*RRCManager) HasUnread ¶
func (m *RRCManager) HasUnread() bool
HasUnread returns true if any hub has unread messages.
func (*RRCManager) HistoryPerRoomCap ¶
func (m *RRCManager) HistoryPerRoomCap() int
HistoryPerRoomCap returns the per-room history cap, or 0 when no cap is set (matching Python _per_room_cap returning None).
func (*RRCManager) HubsSnapshot ¶
func (m *RRCManager) HubsSnapshot() []*RRCHub
HubsSnapshot returns a locked copy of the hub slice, for the TUI to render the channels list without racing AddHub/RemoveHub mutations. The returned slice is a copy; mutating it does not affect the manager.
func (*RRCManager) Identity ¶
func (m *RRCManager) Identity() *rns.Identity
Identity returns the local RNS identity, mirroring Python's RRCManager.identity property (self.app.identity). It returns nil when no identity has been configured.
func (*RRCManager) IsStopped ¶ added in v0.6.0
func (m *RRCManager) IsStopped() bool
IsStopped reports whether Shutdown has been called. Hubs consult this before scheduling a reconnect or spawning a connectWorker so a late closed-callback does not drive a stopped transport.
func (*RRCManager) Load ¶
func (m *RRCManager) Load() error
Load reads hub configurations from disk.
func (*RRCManager) NotifyChange ¶
func (m *RRCManager) NotifyChange(hub *RRCHub)
NotifyChange fires the change callback.
func (*RRCManager) NotifyMessage ¶
func (m *RRCManager) NotifyMessage(hub *RRCHub, msg *RRCMessage)
NotifyMessage fires the message callback.
func (*RRCManager) OnWelcome ¶
func (m *RRCManager) OnWelcome(hub *RRCHub)
OnWelcome is called when a hub receives a WELCOME packet. It re-joins all stored rooms.
func (*RRCManager) RemoveHub ¶
func (m *RRCManager) RemoveHub(hub *RRCHub)
RemoveHub disconnects and removes a hub.
func (*RRCManager) Save ¶
func (m *RRCManager) Save() error
Save persists all hub configurations to disk.
func (*RRCManager) SetActive ¶
func (m *RRCManager) SetActive(hub *RRCHub, room string)
SetActive sets the active hub and room.
func (*RRCManager) SetChangeCallback ¶
func (m *RRCManager) SetChangeCallback(fn func())
SetChangeCallback registers a callback for hub state changes.
func (*RRCManager) SetHistoryConfig ¶
func (m *RRCManager) SetHistoryConfig(perRoomCap int, filterLoaded bool, ephemeralSecs int)
SetHistoryConfig configures the per-room message-history cap, whether loaded history is filtered (system/notice messages dropped on load), and how long ephemeral system/notice messages survive the periodic cleanup — mirroring Python's rrc_history_per_room_cap, rrc_filter_loaded_history and rrc_ephemeral_notices app attributes. A perRoomCap <= 0 disables the cap.
func (*RRCManager) SetIdentity ¶
func (m *RRCManager) SetIdentity(id *rns.Identity)
SetIdentity sets the local RNS identity, mirroring Python RRCManager, which obtains its identity from the owning app (self.app.identity). The identity is exposed via Identity and used as the source for outgoing envelopes and for link identification.
func (*RRCManager) SetMessageCallback ¶
func (m *RRCManager) SetMessageCallback(fn func(hub *RRCHub, msg *RRCMessage))
SetMessageCallback registers a callback for new messages.
func (*RRCManager) SetNickname ¶
func (m *RRCManager) SetNickname(nick string)
SetNickname sets the display nickname.
func (*RRCManager) Shutdown ¶
func (m *RRCManager) Shutdown()
Shutdown disconnects all hubs and marks the manager stopped so that any link-closed callback still in flight (go-reticulum dispatches closed callbacks as `go callback(l)`, which can run after this method returns) will not schedule a reconnect against the now-torn-down transport. The change/message callbacks are cleared so post-shutdown NotifyChange / NotifyMessage invocations from in-flight RRC worker callbacks become no-ops rather than queueing draws onto a stopped tview Application.
type RRCMessage ¶
type RRCMessage struct {
Kind string // "msg", "action", "notice", "system", "error"
Room string // room name (lowercased), empty for global notices
Src []byte // sender identity hash, nil for system/notices
Nick string // sender display nick
Text string // message content
Ts int64 // timestamp in milliseconds since epoch
Mention bool // true if message mentions the local user
}
RRCMessage represents a single chat message.
func DecodeHistoryEntry ¶
func DecodeHistoryEntry(entry map[string]any) *RRCMessage
DecodeHistoryEntry creates an RRCMessage from a CBOR-decoded history entry map.
func (*RRCMessage) HistoryEntry ¶
func (m *RRCMessage) HistoryEntry() map[string]any
HistoryEntry returns a map suitable for CBOR encoding to the history file format.