-
Notifications
You must be signed in to change notification settings - Fork 67
Description
Load81 programs are currently self-contained into a box without the ability to talk with the external world.
Specifically they can't talk with other instances of the same program running in other Load81 instances around the world! What a shame. So what I'm proposing and implementing is a Cloud message service for Load81.
API
A Load81 program listen to channels using the listen() function. Multiple calls to listen are allowed in order to listen to multiple channels, and it is also possible to no longer listen to a given channel using unlisten(). Example:
listen("asteroids")
listen("foo","bar")
unlisten("asteroids")
Every time a message is received the function receive is called. It is important to understand how this works. The normal flow of a Load81 program is to call setup the first time, and then call draw. When the program is listening to one or more channels, the function receive is called before the function draw is called, and is called for all the pending messages currently in the queue, so for instance you may have 5 calls to receive, and finally the call to draw, and so forth.
This is how the function receive is defined in a program:
function receive(sender,channel,msg)
....
end
The three arguments are:
- sender: a 40 chars hex string that uniquely identifies the sender instance (this instance ID changes at every run).
- channel: the channel that received the message.
- msg: a Lua object (number, string, table, boolean, ...)
You don't receive messages that are sent by your instance.
In order to send messages you simply use:
send("channel",lua_object)
You can send messages to channels you are not listening without problems if you wish.
Implementation
The implementation using a Redis instance running at pubsub.load81.com, with only PUBLISH and SUBSCRIBE commands enabled. The instance is configured to drop clients that reached an output buffer of a few hundred kbytes so that it is not possible to abuse the instance just listening to channels without actually reading data.
Every Load81 instance creates a random identifier at startup, either reading from /dev/urandom or using a mix of time and rand() if urandom is not available.
Messages are send to Redis as <Instance ID>:<MessagePack representation of the Lua object sent>
.
Messages are both sent and received using a non blocking socket. At every iteration we read what's new in the socket, and call a function that will put all the entire messages in the queue, parsing the Redis protocol.
From the point of view of sending, we'll try to send messages every time the user calls the send() function in order to minimize latency, but if there is no room on the kernel socket buffer we'll bufferize the write and send it when possible (at the next iteration of the event processor, that is, by default, 30 times per second).
Abuses
From the outside attacker this is a free message hub, but I think it's fine since for instance an IRC server has the same problem.... and I think no one will try to abuse this stuff, at least I hop.