Between hosts
Three things cross between hosts: a bundle of data, a program, and a running machine.
They all come in through one door. Whatever arrives at a host goes into
the machine’s input register and the machine runs it; the door checks
only that it is a well-formed bundle. So every arrival is a program followed by a verb: data
followed by what to do with it, source followed by the verb that parses
and runs it, a machine followed by /continue/admit. The verb is the
sender’s, and what a host does with what it is handed is its own.
Trust
The door checks one thing: that what arrived is a well-formed bundle. Nothing else about it is inspected, neither who sent it nor what it will do. A host then runs what it is sent, with every capability it has bound. That assumes a network you trust: a studio, a stage, a lab. A host reachable from beyond one belongs behind whatever you put any listening service behind.
A bundle of data
Any OSC tool can send one to a host’s port. The command line receives on a port it opens, and hands each arrival to a function:
/show : ({ (/b) /o/println }, ["/b"]) /o/defn, (7788, /show) /o/listen
The board listens on UDP 8888 and answers whoever sent to it; the Python
host’s examples/udp.py --serve 7777 is a responder to try against.
A program
Source, or already parsed: the parsed form needs only a machine at the far end, the source needs osen there too and is smaller on the wire.
- Command line:
/!/loadwith a path takes a.oseor.osenfile, or a shared library; a string of osen arrives as[/,/s/<source>, /!/repl/rep]. - Python:
vm.parse(src)gives the bytes for a socket;ose.program(vm, src)marks them as a program when they define anything;vm.recvtakes bytes in. - Board:
({ ((1, 2) /o/add) /o/println }, "tcp://<address>:8889") /o/eval/atat the command line’s prompt sends the block over TCP, and the board runs it; Talk to a board is the walk. - Max: a message into the object; instantiating
o.se.<name>loads<name>.osefrom the search path, soo.se.o.routeloadso.route.ose. - Browser: whatever arrives on the page’s socket lands in the machine’s input.
A running machine
("host:port") /continue/at moves the running program to that address;
the rest of it runs on the far side, and a name it bound before the move
is bound after it too.
A program leaves one window and finishes in another
shows it, and A line fails at the prompt, and you fix it
there is the kept machine, looked
at and repaired without leaving the prompt.
("/name", "host:port") /continue/copy sends a copy of a loop, its state
with it; the far end files it under the same name, where it carries on
from its count, and the original runs on. A loop whose period fails is
parked where it is, as it was at the fault, and a copy of it goes
anywhere a machine goes: fixed at a prompt or in a page, it returns with
(machine, "/name", "host:port") /o/machine/resume into the parked loop
of that name, which carries on from the step that failed.
Fix a loop that failed on a board
is the round trip, from a blank board.
Who is there
A node is anything on the network that answers the census: a program at
a prompt, examples/census.osen in unix.o.se, that listens on UDP
19993, asks the network who is there, and keeps a list of who answered
and for how long they said to hold them. Nothing on a node is built for
it but two names, /node/id and /addr/here: the question is a program
sent to the node, which reads its own list of loops and the count of its
names and sends them home. A board announces itself when it boots, a
prompt serving on 8888 says () /node/hello, and a patch with
[o.se.node 7401] in it answers like either. The view draws
that list as cards.
Transports
- UDP — every host but the browser: the command line (
/udp/*, fromo.se.udp), the board (8888 for a program, 8889 for a machine, replies on 8890), Max (udpreceive/udpsend), Python (udp.py). A datagram to the board carries about 1,440 bytes, and a program or a machine can be larger: the sender cuts anything over that into/chunkmessages, the board keeps the pieces in whatever order they arrive and acknowledges when it has them all, and a resend fills the gaps. That carries about 9 KB. Over TCP none of that is needed. - TCP, SLIP-framed —
o.se.tcpat the command line (/tcp/listen,/tcp/accept,/tcp/connect,/tcp/send,/tcp/recv), and the board’sESP32S3ResumeTCPsketch on 8889. No size limit, so a machine crosses it whole:tcp://host:portis a destination for/continue/atand for/o/eval/at, which sends a program to run in the machine that is there.tools/machine-get.sh,machine-put.shandprogram-put.shinunix.o.sefetch a parked machine off a board, send one back into its loop, and send a program whole. -
WebSocket — the bridge, a program in the language that comes with
o.se.ws: it carries datagrams to a browser tab as WebSocket frames and frames back out, byte for byte, to one destination over UDP or, fortcp://, as one SLIP frame. Start it at the command line’s prompt:("o.se.ws/bridge.osen") /o/load, (9999, 8080, "tcp://192.168.1.101:8889") /ws/bridgeor from a shell,
tools/ws-bridge.sh --to tcp://192.168.1.101:8889inunix.o.se, which is that line. Putws://localhost:8080in the page’s socket field and press Connect. One tab at a time; a machine that arrives before a tab has connected is held until one does. The bridge listens on this machine only, and admits a page only from an origin it allows;/ws/bridge/ontakes an address, for wider. - Serial, SLIP-framed —
o.se.serialat the command line (/o/serial/open,/o/serial/send,/o/serial/recv,/o/serial/serve), and a board on its USB cable:serial:///dev/ttyACM0is a destination for/o/eval/atand/continue/at. That is how a Teensy, a Pico or an ESP32-S3 without a network is reached, and how a Mega takes a program written in the instruction language. What a board prints comes up the same cable, and/o/serial/serveruns what a board sends home, as/o/servedoes for a datagram../o.se -f o.se.serial/monitor-osen.oseis a serial monitor at the prompt:("/dev/ttyACM0") /o/monitor/open, then/tx/d/13 : 1sets a pin and/tx/d/13 : []reads it.
From → to
| from \ to | command line | Max | browser | board | Python |
|---|---|---|---|---|---|
| command line | machine | program | machine, via the bridge | machine | program |
| Max | program | program | program, via the bridge | program | program |
| browser | machine, via the bridge | program, via the bridge | — | machine, via the bridge | program, via the bridge |
| board | machine | program | machine, via the bridge | machine | program |
| Python | program | program | program | program | program |
| any OSC tool | data | data | data, via the bridge | data | data |
machine: a running machine crosses and continues; program: a bundle
that runs at the far end; data: a bundle arrives as data; —: no
transport both ends share. A board on a USB cable is the board column
reached as serial:// instead of over WiFi.
Recipes
- Move a program between two shells
- Send a program to a board
- Send data to the command line
- A program from Python to the browser
- The browser and a board through the bridge