diff --git a/packages/controller/src/Controller.ts b/packages/controller/src/Controller.ts index e1e53293..f256da32 100644 --- a/packages/controller/src/Controller.ts +++ b/packages/controller/src/Controller.ts @@ -1351,10 +1351,10 @@ export default class Controller { throw Error(`Unknown type ${requestOrEvent.constructor.type}.`); } - async sendRequest(request: any, dst: lib.Address) { + sendRequest(request: any, dst: lib.Address) { let connection; if (dst.type === lib.Address.controller) { - throw new Error("controller as dst is not supported."); + throw new Error(`Message would return back to sender ${dst}.`); } else if (dst.type === lib.Address.control) { connection = this.wsServer.controlConnections.get(dst.id); @@ -1389,24 +1389,33 @@ export default class Controller { sendEvent(event: lib.Event, dst: lib.Address) { let connection; if (dst.type === lib.Address.controller) { - throw new Error("controller as dst is not supported."); + throw new Error(`Message would return back to sender ${dst}.`); } else if (dst.type === lib.Address.control) { connection = this.wsServer.controlConnections.get(dst.id); + if (!connection) { + throw new Error("Target control connection does not exist."); + } } else if (dst.type === lib.Address.instance) { let instance = this.instances.get(dst.id); if (!instance) { - return; + throw new Error(`Instance with ID ${dst.id} does not exist`); } let hostId = instance.config.get("instance.assigned_host"); if (hostId === null) { - return; + throw new Error("Instance is not assigned to a host"); } connection = this.wsServer.hostConnections.get(hostId); + if (!connection) { + throw new Error("Host containing instance is not connected"); + } } else if (dst.type === lib.Address.host) { connection = this.wsServer.hostConnections.get(dst.id); + if (!connection) { + throw new Error("Host is not connected"); + } } else if (dst.type === lib.Address.broadcast) { if (dst.id === lib.Address.control) { @@ -1424,7 +1433,7 @@ export default class Controller { } } else { - throw new Error(`Unexpected broacdast target ${dst.id}`); + throw new Error(`Unexpected broadcast target ${dst.id}`); } return; @@ -1432,9 +1441,7 @@ export default class Controller { throw new Error(`Unknown address type ${dst.type}`); } - if (connection) { - connection.sendEvent(event, dst); - } + connection.sendEvent(event, dst); } async sendToHostByInstanceId(request: Req & lib.Request): Promise; diff --git a/packages/lib/src/link/link.ts b/packages/lib/src/link/link.ts index 1d3d3381..ae91a4c8 100644 --- a/packages/lib/src/link/link.ts +++ b/packages/lib/src/link/link.ts @@ -538,6 +538,9 @@ export class Link { if (!entry) { throw new Error(`Attempt to send unregistered Request ${request.constructor.name}`); } + if (this.connector.src.equals(dst)) { + throw new Error(`Message would return back to sender ${dst}.`); + } if (this.validateSent) { entry.requestFromJSON(JSON.parse(JSON.stringify(request))); } @@ -572,6 +575,9 @@ export class Link { if (!entry) { throw new Error(`Attempt to send unregistered Event ${event.constructor.name}`); } + if (this.connector.src.equals(dst)) { + throw new Error(`Message would return back to sender ${dst}.`); + } if (this.validateSent) { entry.eventFromJSON(JSON.parse(JSON.stringify(event))); } diff --git a/test/integration/routing.js b/test/integration/routing.js index 22c5e0ad..7c5b204c 100644 --- a/test/integration/routing.js +++ b/test/integration/routing.js @@ -424,18 +424,10 @@ describe("Integration of link routing", function() { }); describe("event should not be routable on loopback", function() { - it("should not loopback on controller", async function() { - // Sending an event never returns a promise, so it throws rather than rejects like a request - assert.throws( - () => send(get("controller"), addr("controller"), new TestEvent()), - new Error("controller as dst is not supported.") - ); - }); - - for (const srcName of ["hostA", "instanceA1", "controlA"]) { + for (const srcName of ["controller", "hostA", "instanceA1", "controlA"]) { it(`should not loopback on ${srcName}`, async function() { const src = get(srcName); - const dstAddr = src.connector.src; + const dstAddr = src instanceof Controller ? addr("controller") : src.connector.src; assert.throws( () => send(src, dstAddr, new TestEvent()), new Error(`Message would return back to sender ${dstAddr}.`) @@ -445,18 +437,11 @@ describe("Integration of link routing", function() { }); describe("request should not be routable on loopback", function() { - it("should not loopback on controller", async function() { - await assert.rejects( - () => send(get("controller"), addr("controller"), new TestRequest()), - new Error("controller as dst is not supported.") - ); - }); - - for (const srcName of ["hostA", "instanceA1", "controlA"]) { + for (const srcName of ["controller", "hostA", "instanceA1", "controlA"]) { it(`should not loopback on ${srcName}`, async function() { const src = get(srcName); - const dstAddr = src.connector.src; - await assert.rejects( + const dstAddr = src instanceof Controller ? addr("controller") : src.connector.src; + assert.throws( () => send(src, dstAddr, new TestRequest()), new Error(`Message would return back to sender ${dstAddr}.`) );