The SPIN Framework is designed so multiple processes can share high-level 3D state over a network using OpenSoundControl (OSC) messages. By default, all messages are sent from the server via UDP multicast on the address of 239.0.0.1. An INFO channel (port) is used to send notifications about available ports, where clients can listen or connect and send messages to the server.
Below is a table that summarizes the important networking channels used by SPIN. We will explain each of these in more detail below.
channel | RX proto | RX addr | RX port | TX proto | TX addr | TX port |
INFO | multicast UDP | 239.0.0.1 | 54320 | multicast UDP | 239.0.0.1 | 54320 |
SERVER | unicast UDP | [serverIP] | 54324 | multicast UDP | 239.0.0.1 | 54323 |
SECURE | TCP | [serverIP] | 54322 | TCP | [client subscibes] | |
CLIENT | multicast UDP | 239.0.0.1 | 54323 | unicast UDP | [serverIP] | 54324 |
TIMECODE | same as client RX addr | 54321 | same as client TX addr | 54321 |
NOTE: These are default settings, and can be overridden using command-line arguments or environment variables.
Using the above table, we can imagine a basic setup consisting of one spinserver and one spinviewer (a type of client). Any time the state changes on the server, a multicast message is emitted by ther sercer on port 54323. The viewer listens on this port and updates it's internal representation so that the change is drawn in the next frame. The client may want to send some messages to the server. For instance, a spinviewer allows a user to pick and move an object using the mouse. In this case, messages are sent to the server on port 54324; the server state will be updates, and the resulting change is again multicast on port 54323, and will be displayed.
SPIN Message Protocol
In general, all messaging conforms to a particular protocol:
/SPIN/<sceneID>/<nodeID> method <var_args>
All OSC messages are contained within the /SPIN namespace, and may control a scene element or a particular node within a scene. For example, a message to /SPIN/someScene will control a scene with id "someScene" at the scene level, allowing you to create/delete nodes, clear/refresh the scene, etc. If the selector is more specific, for example /SPIN/someScene/someModel, the intention is to send messages to a particular node, and not the scene in general. Wildcards are acceptable in the selector, so /SPIN/*/shape* would target all nodes that start with "shape" on all servers on the network.
For a full reference of all messages, see the osc protocol page
The INFO channel
To facilitate the network binding procedure, the server periodically multicasts it's information on the INFO channel, notifying potential clients of it's existence, and providing the ports to which they must send messages. The server's info message looks like this:
/SPIN/__server__ sceneID addr rxUDPport rxTCPport txAddr txPort syncPort
In the case of our defaults described in the table above, a real example might look like this:
/SPIN/__server__ default 192.168.1.100 54324 54322 224.0.0.1 54323 54321
Client INFO (and UserNodes)
An "official" SPIN client process that communicates with a server should create a UserNode in the scene with a UserID as an identifier (typically, the computer's hostname is used as the UserID).
The client is then required to periodically send the "ping" message to the UserNode it created in order to assert the client's continued presence. If a client suddenly disappears, the server will see an interruption in the stream of "ping" messages to that UserNode and will thus clean up unnecessary state (i.e. delete the UserNode and its subgraph).
A client's "ping" message to the UserNode it created should be sent at least once every 20 seconds; the message should be structured like this:
/SPIN/sceneID UserNodeID ping
IMPORTANT: Any UserNode created on the server (and any attached child nodes) will be automatically removed by the server if an info message is not received within a regular interval (eg, within 60 seconds).
Secure TCP Channel
The server listens to messages on UDP for non-critical control data, while important state messages should be sent to the server via TCP. Any one may send messages to the TCP channel, but it should be understood that this is a one-way connection; resulting changes to the scene state will be sent out via UDP multicast as usual.
If a client wants to receive important state from the server via TCP, a subscription is required. The client must send a "subscribe" message to the server's TCP port, in the following form:
/SPIN/sceneID subscribe UserID clientAddr clientTCPport
The server will then form a unicast TCP connection to the client's specified address, and send any requested state to that port. However, only the following TCP queries are currently supported:
Message | Result |
---|---|
/SPIN/<sceneID> refresh | SPIN will send the entire scene in bundles to the TCP receiver |
/SPIN/<sceneID> getState <nodeID> | SPIN will send the state of a node to the TCP receiver |
Timecode and Synchronization
A timecode is sent in a separate multicast OSC channel, allowing clients to manage their own animations while maintaining sync with the server:
/SPIN/<sceneID> sync <elapsed-time-in-milliseconds>
Example
To summarize, when SPIN launches, it periodically sends an info message on the INFO channel:
/SPIN/__server__ sceneID rxAddr rxUDPport rxTCPport txAddr txPort syncPort
Clients can just listen on UDP port txAddr:txPort for scene updates, or they can connect (via unicast to rxAddr:rxUDPport) and send server-level messages. Example:
/SPIN/sceneID debug /SPIN/sceneID createNode <nodeType> <nodeID> /SPIN/sceneID deleteNode <nodeID> /SPIN/sceneID load <scenefile.xml> /SPIN/sceneID save <scenefile.xml> /SPIN/sceneID clear
Once a particular node is created on the server, messages can be sent to it as follows:
/SPIN/sceneID/nodeID setTranslation 1 2 3 /SPIN/sceneID/nodeID setOrientation 1 2 3 /SPIN/sceneID/nodeID setParent <parentID>
All clients listening on the server's txAddr:txPort, will be notified on these updates, and can update themselves accordingly.