sock-rpc
v1.0.8
Published
RPC server for Arma 3, that can be used with the sock.dll extension
Downloads
8
Readme
[TOC]
sock-rpc#
- This a Node.js module that implements an RPC server on top wire-protocol from Arma 3 sock.dll extension.
Changelog
- 1.0.8
- Fix broken typeof2 function
- Add test case for rawToJSON
- 1.0.7
- Pull fix for Context from @Fusselwurm
- 1.0.6
- Fix bug where
1.#QNAN
value was not being parsed correctly
- Fix bug where
- 1.0.5
- Fix bug where booleans where not being handled when using RAW SQF format
- 1.0.4
- Add support for requests formatted as Raw SQF (to help with client-side performance)
- Add support command line arguments --trace-req
- 1.0.3
- Add support command line arguments --trace-send, and --trace-recv
- Extend the high level RPC protocol to allow passing "accept" property (supports "application/sqf", and "application/json")
- Add Client class that can be used to communicate with a remote sock-rpc server
- 1.0.1 - Major version bump due to design changes in callback mechanism
- Added SEVERE level logging to show the the actual JSON string when parsing error happens
- 1.0.0 - Major version bump due to design changes in callback mechanism
- Improved logging using the util-logging module
- Improved command line processing using yargs module
- Design change: callback passed into registered RPC functions are now always the last argument
- Design change: callback passed into registered RPC functions have now the following signature: callback(err, result)
- 0.0.2 - Update to add license file
- 0.0.1 - Initial release
Prerequisites
- Download and install Node.js
Installation
- From the head of the master branch
.
npm install -g git+https://bitbucket.org/micovery/sock-rpc.git
.
- From the npmjs.org repository
.
npm install -g sock-rpc
.
How to use
Create a Node.js JavaScript file (e.g. example.js) containing the functions to be used by the RPC server.
"use strict";
var rpc = require('sock-rpc');
/**
* Echo back all arguments passed.
* echo(...,callback);
*/
rpc.register("echo", function () {
var args = Array.prototype.slice.call(arguments, 0);
var callback = args.pop();
callback(null, args);
});
/**
* Get date (no arguments)
*/
rpc.register("getDate", function (callback) {
callback(null, new Date().toString());
});
rpc.listen();
.
All registered method's must use the callback mechanism to pass the result to the client, and by doing so indicate that the execution is complete.
If a method does not invoke the callback, the client side will likely hang while it waits for a response from the server.
.
In order to indicate that an error has happened, you can pass an error as the first argument to the callback.
.
callback(new Error("Cannot compute!"));
Starting the Server
The following commands shows how to start the RPC server on port 1337, and IPv6 loolback address ::1 using the Windows command-line.
set NODE_PATH=%AppData%\npm\node_modules
node example.js -port=1337 -host=::1
.
API
listen([host], [port])
host (type: string, optional) - Host name, or address to listen on
If not provided, it defaults to command line argument -host=
If -host is not provided, it defaults to localhost
.port (type: number, optional) - Port number to listen on
If not provided, it defaults to command line argument -port=
If -port is not provided, it defaults to a random available port
.
register(functions)
- functions (type: object, required) - An object containing functions
.
- functions (type: object, required) - An object containing functions
register(name, function)
name (type: string, required) - Host name, or address to listen on
function (type: function, required) - Function to register
.
Low-Level Protocol
At the lowest level, this module uses the SOCK-TCP wire-protocol from the sock.dll Arma 3 extension, acting as the server. .
//First, wait for client to send a request message
server: recv: request-header-foo (4 bytes, unsigned long, network byte order, length of the body that follows)
server: recv: request-body-foo (variable bytes, actual request message data)
//then send the response message
server: send: response-header-foo (4 bytes, unsigned long, network byte order, length of the body that follows)
server: send: response-body-foo (variable bytes, actual response message data)
.
That's pretty much it, server receives a request message, and replies with a response message.
.
- The server does not guarantee that response messages are sent to client matching the same order as the request messages.
- The client must either send only one request message at a time, and wait for the response ... or keep track of of the messages using sequence IDs.
- In Arma 3, the execution of extensions is single threaded. This guarantees that only one request packet is sent at a time.
- Client may send a zero-length request message. The server must ignore zero-length messages and continue on processing.
High-Level Protocol
At a high level, this module uses a protocol similar to JSON-RPC, for client requests.
For server responses, on the other hand, they are formatted as SQF code that can be compiled dynamically inside the game.
.
//First wait for client to send a JSON-RPC request
server: recv: {"method":"methodName", "params": ["param1", "param2"],...]}
//then send the SQF response
server: send: [false,"response"]
.
The response to a client request is always an SQF array with two elements.
[error-state, mapped-response-data]
.
error-state (type: boolean) - This is an indicator of whether or not an error occurred while processing the request.
- tue - if an error occurred processing the client's request
- false - if no error occurred processing the client's request
.
mapped-response-data
- The mapped-response-data, as the name indicates, is simply the output of the RPC invocation mapped into its equivalent SQF representation.
- When an error occurs (error-state is true), then mapped-response-data is an SQF string containing explanation of the error.
- If no error occurs, then the mapped-response-data can be of any SQF data type.
.