LSL Protocol/Restrained Love Open Relay Group/ORG Requirements/0004 draft
This page lists requirements that make a RLV relay or a RLVR controller "ORG compliant". Main advantages of an ORG compliant device over a classic RLVR devices are the following:
- ORG devices follow a stricter specification (while keeping compatibility), thus making the experience more predictable for scriptwriters;
- ORG devices support wildcards for easy and low lag relay scanning and mass effects;
- ORG devices can support optional x-tensions for more fun. Supported x-tensions can easily be discovered thanks to a new query meta-command.
For a quick overview of the motivations and general working of the RLVR protocol and a few examples, we refer the reader to the original RLVR specification.
If you are making furniture, traps, or other RLVR controllers and you are not interested in what optional ORG x-tensions can offer, then you can stick with the original RLVR specification and still be compatible with ORG relays. However, to have the right to call your controller "ORG compatible", there are still a few light additional requirements such as:
- using only llRegionSayTo for communications (in both directions),
- not spamming the RLVR channel with messages that do not belong to the protocol,
- and remain responsive to ping messages at every time if you want the session to remain locked.
If you are making a relay, sorry we are afraid you will have to read all this page.
Definition of an ORG device
A RLVR device is compliant with ORG specifications if it implements the consolidated RLVR protocol and meta-commands described in sections below, along with the optional ORG x-tensions it announces supporting.
- An x-tension can constrain the core specification (this document) even more, but cannot alter its requirements or make them less constraining by the mere fact of being there.
- However requirements may be altered as the result of executing a meta-command belonging to an x-tension.
- Thus, although the protocol is extensible, a controller can always rely on the fact an ORG relay abides by the core requirements until the controller knowingly asks the relay to do otherwise.
If a device is ORG compliant, it may be advertised by the use of the ORG logo. ORG device makers are encouraged to do so.
Consolidated RLVR protocol
This consolidated RLVR protocol is roughly the same as Marine Kelley's RLVR protocol version 1.100, minus a few embarrassing loose ends.
Main differences are highlighted at the beginning of each subsection.
Summary of differences with original RLVR:
- we force use of llRegionSayTo,
- we explicitly forbid incorrect syntax on the relay channel
- the relay is supposed to ignore bad commands
- wildcards are supported
- The Restrained Love Relay (RLVR) protocol implies two partners (SL objects): the relay, attachment worn by the avatar commands are intended for, and a controller, which sends commands to the relay.
- The goal of the protocol is to force the relay wearer to make perform actions and to toggle restrictions on their behavior. Both actions and restrictions can be enforced either through use of viewer hooks (Restrained Love API, or RLV) or through LSL scripting.
- Hence we distinguish between "RLV commands", starting with "@", which are commands following the syntax of the RLV API and which will ultimately be forwarded to the viewer, and "meta-commands", starting with "!", which are meant to be interpreted by LSL functions.
RLVR protocol consists of messages exchanged between relay and controller
- on channel -1812221819 (called RLVR channel),
- using the LSL function llRegionSayTo (except for <c_msg>'s using a wildcard)
- all sent from the same prim of the controller or relay (within a session)
- and having the following syntax (non-terminal <c_msg> for controller messages/command messages and <r_msg> for relay messages/acknowledgement messages):
<c_msg> ::= IDENT "," KEY "," <commands> <r_msg> ::= IDENT "," KEY "," <command> "," ACK <commands> ::= <command> | <command> "|" <commands> <command> ::= <rlv-command> | <meta-command> <rlv-command> ::= "@" RLV-COMMAND <meta-command> ::= "!" META-COMMAND_NAME <meta-command arguments> <meta-command arguments> ::= "" | "/" ARG <meta-command arguments>
where we explicit the different terminal tokens:
IDENT: any string without "," KEY: any UUID ACK: any string without "," RLV-COMMAND: any string without "," META-COMMAND_NAME: any string without "/" and "," ARG: any string without "/" and ","
- Relays can only send <r_msg>'s, and controllers <c_msg>'s. Nothing else is allowed on RLVR channel.
- In <c_msg>, KEY is always either the UUID of the relay wearer or ffffffff-ffff-ffff-ffff-ffffffffffff (wildcard) if it is a message intended for all relays who can hear it. If llRegionSayTo is used, then the first parameter will also be the UUID of the relay wearer.
- In <r_msg>, KEY is always the UUID of the controller (more accurately: the uuid of the primitive sending the <c_msg>'s), this will also be used as the first parameter of llRegionSayTo.
IDENT and ARG can be empty, relay makers must take care of properly handling messages with empty IDENT or ARG (use llParseStringKeepNulls instead of llParseString2List). However, due to the fact many existing relays do not properly handle them, controllers should avoid using empty IDENTS.
On the relay side only
- A relay MUST ignore any message on RLVR channel which is not a <c_msg> with KEY being either the key of the avatar wearing the relay or ffffffff-ffff-ffff-ffff-ffffffffffff.
Then, for every <command>:
- if <command> is neither a valid <rlv-command> or <meta-command>, the relay must ignore it and process the next <command>'s;
- if <command> is a <rlv-command> or a <meta-command>, the relay MUST send back to the controller a <r_msg> (see above) such that:
- IDENT is the same as IDENT in the <c_msg> being processed,
- <command> is the subcommand being processed
- and ACK is a string called acknowledgement value. By default the acknowledgement value is "ok" if the relay will execute the <command >, "ko" otherwise.
- Many meta-commands may have other acknowledgements than "ok" or "ko" (or none, for !pong). Their definitions supersede this specification.
- Note that unknown meta-commands cannot be executed and thus wil be acknowledged by "ko".
- Known meta-commands which are sent with not enough parameters or parameters with types incompatible with those in the definition known by the relay also cannot be executed and will also be acknowledged by "ko". (ex: the relay knows !x-who/key, but receives !x-who/integer/string).
On executing commands
Summary of differences with original RLVR:
- explanation on how to handle meta-commands with variable number of parameters,
- the relay knows commands in both core specification and x-tensions,
- clarification on multi-controller relays.
- If a <rlv-command> is acknowledged with value "ok", the relay ensures the viewer is affected the same way as if the LSL instruction llOwnerSay(<rlv-command>) was executed by a script in a primitive that handles only one controller.
- When processing a <meta-command>, if the relay knows at least one definition of '!'+META-COMMAND_NAME for which the received <meta-command arguments> provide enough parameters, then it will be handled according to the definition handling the most parameters among the latter. Extra parameters are ignored.
- A relays knows the following meta-command definitions:
- When acknowledging a <meta-command> by anything else than "ko", the relay commits itself to execute it.
- For first requirement, it must be understood that the reference behavior is that the relay would have if it had one controller per prim. However handling several controllers from one unique prim is possible but requires taking care that different controllers do not interfere with each other, releasing each others restrictions, for instance.
- For the second requirement, the word "handled" means that if the meta-command with these parameters is known, then requirements in known definition cannot be ignored. Sometimes, this can imply that the meta-command cannot be refused, for instance.
- The controller can send any command within allowed syntax.
- Only commands described in this specification and commands belonging to x-tensions announced by the relay are guaranteed to be understood by the relay. If not understood, the relay will just answer "ko", do nothing and skip to the next command.
Summary of differences with original RLVR:
- it is now clear when a session starts and stops (and what a session is!)
- it is clear when to expect interactive dialogs (and how to avoid spamming relay wearers with blue dialogs)
- no session for unreachable controllers (answer to ping is mandatory to ensure session persistence)
- During an execution of the RLVR protocol, a relay and a controller establish a session together. A relay may manage several sessions with several controllers. Likewise, a controller could establish sessions with several relays.
- Restrictions on a relay wearer are relative to a session. So are most other variables (authorization state, key of the controller, ... ).
- A session is Opened whenever the relay accepts a RLVR command from a controller.
- A session is Closed (or released) as soon as the relay forgets every variables and releases all restrictions pertaining to that session.
- A session is Locked whenever it holds active restrictions.
- A session is Authenticated if the controller has been allowed to control the relay (not only store some variables with no consequence). Once authenticated, no interactive "ask" dialog should pop up anymore concerning this session. Most commands should now normally be accepted (and maybe a few automatically rejected).
- A controller is called reachable if it can receive messages from the relay and can prove it by answering ping requests from the relay. By "can", it is meant by the method of communication agreed upon by the relay and controller (by default: chat messages sent on RLVR channel by llRegionSayTo). X-tensions such as email and delay can modify what is meant by reachable.
Relay side requirements
On closing sessions:
- Closing a session clears all RLV restrictions that belong only to that session, clears all session variables and disables all restrictions relative to that session. This MUST happen on the following events and no other:
- on executing !release (received from the controller, or relay-triggered as in a safe-word, see #!release)
- on noticing the controller is not reachable
- on timeout, if the session is not Locked
- Sessions that are not locked MUST be closed after a reasonable timeout.
On interactive Authentication:
- Unless specified otherwise (see !x-who), no command can trigger an interactive dialog unless the command requires an Authenticated session and the session is not already Authenticated.
- Relay implementations MAY require an authenticated session for all <rlv-command>'s of the form @xxx=force, @xxx=add and @xxx=n, and for meta-commands whose specifications say it is allowed.
- Other RLV commands MUST automatically accepted or rejected by any relay.
On removing and adding restrictions:
- Commands that remove restrictions are always accepted (RLV @...=<channel_number>, @clear[=...] and @...=y/rem commands, !release, and !x-.../clear[/...] meta-commands).
- No restriction can be released unless as the result of one of the above commands, or of closing a session.
- @xxx=n/add <rlv-command>'s, after being accepted, add a restriction and therefore Lock the session.
- Some meta-commands described in x-tensions can also add restrictions and therefore Lock the session.
- A relay MUST provide a mechanism for checking that every controlling device is reachable. It is not specified whether this checking process should be automatic or manually triggered.
Controller side requirements
- A controller MUST eventually close any Locked session using the meta-command !release.
In particular, non-portable controllers should not let a Locked relay wearer run free out of reach. Moreover, any controller should either react to some kind of event that is bound to happen (timer expiration being the most common) or provide a user interface for closing the session. It should be clear at least to the person who set the trap how the victim will be released.
Core meta-commands and associated mechanisms
An ORG device MUST at least support the meta-commands !release, !pong, !version, !implversion and !x-orgversions described below and implement their associated mechanisms.
Particular meta-commands definitions and mechanisms may override general requirements above.
New in ORG compared to RLVR: !x-orgversions
Sent by a controller, this command closes the session.
- !release obviously opens no session, requires no Authrnyication and is not Locking.
- If there is an actual session to close, !release MUST be accepted by the relay and acknowledged by "ok".
- On accepting !release, the relay erases all data pertaining to the session and disables all restrictions of the session.
- When a relay decides to close a session on its own (user safe-word, for instance) and it is not due to the controller being unreachable, the relay must send the following acknowledgement message:
When receiving the latter message, the controller should act accordingly, for instance by resetting itself and making itself ready for the next session.
Note that !release is not the same as @clear. @clear is interpreted by the relay as a RLV command and, as such, can only clear RLV restrictions. If RLV restrictions were the only restrictions of the session, then the session will be closed, but some x-tensions also define pure LSL based restrictions.
The ping/!pong mechanism exists so that relays can check presence and responsiveness of a controller. This was primarily meant to be used on relay wearer relog, in order to reactivate all restrictions so that sessions persist on relog if the controller still exists and is ready to continue the session.
!pong cannot require authentication and does not lock a session
We call ping message a message from the relay, having the following syntax:
We call !pong message a message from the controller, having the following syntax:
- A relay SHOULD NOT send an acknowledgement in response to !pong.
- A ping message can be sent any time by the relay to a known controller.
- On wearer relog, for each existing Locked session, the relay must send a ping message to the session controller.
- When a !pong message is received from a controller, if it was a reply to a previous ping message:
- if the session RLV restrictions contain unsit and the avatar was sitting on some object when the restriction was applied, then the relay MUST force the avatar to sit back on the same object (if still existing);
- the relay MUST make sure all restrictions belonging to the session are made active again.
- If a ping message is sent and is not answered by the controller, then the relay closes the session.
Note that the relay is responsible for storing restrictions and the key of the sit target across sessions, not the controller.
- Unless it does not matter that the relay could close the session (or for another reason, the controller knows the relay will not close it), a controller SHOULD listen to ping messages and answer any ping message with a !pong message.
- A controller should ignore ping requests from relays it is not ready to handle.
Note controller don't have to poll for relay presence to resume a session but should just listen for ping messages instead. The relay should have stored all restrictions and handle sitting back to whatever furniture the relay wearer was tied up to.
Concerning the second bullet: for instance, if the controller is a furniture which is already in use by another relay wearer, it would be cause dysfunctions to let the pinging relay restore the restrictions without letting its wearer sit on the furniture. Or if the controller is not stateless and the state for the pinging relay has not been saved before, resuming the session from the initial state might be inconsistent.
The purpose of this meta-command is to query the version of the RLVR protocol supported by a relay.
- !version opens no session (and requires no authentication, neither can lock a session)
- A relay MUST always acknowledge !version with the version number of the RLVR protocol it supports ("1100" here, since ORG 0004 includes RLVR 1.100).
Note this is the most common command for a controller to scan for nearby relays, as non-ORG relays also accept this command and answer it the way described above.
The purpose of this meta-command is to query the name and version of the relay implementation.
- !implversion opens no session (and requires no authentication, neither can lock a session)
- A relay MUST always acknowledge !implversion with its implementation version string... which can be any string.
It is recommended this string includes the following elements:
- the relay name/brand/identifier,
- the version number of that relay name/brand/identifier,
- at the beginning, the string prefix "ORG=0004/"
The latter is convenient for checking for ORG compatibility using a command even non-ORG relay should understand.
This meta-command's purpose is to make it possible for the controller to have detailed information on the protocol the relay supports. First the version of the ORG consolidated protocol, second the list of supported optional x-tensions, also with their version numbers.
C<->R -> query,rUUID,!x-orgversions <- query,cUUID,!x-orgversions,ORG=0004/who=002/email=006
- !x-orgversions should always be accepted with no Auth required, it does not open a session or Lock one.
- The acknowledgement value in a reply to !x-orgversions is a "/"-list of items of the form <package>=<version>. The first <package> is always "ORG" (representing the core specification package of ORG relays), its version string is the version of the specification (4 digits). The other packages are x-tension names, whose version string is 3 digits.
- If several incompatible versions of a same x-tension are supported, they must be listed ordered by version number. Ex: ORG=0004/who=002/email=005/email=006. If versions are backward compatible, only the last version should be reported.
- By announcing an x-tension, the relay commits itself to comply to all requirements of its specification.
- In a controller, it is however recommended to use !x-orgversions as soon as possible in order to avoid sending unsupported and useless meta-commands later on.
- In the acknowledgement message, x-tension names are listed, not meta-command names (as one x-tension can have several meta-commands). Thus listed names do not include the prefix "!x-".
- x-tensions do not have to be standards defined by ORG but can also be proprietary. We recommend that the x-tension name then contains the name of the brand who proposes it.
Commands not listed here can belong to one of the following categories:
- (unlikely) commands from a future revision of Marine Kelley's original RLVR protocol.
- (more likely but not that much!) core commands from a future revision of ORG
- (very likely) commands from optional x-tensions
- proprietary commands
ORG intends for its successive versions to be backward compatible. Therefore ORG relays handle all unknown meta-commands.
We also intend for future versions of ORG consolidated protocol to include last version of original RLVR protocol, hence the prefix "!x-" for all meta-commands coming from ORG, which ensures there will be reasonably no collision.
For the same reason, we require that proprietary commands use an obvious prefix such as "!a-" or "!b-", and so on. Not doing so would prevent ensuring backward compatibility, hence a relay or controller who would use proprietary commands with wrong prefixes are not ORG compliant.