thox process API¶
When started, every process has access to the utilities described in the Lua 5.3 manual.
Events¶
-
class
os.
Event
¶ An event as seen by the user process.
-
type
: string¶ The event type; see derivative classes.
-
Events can be one of the following:
-
class
os.
CallEvent
: Event¶ An event emitted when receiving a call from another process through RPC.
-
type
: string¶ The event type, set to
"call"
.
-
cid
: number¶ The Call IDentifier (CID) to which to answer.
-
ctx
: number¶ The context identifier from which the call was emitted.
-
name
: string¶ The name which was used to emit the call to the current process.
-
pid
: number¶ The Process IDentifier (PID) of the process which has emitted the call.
-
args
: table¶ The arguments to the function, as a sequence.
-
-
class
os.
AnswerEvent
: Event¶ An event emitted when receiving an answer to a call emitted previously.
-
type
: string¶ The event type, set to
"answer"
.
-
cid
: number¶ The Call IDentifier (CID) of the answered call.
-
args
: table¶ The arguments returned by the process.
-
-
class
os.
OpenEvent
: Event¶ An event produced when a process opens a context owned by the current process (when not shared by the current process).
-
type
: string¶ The event type, set to
"open"
.
-
ctx
: number¶ The identifier of the context which was shared.
-
pid
: number¶ The Process IDentifier (PID) of the process which has gained access to the context.
-
-
class
os.
CloseEvent
: Event¶ An event produced when a process closes a context owned by the current process (when not closed by the current process).
-
type
: string¶ The event type, set to
"close"
.
-
ctx
: number¶ The identifier of the context which was shared.
-
pid
: number¶ The Process IDentifier (PID) of the process which has gained access to the context.
-
For answers, the first argument is always the status as a number. The standardized statuses are the following:
-
class
os.
status
¶ A status code.
-
OK
: number¶ The status returned when no error has occurred.
-
UNBOUND
: number¶ The status returned when an error has occurred; notice that while this status is usually returned by the system, it can also be set by the process at the other end.
-
These events are produced by the following function:
-
os.
pull
([filter[, ...]])¶ Pull the next event out of the event queue for the process.
The filters are tables containing expected values to filter the event with.
For example, the following snippet waits for either:
an answer for the calls 4 and 5;
a new call.
local event = os.pull({type = "answer", cid = 4}, {type = "answer", cid = 5}, {type = "call"})
When requiring a specific event, other events will stay in the queue for the next call asking specifically for it in the queue.
- Parameters
filter (table) – The filter as a table with the expected values.
- Returns
The next event out of the event queue.
- Return type
An
Event
.
Asynchronous RPC¶
-
os.
call
(ctx, name, ...)¶ - Parameters
ctx (number) – A valid context identifier.
name (str) – A valid procedure name.
- Returns
The generated Call IDentifier, or
nil
if an error has occurred.- Return type
number
-
os.
answer
(cid, ...)¶ Answer a call with arguments.
Todo
The arguments to the call are something like this:
os.answer(1, {2}, {"string value"}, {{key = "value"}}, {2, "ctx"})
Or another format, because we need to distinguish between “normal” values and context sharing, and maybe other things as well. Maybe we could allow a second argument “transformations”, e.g.:
os.answer(1, nil, 2, "string value", {key = "value"}) os.answer(1, "4c", 2, "string value", {key = "value"}, 2)
I don’t know yet; the fact is, we need to inform the kernel when we’re delegating a context through an answer…
- Parameters
cid (number) – A valid Call IDentifier (CID).
-
os.
transmit
(ctx, name, cid[, pid])¶ Transmit a call to another process bound to a given name on a given context.
This function is an optimization: instead of having to make the call to the parent process and waiting for the answer to retransmit it to the end process, this actually sends the same call event (with the context and name replaced to correspond to this function’s arguments) to the bound process, which will then answer directly to the client process; the CID is therefore closed from the current process’s point of view when the call is transmitted.
The
pid
parameter serves mostly when the call is not transmitted to the context owner specifically. This mostly serves for context-managing processes that support bindings, for them to transmit calls to children on a context they have created.Todo
For now, we stay on the
os.transmit
logic, but soon we’ll see that this approach may be slow when there are multiple levels of sandboxing. So what we could do is, have a nftables-like approach where a process owning a context configures routing for calls on the context (based on origin, name, why not arguments as well?), and the kernel doesn’t need to call this process to route, whereas with theos.transmit
we need to and this may be slow.However this is the complicated approach, for now we’ll stick with the simpler approach as a PoC.
- Parameters
ctx (number) – A valid context identifier.
name (str) – A valid RPC name.
cid (number) – A valid Call IDentifier (CID).
pid (number) – The optional PID of the process to which the call should be transmitted on the given context.
Synchronous RPC¶
-
class
os.
RPCProxy
¶ An RPC proxy object, which allows you to make synchronous RPC calls, on a given context. By calling this object, you emit a system call to the given name, and wait for an answer.
Examples usages of this object are the following:
local status, div, rem = os.rpc.math.div(10, 3) -- is the equivalent of: local status, div, rem do local cid = os.call(0, "math.div", 10, 3) local status status, div, rem = os.pull({ type = "answer", cid = cid}) end
-
any
: RPCProxy¶ Indexing the object gives you an RPC proxy object, on the same context and with a prefixed name, which you can call the same.
-
This class is instanciated as the following object:
-
class
os.
rpc
: RPCProxy¶ The basic RPC proxy object, with a blank namespace.