Protocol Buffers over WebSockets¶
This communication protocol allows web browsers to communicate with kRPC over a websockets connection, for example from Javascript in a web browser.
Note
If a client library is available for your language, you do not need to implement this protocol.
Connecting to the RPC Server¶
A client invokes remote procedures by communicating with the RPC server. To establish a
connection, open a websockets connection to the server on its RPC port (which defaults to
50000). The connection URI can also contain a name
parameter with the name of the client to
display in the on the in-game UI. For example: ws://localhost:50000/?name=Jeb
Connecting to the Stream Server¶
Clients can receive Streams from the stream server. To establish a connection, a client must first connect to the RPC server (as above) then do the following:
Get the identifier of the client by calling the
KRPC.GetClientID
remote procedure.Open a websockets connection to the server on its stream port (which defaults to 50001), with an
id
query parameter set to the client identifier encoded in base64. For example:ws://localhost:50001/?id=Eeh8Vbj2DkWTcJZTkYlEhQ==
Connecting to the stream server is optional. If the client doesn’t require stream functionality, there is no need to connect.
Sending and Receiving Messages¶
Communication with the server is performed via Protocol Buffer messages, encoded according to the protobuf binary format.
To send a message to the server:
Encode the message using the Protocol Buffers format.
Send a binary websockets message to the server, with payload containing the encoded message data.
To receive a message from the server, do the reverse:
Receive a binary websockets message from the server.
Decode the messages payload using the Protocol Buffers format.
Invoking Remote Procedures¶
See Messaging Protocol.
Examples¶
The following code connects to the RPC server at address 127.0.0.1 and port 50000 using
the name “Jeb”. Next, it connects to the stream server on port 50001. It then invokes the
KRPC.GetStatus
RPC, receives and decodes the result and prints out the server version number
from the response.
var websocket = require('ws');
var protobufjs = require('protobufjs')
var ByteBuffer = require('bytebuffer')
var proto = protobufjs.loadProtoFile('krpc.proto').build();
console.log('Connecting to RPC server')
let rpcConn = new websocket('ws://127.0.0.1:50000')
rpcConn.binaryType = 'arraybuffer'
rpcConn.onopen = (e) => {
console.log('Successfully connected')
let call = new proto.krpc.schema.ProcedureCall('KRPC', 'GetStatus');
let request = new proto.krpc.schema.Request([call]);
rpcConn.send(request.toArrayBuffer());
rpcConn.onmessage = (e) => {
let response = proto.krpc.schema.Response.decode(e.data)
let status = proto.krpc.schema.Status.decode(response.results[0].value)
console.log(status);
process.exit(0);
};
};
The following example demonstrates how to set up and receive data from the server over a stream:
'use strict'
var websocket = require('ws');
var protobufjs = require('protobufjs')
var proto = protobufjs.loadProtoFile('krpc.proto').build();
console.log('Connecting to RPC server')
let rpcConn = new websocket('ws://127.0.0.1:50000')
rpcConn.binaryType = 'arraybuffer'
rpcConn.onopen = (evnt) => {
console.log('Successfully connected')
console.log('Calling KRPC.GetClientID')
let call = new proto.krpc.schema.ProcedureCall('KRPC', 'GetClientID');
let request = new proto.krpc.schema.Request([call]);
rpcConn.send(request.toArrayBuffer());
};
rpcConn.onmessage = (evnt) => {
let response = proto.krpc.schema.Response.decode(evnt.data);
response.results[0].value.readVarint32(); // skip size
let client_identifier = response.results[0].value.toBase64();
console.log('Client identifier =', client_identifier);
console.log('Connecting to Stream server');
let streamConn = new websocket('ws://127.0.0.1:50001?id=' + client_identifier);
streamConn.binaryType = 'arraybuffer';
streamConn.onopen = (evnt) => {
console.log('Successfully connected');
let call_to_stream = new proto.krpc.schema.ProcedureCall('KRPC', 'GetStatus');
let arg = new proto.krpc.schema.Argument(0, call_to_stream.toArrayBuffer());
let call = new proto.krpc.schema.ProcedureCall('KRPC', 'AddStream', [arg]);
let request = new proto.krpc.schema.Request([call]);
rpcConn.send(request.toArrayBuffer());
rpcConn.onmessage = (evnt) => {
let response = proto.krpc.schema.Response.decode(evnt.data);
let stream = proto.krpc.schema.Stream.decode(response.results[0].value);
console.log("added stream id =", stream.id.toString());
};
};
streamConn.onmessage = (evnt) => {
let value = new proto.krpc.schema.StreamUpdate.decode(evnt.data);
let status = proto.krpc.schema.Status.decode(value.results[0].result.value)
console.log(status);
};
};