Skip to content

Commit

Permalink
feat(solo): WIP implement routes for listConnections and publishBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Apr 21, 2022
1 parent 04c6c4b commit 98871b7
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/solo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
},
"devDependencies": {
"@agoric/ertp": "^0.14.0",
"@agoric/publish-bundle": "^0.1.0",
"@endo/bundle-source": "^2.2.0",
"ava": "^3.12.1",
"c8": "^7.7.2"
Expand Down
6 changes: 6 additions & 0 deletions packages/solo/src/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ const buildSwingset = async (
// now let the bootstrap functions run
await processKernel();

const { validateAndInstallBundle } = controller;

return {
deliverInboundToMbx: queuedDeliverInboundToMbx,
deliverInboundCommand: queuedDeliverInboundCommand,
Expand All @@ -334,6 +336,7 @@ const buildSwingset = async (
plugin.reset();
return processKernel();
}),
validateAndInstallBundle,
};
};

Expand Down Expand Up @@ -432,6 +435,7 @@ const start = async (basedir, argv) => {
deliverOutbound,
startTimer,
resetOutdatedState,
validateAndInstallBundle,
} = d;

// Start timer here!
Expand Down Expand Up @@ -491,6 +495,8 @@ const start = async (basedir, argv) => {
c.host,
deliverInboundCommand,
agWalletHtml,
validateAndInstallBundle,
connections,
);
break;
}
Expand Down
65 changes: 62 additions & 3 deletions packages/solo/src/web.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global setTimeout clearTimeout setInterval clearInterval */
/* eslint-env node */
// Start a network service
import path from 'path';
import http from 'http';
Expand All @@ -10,6 +10,10 @@ import morgan from 'morgan';

import { getAccessToken } from '@agoric/access-token';

const textDecoder = new TextDecoder();

const maximumBundleSize = 1024 * 1024 * 128; // 128MB

const log = anylogger('web');

const channels = new Map();
Expand Down Expand Up @@ -67,6 +71,8 @@ export async function makeHTTPListener(
host,
rawInboundCommand,
walletHtmlDir = '',
validateAndInstallBundle,
connections,
) {
// Enrich the inbound command with some metadata.
const inboundCommand = (
Expand Down Expand Up @@ -178,8 +184,8 @@ export async function makeHTTPListener(
return false;
};

// accept POST messages to arbitrary endpoints
app.post('*', async (req, res) => {
// accept POST messages as commands.
app.post('/', async (req, res) => {
if (!(await validateAccessToken(req))) {
res.json({ ok: false, rej: 'Unauthorized' });
return;
Expand All @@ -194,6 +200,59 @@ export async function makeHTTPListener(
.catch(_ => {});
});

app.get('/connections.json', async (req, res) => {
if (!(await validateAccessToken(req))) {
res.json({ ok: false, rej: 'Unauthorized' });
return;
}

res.json({ ok: true, connections });
});

app.post('/publish-bundle', async (req, res) => {
if (!(await validateAccessToken(req))) {
res.json({ ok: false, rej: 'Unauthorized' });
return;
}

const expectedLengthHeader = req.getHeader('Content-Length');
const expectedLength = parseInt(expectedLengthHeader, 10);

if (expectedLength > maximumBundleSize) {
res.json({
ok: false,
rej: `Content-Length ${expectedLength} exceeds maximum bundle size ${maximumBundleSize}`,
});
return;
}

/** @type {Array<Uint8Array>} */
const chunks = [];
let length = 0;
for await (const chunk of req) {
length += chunk.length;
if (length > expectedLength) {
res.json({
ok: false,
rej: `Length of content exceeds Content-Length ${expectedLength}`,
});
return;
}
chunks.push(chunk);
}
const bytes = Buffer.concat(chunks);

try {
const text = textDecoder.decode(bytes);
const json = JSON.parse(text);
await validateAndInstallBundle(json);
} catch (error) {
res.json({ ok: false, rej: error.message });
}

res.json({ ok: true });
});

// accept WebSocket channels at the root path.
// This senses the Upgrade header to distinguish between plain
// GETs (which should return index.html) and WebSocket requests.
Expand Down
5 changes: 2 additions & 3 deletions packages/solo/test/test-home.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
/* global process */

import '@endo/init/pre-bundle-source.js';

// `test.after.always` does not yet seem compatible with ses-ava
// See https://github.com/endojs/endo/issues/647
// TODO restore
// import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava';
// import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js';
import '@agoric/swingset-vat/tools/prepare-test-env.js';
// eslint-disable-next-line import/no-extraneous-dependencies
import test from 'ava';

import bundleSource from '@endo/bundle-source';
import { makeBundlePublisher } from '@agoric/publish-bundle';
import { AmountMath } from '@agoric/ertp';
import { Far } from '@endo/marshal';
import { resolve as importMetaResolve } from 'import-meta-resolve';
Expand Down

0 comments on commit 98871b7

Please sign in to comment.