rrc

package
v0.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

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

View Source
const (
	KeyVersion   = 0
	KeyType      = 1
	KeyMessageID = 2
	KeyTimestamp = 3
	KeySource    = 4
	KeyRoom      = 5
	KeyBody      = 6
	KeyNick      = 7
)

Envelope keys for CBOR-encoded messages.

View Source
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.

View Source
const (
	BHelloName = 0 // client name string ("nomadnet")
	BHelloVer  = 1 // client version string ("0.1")
	BHelloCaps = 2 // capabilities dict
)

Body sub-keys for HELLO messages.

View Source
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.

View Source
const (
	LMaxNickBytes           = 0
	LMaxRoomNameBytes       = 1
	LMaxMsgBodyBytes        = 2
	LMaxRoomsPerSession     = 3
	LRateLimitMsgsPerMinute = 4
)

Limit keys in WELCOME body.

View Source
const (
	CapResourceEnvelope = 0
	CapAction           = 1
)

Capability flags.

View Source
const (
	ResKeyID       = 0
	ResKeyKind     = 1
	ResKeySize     = 2
	ResKeySHA256   = 3
	ResKeyEncoding = 4
)

Resource envelope body keys.

View Source
const (
	ResKindNotice = "notice"
	ResKindMOTD   = "motd"
	ResKindBlob   = "blob"
)

Resource kinds.

View Source
const (
	DefaultDestName      = "rrc.hub"
	DefaultMaxNickBytes  = 32
	DefaultMaxRoomBytes  = 64
	DefaultMaxMsgBytes   = 350
	DefaultMaxRooms      = 32
	DefaultRatePerMinute = 240
)

Default values.

View Source
const (
	HKind    = "k"
	HSrc     = "s"
	HNick    = "n"
	HText    = "t"
	HTS      = "ts"
	HMention = "m"
)

History entry keys for persistence.

View Source
const (
	StatusDisconnected = 0
	StatusConnecting   = 1
	StatusConnected    = 2
	StatusFailed       = 3
)

Hub connection status.

View Source
const (
	CleanHistoryInterval = 5   // seconds between history cleanups
	NoticeTimeout        = 600 // seconds before ephemeral notices expire
)

Timing constants.

View Source
const RRCVersion = 1

Protocol version.

Variables

This section is empty.

Functions

func DecodeEnvelope

func DecodeEnvelope(data []byte) (map[any]any, error)

DecodeEnvelope deserializes CBOR bytes to an envelope map.

func EncodeEnvelope

func EncodeEnvelope(env map[any]any) ([]byte, error)

EncodeEnvelope serializes an envelope map to CBOR bytes.

func MakeEnvelope

func MakeEnvelope(msgType int, src, room, nick []byte, body any, mid []byte, ts int64) map[any]any

MakeEnvelope constructs a CBOR-encodable envelope for the RRC protocol.

func MentionRegex

func MentionRegex(nick string) string

MentionRegex returns a simple pattern for detecting @mentions. The actual implementation uses word-boundary-aware matching.

func MsgID

func MsgID() []byte

MsgID returns 8 random bytes for message deduplication.

func NowMs

func NowMs() int64

NowMs returns the current time in milliseconds since epoch.

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) AddRoom

func (h *RRCHub) AddRoom(room string)

AddRoom adds a room to the local state.

func (*RRCHub) ClearMessages

func (h *RRCHub) ClearMessages(room string)

ClearMessages clears the message buffer for a room.

func (*RRCHub) Connect

func (h *RRCHub) Connect(ts rns.Transport, dest *rns.Destination) error

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

func (h *RRCHub) DisplayNameFor(peer []byte) string

DisplayNameFor returns the display name for a peer hash.

func (*RRCHub) GetEffectiveNick

func (h *RRCHub) GetEffectiveNick() string

GetEffectiveNick returns the override nick or the manager's nick.

func (*RRCHub) GetHubName

func (h *RRCHub) GetHubName() string

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

func (h *RRCHub) GetHubStatus() int

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

func (h *RRCHub) GetMembers(room string) []string

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

func (h *RRCHub) HandleData(data []byte)

HandleData decodes a CBOR-encoded RRC envelope and dispatches it to the appropriate handler based on the message type.

func (*RRCHub) JoinRoom

func (h *RRCHub) JoinRoom(room string, silent bool)

JoinRoom sends a T_JOIN for a room.

func (*RRCHub) JoinedRoomList

func (h *RRCHub) JoinedRoomList() []string

JoinedRoomList returns the sorted list of joined room names, for the TUI HubView adapter (mirrors Python hub.rooms).

func (*RRCHub) MarkRead

func (h *RRCHub) MarkRead(room string)

MarkRead clears unread/mention flags for a room.

func (*RRCHub) MentionRoomList

func (h *RRCHub) MentionRoomList() []string

MentionRoomList returns the sorted list of rooms with unread mentions, for the TUI HubView adapter (mirrors Python hub.mention_rooms).

func (*RRCHub) MessageRoomList

func (h *RRCHub) MessageRoomList() []string

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) PartRoom

func (h *RRCHub) PartRoom(room string)

PartRoom sends a T_PART for a room.

func (*RRCHub) RemoveRoom

func (h *RRCHub) RemoveRoom(room string)

RemoveRoom removes a room and its history.

func (*RRCHub) SendAction

func (h *RRCHub) SendAction(room, text string) string

SendAction sends a T_ACTION to a room.

func (*RRCHub) SendCommand

func (h *RRCHub) SendCommand(text, room string) error

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

func (h *RRCHub) SendMessage(room, text string) string

SendMessage sends a T_MSG to a room and records it locally.

func (*RRCHub) SendPing

func (h *RRCHub) SendPing(room string)

SendPing sends a T_PING to a room.

func (*RRCHub) SetAutoList

func (h *RRCHub) SetAutoList(enabled, save bool)

SetAutoList toggles the auto-list option, persisting and notifying, mirroring Python RRCHub.set_auto_list.

func (*RRCHub) SetAutoReconnect

func (h *RRCHub) SetAutoReconnect(enabled, save bool)

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

func (h *RRCHub) SetAutoWho(enabled, save bool)

SetAutoWho toggles the auto-who option, persisting and notifying, mirroring Python RRCHub.set_auto_who.

func (h *RRCHub) SetLink(link *rns.Link)

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

func (h *RRCHub) SetNickOverride(nick string)

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) SetStatus

func (h *RRCHub) SetStatus(status int, text string)

SetStatus updates the connection status.

func (*RRCHub) SetTransport

func (h *RRCHub) SetTransport(ts rns.Transport)

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

func (h *RRCHub) UnreadRoomList() []string

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL