Skip to content
This repository has been archived by the owner on Oct 5, 2024. It is now read-only.

maandree/sbus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This repo has been moved to Codeberg and may be out of date on GitHub.
Canonical repo: https://codeberg.org/maandree/sbus


sbus is simple message bus based on unix domain, sequenced-packet sockets.

Features:
	Support for multi-user buses.
	No state-keeping required in clients.
	Supports all send(2)/recv(2) flags.
	Almost full setsockopt(2)/getsockopt(2)/fcntl(2)/ioctl(2) support:
		No send-time timestamps
		Increasing message size limit may cause problems
	Supports select(2)/poll(2)/epoll(7).
	Support for routing keys with wildcards.
	Support for secret communication.
	Reliable and ordered communication.

Non-features:
	No IP or cluster support, should be implemented as a separate service.
	No support for overly large messages, should be implemented at application level.
	No persistence support, should be implemented as a separate service.
	No support for automatic unsubscriptions.
	No support for reply-to keys, should be implemented at application level.
	No support for shared queues, should be implemented as a separate service.
	No file descriptor passing support, not network-compatible, should be
		implemented as a separate service or at application level.
	No support for server-verified credentials, can be implemented at
		application level by using '!/cred/' routing keys.
	No acknowledgement of when messages have been processes, can be
		implemented at application level by sending yourself a message
		and wait for it to return.
	No remote procedure call support.

Routing keys:
	Routing keys are used to filter received messages. A routing key
	may contain any byte other than the NUL, whoever there are three
	bytes with special meaning: '*', '/', and '!'. '*' should not be
	in routing keys, but only in routing key patterns, it matches until
	the next '/' or end if there are not more '/'s. Additionally if a
	routing key pattern ends with '/' that '/' will match to a '/' and
	any subsequent byte. For example 'a/*/c/' will match 'a/b/c/' and
	'a/b/c/d/e' but not 'a/b/c' or 'a/c/d'. And empty routing key
	pattern shall match everything. The token '!' is reserved, a client
	should never use '!' for any other purpose than specified in the
	protocol, unless it has an other byte than a '/' next to it. The
	server may choose to disconnect a client using '!' in an invalid
	way or simply ignore such messages.

Protocol:
	Communication is done over unix domain, sequenced-packet sockets.
	Each packet is interpreted as a complete message. A packet cannot
	contain multiple message, and a message cannot be split over
	multiple packets. There are 4 types of messages:

	Subscribe:
		Send a routing key pattern to the server for the client.
		The server shall send all messages with matching routing
		keys to this client. The server shall store the key even
		if there is already an identical routing key pattern
		registered for the client.

		Messages of this type shall match the regular expression

			^SUB \([^\x00]*\)\(\x00.*\)\?$

		where \1 is the routing key pattern, \2 is ignored.

	Unsubscribe:
		Tell the server to remove a routing key pattern for the
		client. The server may choose to disconnect the client
		if it sends a routing key pattern that is not registered
		for the client.

		Messages of this type shall match the regular expression

			^UNSUB \([^\x00]*\)\(\x00.*\)\?$

		where \1 is the routing key pattern, \2 is ignored.

	Publish:
		Publish a message on the bus. The server shall send a
		copy of packet to all clients with a matching routing
		key pattern, including the client that sent the packet
		if and only if that client has a matching routing key
		pattern. The server may not send a copy of the packet
		to any clients without a matching routing key pattern.

		Messages of this type shall match the regular expression

			^MSG \([^\x00]*\)\x00\(.*\)$

		where \1 is the routing key for the message and \2
		is the message payload.

	Control message:
		Send a control message to the server. The server may
		also send control message to clients. The server will
		never forward control message it receives, and no
		subscriptions are required to receive the messages.

		Messages of this type shall match the regular expression

			^CMSG \([^\x00]*\)\(\x00\(.*\)\)$

		where \1 is the routing key for the message and \3
		is the message payload. \2 may be om be omitted if
		sent by the client.

Secret messages:
	Routing keys starting with '!/cred/' can only be subscribed to
	by clients with matching credentials. These routing keys must
	match regular expression

		^!/cred/\([0-9]*\)/\([0-9]*\)/\([0-9]*\)/\(.*\)$

	where \1 is the group ID, \2 is the user ID, \3 is the process
	ID, and \4 the rest of routing key which may also use this
	pattern a process it communicates. Client can only subscribe
	to the routing key \1, \2, and \3 match it's credentials.
	If \1, \2, or \3 are empty, they will match the clients it's
	credentials when subscribing. However, the server will not
	accept '*' for \1, \2, or \3, or truncated routing keys.

	However, due to network support, these routing keys may need
	to be prefixed with the credentials for the servers the message
	goes through, or use the credentials of the a program running
	on a different master machine. Therefore, a client cannot
	simply just use its GID, UID, and PID, but must ask what's its
	credentials are by sending an empty control message (CMSG) with
	the routing key '!/cred/whoami'. The server will reply with a
	control message with the same routing key and the message will
	be the credentials, for example '!/cred/100/1000/1111' or
	'!/cred/100/1000/1111/!/cred/1000/1000/19211'. Note, the server
	will never send control messages it receives from other clients,
	so the received control message is guaranteed to come from the
	server.

	Example of how two client can prove their identities to each oter:

		A: Send A's credentials to B.
		B: Send B's credentials with routing key private to A.
		A: Send a random message with routing key private to B.
		B: Send back the message with routing key private to A.

Flood control:
	The following control messages can be sent to the server to
	choose the server behaviour when messages cannot be delivered
	without blocking. All control messages are optional and server
	may choose to ignore them at any time, even if previously
	honoured. Most recently sent control message that precedence.

	^CMSG blocking/soft/queue\(\x00.*\)*$

		Delivering is preferable, the server should queue up
		message that cannot be sent.

	^CMSG blocking/soft/discard\(\x00.*\)*$

		Delivering is unimportant, the server should discard
		message that cannot be sent.

	^CMSG blocking/soft/block\(\x00.*\)*$

		Delivering is important, the server may block communication
		to guarantee that messages are delivered.

	^CMSG blocking/soft/error\(\x00.*\)*$

		The server may treat a client as misbehaving if message
		cannot be sent.

	^CMSG blocking/hard/discard\(\x00.*\)*$

		If the server has queued up too many message it should
		start discarding new message instead of queuing them.

	^CMSG blocking/hard/block\(\x00.*\)*$

		If the server has queued up too many message it should
		start blocking communication until it can start queuing
		messages again.

	^CMSG blocking/hard/error\(\x00.*\)*$

		If the server has queued up too many message it should
		start treating clients that are blocking as misbehaving.

	^CMSG order/queue\(\x00.*\)*$

		If the client is blocking it is preferable that messages
		are sent in order.

	^CMSG order/stack\(\x00.*\)*$

		If the client is blocking it is preferable that messages
		are sent in reverse order.

	^CMSG order/random\(\x00.*\)*$

		If the client is blocking it is preferable that messages
		are sent in such order that memory is freed up as fast
		as possible.

Echos:
	By default, if a client sends a message with a routing key it is
	subscribed to, that client will receive that message. The server
	may however choose to implement control messages for selecting
	whether this happens. Disabling echoing is useful for implementing
	slave servers that only send messages upwords in the server
	hierarchy when necessary. The control messages for controlling
	echoing are

	^CMSG echo/off\(\x00.*\)*$

		Disable echoing.

	^CMSG echo/on\(\x00.*\)*$

		Reenable echoing.