initial attempt at portal and contact
Some checks failed
Build and Deploy / build-linux (push) Failing after 1m41s
Build and Deploy / build-windows (CLANG64) (push) Failing after 9m19s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
Some checks failed
Build and Deploy / build-linux (push) Failing after 1m41s
Build and Deploy / build-windows (CLANG64) (push) Failing after 9m19s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
This commit is contained in:
@@ -234,7 +234,9 @@ tests = [
|
||||
'empty',
|
||||
'nota',
|
||||
'enet',
|
||||
'wota'
|
||||
'wota',
|
||||
'portalspawner',
|
||||
'overling'
|
||||
]
|
||||
|
||||
foreach file : tests
|
||||
|
||||
@@ -522,7 +522,6 @@ js.eval(DOCPATH, script)()
|
||||
var enet = use('enet')
|
||||
var util = use('util')
|
||||
var math = use('math')
|
||||
var crypto = use('crypto')
|
||||
|
||||
var $_ = {}
|
||||
|
||||
@@ -536,24 +535,19 @@ $_.clock = function(fn)
|
||||
var underlings = new Set()
|
||||
var overling = undefined
|
||||
|
||||
var host = enet.create_host()
|
||||
$_.host = host
|
||||
|
||||
console.log(`made a host with port ${host.port()}`)
|
||||
var host = enet.create_host({
|
||||
address:"127.0.0.1", // or any address like "x.x.x.x", or "broadcast" for 255.255.255.255 and "any" for o0
|
||||
port:0,
|
||||
channels:0,
|
||||
incoming_bandwidth:0,
|
||||
outgoing_bandwidth:0
|
||||
});
|
||||
|
||||
globalThis.$_ = $_
|
||||
|
||||
var portal = undefined
|
||||
|
||||
var receive_fn = undefined;
|
||||
|
||||
var ephemeralkeys = {}
|
||||
var knownsecrets = {}
|
||||
|
||||
$_.contact = function(callback, record)
|
||||
{
|
||||
|
||||
}
|
||||
var receive_fn
|
||||
|
||||
$_.connection = function(callback, actor, config) {
|
||||
var peer = actor.peer;
|
||||
@@ -582,7 +576,26 @@ $_.connection = function(callback, actor, config) {
|
||||
var portal = undefined
|
||||
$_.portal = function(fn, port)
|
||||
{
|
||||
console.log(`starting a portal on port ${port}`)
|
||||
if (!port)
|
||||
throw new Error("Requires a valid port.");
|
||||
|
||||
$_.start(e => {
|
||||
switch(e.type) {
|
||||
case "actor_started":
|
||||
portal = e.actor
|
||||
break
|
||||
}
|
||||
portal = e
|
||||
}, undefined, {
|
||||
port
|
||||
});
|
||||
}
|
||||
|
||||
$_.contact = function(callback, record)
|
||||
{
|
||||
console.log(`connecting to ${json.encode(record)}`)
|
||||
host.connect(record.address, record.port)
|
||||
}
|
||||
|
||||
$_.receiver = function(fn)
|
||||
@@ -594,30 +607,31 @@ var greeters = {}
|
||||
|
||||
$_.start = function(cb, prg, arg)
|
||||
{
|
||||
var ephemeral = crypto.keypair()
|
||||
var guid = util.guid()
|
||||
greeters[guid] = cb
|
||||
ephemeralkeys[guid] = ephemeral
|
||||
os.createprocess([
|
||||
var argv = [
|
||||
"./prosperon",
|
||||
"spawn",
|
||||
"--program",prg,
|
||||
"--overling", $_.host.port(),
|
||||
"--overling", host.port,
|
||||
"--guid", guid,
|
||||
"--parentpub", ephemeral.public
|
||||
])
|
||||
]
|
||||
|
||||
if (prg)
|
||||
argv = argv.concat(['--program', prg])
|
||||
|
||||
if (arg)
|
||||
argv = argv.concat(cmd.encode(arg))
|
||||
|
||||
os.createprocess(argv)
|
||||
guid2actor.set(guid, {peer:undefined, guid:guid})
|
||||
}
|
||||
|
||||
$_.stop = function(actor)
|
||||
{
|
||||
if (!actor) {
|
||||
os.exit(0)
|
||||
}
|
||||
|
||||
actor.peer.send({
|
||||
type:"stop",
|
||||
})
|
||||
if (!actor)
|
||||
destroyself()
|
||||
|
||||
send_system(actor, {type:"stop"})
|
||||
}
|
||||
|
||||
var unneeded_fn = $_.stop
|
||||
@@ -644,91 +658,84 @@ $_.couple = function(actor)
|
||||
couplings.add(actor)
|
||||
}
|
||||
|
||||
use('cmd')(prosperon.argv)
|
||||
|
||||
var child_ephemeral
|
||||
|
||||
if (prosperon.overling) {
|
||||
$_.host.connect("localhost", prosperon.args.overling)
|
||||
function send_system(actor, message)
|
||||
{
|
||||
actor.peer.send({
|
||||
type:"system",
|
||||
data:message
|
||||
})
|
||||
}
|
||||
|
||||
if (prosperon.program)
|
||||
actor.spawn(prosperon.program)
|
||||
$_.send = function(actor, message, receive)
|
||||
{
|
||||
if (typeof message !== 'object')
|
||||
throw new Error('Must send an object record.')
|
||||
|
||||
actor.peer.send({ // right now only peers so this works
|
||||
type:"user",
|
||||
data: message
|
||||
})
|
||||
}
|
||||
|
||||
if (prosperon.args.parentpub)
|
||||
child_ephemeral = crypto.keypair()
|
||||
else if (prosperon.overling)
|
||||
console.warn("No parentpub provided; secure handshake won't proceed!");
|
||||
var cmd = use('cmd')
|
||||
cmd.process(prosperon.argv)
|
||||
|
||||
if (!prosperon.guid) prosperon.guid = util.guid()
|
||||
if (prosperon.args.overling)
|
||||
host.connect("localhost", prosperon.args.overling)
|
||||
|
||||
var ar = 60 // seconds before reclamation
|
||||
if (prosperon.args.program)
|
||||
actor.spawn(prosperon.args.program)
|
||||
|
||||
if (!prosperon.args.guid)
|
||||
prosperon.guid = util.guid()
|
||||
else
|
||||
prosperon.guid = prosperon.args.guid;
|
||||
|
||||
var ar = 5 // seconds before reclamation
|
||||
|
||||
var unneeded_timer = $_.delay($_.stop, ar)
|
||||
|
||||
function handle_receive(e)
|
||||
function destroyself()
|
||||
{
|
||||
var data = e.data
|
||||
switch(data.type) {
|
||||
case "handshake":
|
||||
var ep = ephemeralkeys[data.guid]
|
||||
if (!ep)
|
||||
throw new Error(`No stored ephemeral keypair found for guid=${data.guid}. Cannot do secure handshake.`)
|
||||
|
||||
var parent_private = ep.private
|
||||
if (!data.child_public)
|
||||
throw new Error("No child public key found in handshake message.")
|
||||
|
||||
var shared = crypto.shared({public:data.child_public, private: ep.private})
|
||||
knownsecrets[data.guid] = shared
|
||||
console.log("Sending handshake ok ..")
|
||||
e.peer.send({
|
||||
type: "handshake_ok",
|
||||
guid:data.guid
|
||||
})
|
||||
break;
|
||||
|
||||
case "handshake_ok":
|
||||
if (!child_ephemeral)
|
||||
throw new Error("We didn't generate a child ephemeral key. Something is off. Not deriving a shared secret!")
|
||||
|
||||
if (!prosperon.args.parentpub)
|
||||
throw new Error("No parent's ephemeral public key was provided. Cannot continue with shared secret.")
|
||||
|
||||
if (!data.guid)
|
||||
throw new Error("handshake_ok message missing guid. We won't store the shared secret.")
|
||||
|
||||
console.log("got handshake ok")
|
||||
knownsecrets[data.guid] = crypto.shared({public:prosperon.args.parentpub, private: child_ephemeral.private})
|
||||
|
||||
break;
|
||||
|
||||
case "greet":
|
||||
if (greeters[data.guid]) {
|
||||
var actor = guid2actor.get(data.guid)
|
||||
if (!actor) throw new Error(`No registered actor for guid ${data.guid}`)
|
||||
actor.peer = e.peer
|
||||
guid2actor.set(e.peer, actor)
|
||||
greeters[data.guid]({
|
||||
type: "greet",
|
||||
data: actor
|
||||
})
|
||||
greeters[data.guid] = undefined
|
||||
}
|
||||
break
|
||||
case "stop":
|
||||
console.log("STOPPING!")
|
||||
os.exit(0)
|
||||
}
|
||||
host.broadcast({type:"system", data:{
|
||||
type:"disconnect"
|
||||
}})
|
||||
host.flush()
|
||||
os.exit(0)
|
||||
}
|
||||
|
||||
function handle_actor_disconnect(actor)
|
||||
{
|
||||
if (couplings.has(actor))
|
||||
$_.stop()
|
||||
|
||||
guid2actor.delete(actor.guid)
|
||||
guid2actor.delete(actor.peer)
|
||||
if (couplings.has(actor)) {
|
||||
console.log(`I was connected to it, so I'm dying`)
|
||||
$_.stop()
|
||||
}
|
||||
|
||||
function handle_system(e)
|
||||
{
|
||||
var msg = e.data.data
|
||||
switch(msg.type) {
|
||||
case "disconnect":
|
||||
handle_actor_disconnect(guid2actor.get(e.peer))
|
||||
break
|
||||
|
||||
case "stop":
|
||||
destroyself()
|
||||
break
|
||||
|
||||
case "greet":
|
||||
if (greeters[msg.guid]) {
|
||||
var actor = guid2actor.get(msg.guid)
|
||||
if (!actor) throw new Error(`No registered actor for guid ${msg.guid}`)
|
||||
actor.peer = e.peer
|
||||
guid2actor.set(e.peer, actor)
|
||||
greeters[msg.guid]({
|
||||
type: "actor_started",
|
||||
actor
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -738,32 +745,35 @@ while (1) {
|
||||
unneeded_timer()
|
||||
unneeded_timer = $_.delay(unneeded_fn, unneeded_time)
|
||||
}, hang)
|
||||
|
||||
host.service(e => {
|
||||
unneeded_timer()
|
||||
switch(e.type) {
|
||||
case "connect":
|
||||
if (child_ephemeral) {
|
||||
console.log(`Child connected. Sending handshake ...`)
|
||||
e.peer.send({
|
||||
type: "handshake",
|
||||
guid: prosperon.guid,
|
||||
child_public: child_ephemeral.public
|
||||
})
|
||||
} else {
|
||||
console.log(`connected. sending greet with guid ${prosperon.guid} to peer ${e.peer}`)
|
||||
e.peer.send({
|
||||
type: "greet",
|
||||
console.log(`message arrived at ${host.address}:${host.port} from somebody ... ${e.peer.address}:${e.peer.port}`)
|
||||
e.peer.send({
|
||||
type:"system",
|
||||
data: {
|
||||
type:"greet",
|
||||
guid: prosperon.guid
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
break;
|
||||
|
||||
case "receive":
|
||||
handle_receive(e);
|
||||
if (e.data.type === "system")
|
||||
handle_system(e)
|
||||
else if(receive_fn)
|
||||
receive_fn(e.data.data)
|
||||
else
|
||||
console.log(`Got a messge but no receiver is registered.`)
|
||||
|
||||
break;
|
||||
|
||||
case "disconnect":
|
||||
greeters[guid2actor.get(e.peer).guid]({
|
||||
type: "actor_stopped"
|
||||
})
|
||||
handle_actor_disconnect(guid2actor.get(e.peer))
|
||||
break
|
||||
}
|
||||
|
||||
@@ -146,17 +146,25 @@ function parse_args(argv)
|
||||
return args;
|
||||
}
|
||||
|
||||
function unparse_args(args) {
|
||||
var argv = [];
|
||||
for (var key in args) {
|
||||
if (args.hasOwnProperty(key)) {
|
||||
argv.push("--" + key); // Add the flag with "--" prefix
|
||||
if (args[key] !== true) {
|
||||
argv.push(args[key]); // Add the value if it's not a boolean true flag
|
||||
}
|
||||
}
|
||||
}
|
||||
return argv;
|
||||
}
|
||||
|
||||
Cmdline.register_order(
|
||||
"spawn",
|
||||
function(argv) {
|
||||
prosperon.args = parse_args(argv)
|
||||
if (!prosperon.args.program)
|
||||
os.exit()
|
||||
|
||||
prosperon.guid = prosperon.args.guid
|
||||
prosperon.overling = prosperon.args.overling
|
||||
prosperon.program = prosperon.args.program
|
||||
prosperon.parentpub = prosperon.args.parentpub
|
||||
},
|
||||
"Spawn a new prosperon actor.",
|
||||
"TOPIC"
|
||||
@@ -212,4 +220,8 @@ function cmd_args(cmds) {
|
||||
Cmdline.orders[cmds[0]](cmds.slice(1));
|
||||
}
|
||||
|
||||
return cmd_args;
|
||||
return {
|
||||
process: cmd_args,
|
||||
encode: parse_args,
|
||||
decode: unparse_args,
|
||||
}
|
||||
|
||||
@@ -7667,8 +7667,6 @@ static inline void to_hex(const uint8_t *in, size_t in_len, char *out)
|
||||
out[2 * in_len] = '\0'; // null-terminate
|
||||
}
|
||||
|
||||
#include <ctype.h> // for isxdigit
|
||||
|
||||
static inline int nibble_from_char(char c, uint8_t *nibble)
|
||||
{
|
||||
if (c >= '0' && c <= '9') { *nibble = (uint8_t)(c - '0'); return 0; }
|
||||
@@ -7688,9 +7686,6 @@ static inline int from_hex(const char *hex, uint8_t *out, size_t out_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <string.h> // for size_t, memcpy
|
||||
#include "quickjs.h"
|
||||
|
||||
// Convert a JSValue containing a 64-character hex string into a 32-byte array.
|
||||
static inline void js2crypto(JSContext *js, JSValue v, uint8_t *crypto)
|
||||
{
|
||||
|
||||
@@ -46,69 +46,113 @@ static JSValue js_enet_deinitialize(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
/* Host creation */
|
||||
static JSValue js_enet_host_create(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv) {
|
||||
int argc, JSValueConst *argv) {
|
||||
ENetHost *host;
|
||||
ENetAddress address;
|
||||
JSValue obj;
|
||||
|
||||
// Default configuration matching the JavaScript object
|
||||
size_t peer_count = 32; // peer_count: 32
|
||||
size_t channel_limit = 0; // channel_limit: 0
|
||||
enet_uint32 incoming_bandwidth = 0; // incoming_bandwidth: 0
|
||||
enet_uint32 outgoing_bandwidth = 0; // outgoing_bandwidth: 0
|
||||
// Default parameters (if not provided by user)
|
||||
size_t peer_count = 32;
|
||||
size_t channel_limit = 0;
|
||||
enet_uint32 incoming_bandwidth = 0;
|
||||
enet_uint32 outgoing_bandwidth = 0;
|
||||
|
||||
if (argc < 1) {
|
||||
// Create client-like host with port 0 and "any" address
|
||||
// If no arguments or first arg is not an object, create a client-like host.
|
||||
if (argc < 1 || !JS_IsObject(argv[0])) {
|
||||
address.host = ENET_HOST_ANY;
|
||||
address.port = 0;
|
||||
host = enet_host_create(&address, peer_count, channel_limit,
|
||||
incoming_bandwidth, outgoing_bandwidth);
|
||||
|
||||
host = enet_host_create(&address,
|
||||
peer_count,
|
||||
channel_limit,
|
||||
incoming_bandwidth,
|
||||
outgoing_bandwidth);
|
||||
if (!host) {
|
||||
return JS_ThrowInternalError(ctx, "Failed to create ENet host (any address).");
|
||||
return JS_ThrowInternalError(ctx, "Failed to create ENet host with 'any:0'.");
|
||||
}
|
||||
goto RET;
|
||||
}
|
||||
|
||||
// If argument is provided, interpret as "ip:port" for server
|
||||
const char *address_str = JS_ToCString(ctx, argv[0]);
|
||||
if (!address_str)
|
||||
return JS_EXCEPTION; // memory or conversion error
|
||||
|
||||
char ip[64];
|
||||
int port;
|
||||
// Now parse the object
|
||||
JSValue configObj = argv[0];
|
||||
|
||||
if (sscanf(address_str, "%63[^:]:%d", ip, &port) != 2) {
|
||||
JS_FreeCString(ctx, address_str);
|
||||
return JS_ThrowTypeError(ctx, "Invalid address format. Expected 'ip:port'.");
|
||||
// 1) address
|
||||
JSValue addrVal = JS_GetPropertyStr(ctx, configObj, "address");
|
||||
const char *addrStr = NULL;
|
||||
if (JS_IsString(addrVal)) {
|
||||
addrStr = JS_ToCString(ctx, addrVal);
|
||||
}
|
||||
JS_FreeCString(ctx, address_str);
|
||||
JS_FreeValue(ctx, addrVal);
|
||||
|
||||
if (strcmp(ip, "any") == 0)
|
||||
// If address not given or not string, default to "any".
|
||||
if (!addrStr) {
|
||||
addrStr = "any";
|
||||
}
|
||||
|
||||
// 2) port
|
||||
JSValue portVal = JS_GetPropertyStr(ctx, configObj, "port");
|
||||
int32_t port32 = 0;
|
||||
JS_ToInt32(ctx, &port32, portVal); // if invalid or undefined, remains 0
|
||||
JS_FreeValue(ctx, portVal);
|
||||
|
||||
// 3) channels -> channel_limit
|
||||
JSValue chanVal = JS_GetPropertyStr(ctx, configObj, "channels");
|
||||
JS_ToUint32(ctx, &channel_limit, chanVal); // default 0 if missing
|
||||
JS_FreeValue(ctx, chanVal);
|
||||
|
||||
// 4) incoming_bandwidth
|
||||
JSValue inBWVal = JS_GetPropertyStr(ctx, configObj, "incoming_bandwidth");
|
||||
JS_ToUint32(ctx, &incoming_bandwidth, inBWVal);
|
||||
JS_FreeValue(ctx, inBWVal);
|
||||
|
||||
// 5) outgoing_bandwidth
|
||||
JSValue outBWVal = JS_GetPropertyStr(ctx, configObj, "outgoing_bandwidth");
|
||||
JS_ToUint32(ctx, &outgoing_bandwidth, outBWVal);
|
||||
JS_FreeValue(ctx, outBWVal);
|
||||
|
||||
// Populate ENetAddress
|
||||
if (strcmp(addrStr, "any") == 0) {
|
||||
address.host = ENET_HOST_ANY;
|
||||
else if (strcmp(ip, "broadcast"))
|
||||
address.host = ENET_HOST_BROADCAST;
|
||||
else {
|
||||
int err = enet_address_set_host_ip(&address, ip);
|
||||
} else if (strcmp(addrStr, "broadcast") == 0) {
|
||||
address.host = ENET_HOST_BROADCAST;
|
||||
} else {
|
||||
int err = enet_address_set_host_ip(&address, addrStr);
|
||||
if (err != 0) {
|
||||
return JS_ThrowInternalError(ctx, "Failed to set host IP from %s. Error %d.", ip, err);
|
||||
// Free addrStr only if it came from JS_ToCString
|
||||
if (addrStr && addrStr != "any" && addrStr != "broadcast") {
|
||||
JS_FreeCString(ctx, addrStr);
|
||||
}
|
||||
return JS_ThrowInternalError(
|
||||
ctx, "Failed to set host IP from '%s'. Error code: %d", addrStr, err
|
||||
);
|
||||
}
|
||||
}
|
||||
address.port = port;
|
||||
address.port = (enet_uint16) port32;
|
||||
|
||||
// Create host with specified configuration
|
||||
host = enet_host_create(&address, peer_count, channel_limit, incoming_bandwidth, outgoing_bandwidth);
|
||||
// Now that we're done using addrStr, free it if it was allocated.
|
||||
if (addrStr && addrStr != "any" && addrStr != "broadcast") {
|
||||
JS_FreeCString(ctx, addrStr);
|
||||
}
|
||||
|
||||
// Finally, create the host
|
||||
host = enet_host_create(&address,
|
||||
peer_count,
|
||||
channel_limit,
|
||||
incoming_bandwidth,
|
||||
outgoing_bandwidth);
|
||||
if (!host) {
|
||||
return JS_ThrowInternalError(ctx, "Failed to create ENet host.");
|
||||
}
|
||||
|
||||
RET:
|
||||
// Wrap up in a QuickJS object
|
||||
obj = JS_NewObjectClass(ctx, enet_host_id);
|
||||
if (JS_IsException(obj)) {
|
||||
enet_host_destroy(host);
|
||||
return obj;
|
||||
}
|
||||
// Associate our C pointer with this JS object
|
||||
JS_SetOpaque(obj, host);
|
||||
return obj;
|
||||
}
|
||||
@@ -464,8 +508,8 @@ static const JSCFunctionListEntry js_enet_host_funcs[] = {
|
||||
JS_CFUNC_DEF("connect", 2, js_enet_host_connect),
|
||||
JS_CFUNC_DEF("flush", 0, js_enet_host_flush),
|
||||
JS_CFUNC_DEF("broadcast", 1, js_enet_host_broadcast),
|
||||
JS_CFUNC_DEF("port", 0, js_enet_host_get_port),
|
||||
JS_CFUNC_DEF("address", 0, js_enet_host_get_address),
|
||||
JS_CGETSET_DEF("port", js_enet_host_get_port, NULL),
|
||||
JS_CGETSET_DEF("address", js_enet_host_get_address, NULL),
|
||||
};
|
||||
|
||||
/* Getter for roundTripTime (rtt) */
|
||||
@@ -584,6 +628,30 @@ static JSValue js_enet_peer_get_reliable_data_in_transit(JSContext *ctx, JSValue
|
||||
return JS_NewInt32(ctx, peer->reliableDataInTransit);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_port(JSContext *js, JSValueConst self)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(self, enet_peer_class_id);
|
||||
return JS_NewUint32(js, peer->address.port);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_address(JSContext *js, JSValueConst self)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(self, enet_peer_class_id);
|
||||
uint32_t host = ntohl(peer->address.host);
|
||||
|
||||
if (host == 0x7F000001)
|
||||
return JS_NewString(js, "localhost");
|
||||
|
||||
char ip_str[16]; // Enough space for "255.255.255.255" + null terminator
|
||||
snprintf(ip_str, sizeof(ip_str), "%u.%u.%u.%u",
|
||||
(host >> 24) & 0xFF,
|
||||
(host >> 16) & 0xFF,
|
||||
(host >> 8) & 0xFF,
|
||||
host & 0xFF);
|
||||
|
||||
return JS_NewString(js, ip_str);
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_enet_peer_funcs[] = {
|
||||
JS_CFUNC_DEF("send", 1, js_enet_peer_send),
|
||||
JS_CFUNC_DEF("disconnect", 0, js_enet_peer_disconnect),
|
||||
@@ -605,6 +673,8 @@ static const JSCFunctionListEntry js_enet_peer_funcs[] = {
|
||||
JS_CGETSET_DEF("packet_loss", js_enet_peer_get_packet_loss, NULL),
|
||||
JS_CGETSET_DEF("state", js_enet_peer_get_state, NULL),
|
||||
JS_CGETSET_DEF("reliable_data_in_transit", js_enet_peer_get_reliable_data_in_transit, NULL),
|
||||
JS_CGETSET_DEF("port", js_enet_peer_get_port, NULL),
|
||||
JS_CGETSET_DEF("address", js_enet_peer_get_address, NULL),
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
|
||||
8
tests/contact.js
Normal file
8
tests/contact.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// Test to connect to a portal
|
||||
|
||||
$_.contact((actor, reason) => {
|
||||
}, {
|
||||
address: "localhost",
|
||||
port: 5678,
|
||||
password: "abc123"
|
||||
});
|
||||
@@ -2,18 +2,19 @@ var os = use('os')
|
||||
|
||||
$_.start(e => {
|
||||
switch(e.type) {
|
||||
case "greet":
|
||||
console.log(`parent got message from child with greet.`)
|
||||
$_.connection(e => console.log(json.encode(e)), e.data)
|
||||
case "actor_started":
|
||||
console.log(`parent got system level actor_started msg`)
|
||||
$_.connection(e => console.log(json.encode(e)), e.actor) // get connection info
|
||||
|
||||
$_.send(e.actor, {message: "Hello!"})
|
||||
|
||||
$_.delay(_ => {
|
||||
console.log(`sending stop message to ${json.encode(e.data)}`)
|
||||
$_.stop(e.data)
|
||||
console.log(`sending stop message to ${json.encode(e.actor)}`)
|
||||
$_.stop(e.actor)
|
||||
}, 1);
|
||||
$_.couple(e.data)
|
||||
|
||||
$_.couple(e.actor)
|
||||
}
|
||||
}, "tests/underling.js");
|
||||
|
||||
$_.contact((actor, reason) => {
|
||||
}, {
|
||||
address: "localhost",
|
||||
});
|
||||
|
||||
|
||||
9
tests/portal.js
Normal file
9
tests/portal.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Test to create a portal
|
||||
|
||||
var password = "abc123"
|
||||
|
||||
$_.portal(e => {
|
||||
console.log(`received a message for contact: ${json.encode(e)}`)
|
||||
if (e.password !== password)
|
||||
throw new Error("Password does not match.");
|
||||
}, 5678);
|
||||
19
tests/portalspawner.js
Normal file
19
tests/portalspawner.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// Creates a portal and a separate actor to contact
|
||||
|
||||
var os = use('os')
|
||||
|
||||
var children = []
|
||||
|
||||
$_.start(e => {
|
||||
console.log('Portal actor finished starting.')
|
||||
children.push(e.actor)
|
||||
$_.start(e => {
|
||||
children.push(e.actor)
|
||||
console.log('Contact actor finished starting.')
|
||||
}, "tests/contact.js")
|
||||
}, "tests/portal.js")
|
||||
|
||||
$_.delay(_ => {
|
||||
for (var c of children) $_.stop(c)
|
||||
$_.stop()
|
||||
}, 3)
|
||||
@@ -1,3 +1,5 @@
|
||||
var os = use('os')
|
||||
|
||||
console.log(`started underling`)
|
||||
$_.receiver(e => {
|
||||
console.log(`got message: ${json.encode(e)}`)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user