Skip to content

Commit c39b904

Browse files
committed
Move the JavaScript into a separate compartment.
1 parent 275325f commit c39b904

File tree

3 files changed

+32
-423
lines changed

3 files changed

+32
-423
lines changed

demos/2024-04-23-cheritech/demo.cc

Lines changed: 27 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <vector>
1717

1818
#include "host.cert.h"
19-
#include "microvium-ffi.h"
19+
#include "javascript.hh"
2020

2121
using CHERI::Capability;
2222

@@ -45,9 +45,6 @@ namespace
4545
constexpr const char *buttonTopic = "cheri-button";
4646
int buttonCounter = 0;
4747

48-
std::unique_ptr<mvm_VM, MVMDeleter> vm;
49-
std::vector<uint8_t> bytecode;
50-
5148
/**
5249
* Note from the MQTT 3.1.1 spec:
5350
* The Server MUST allow ClientIds which are between 1 and 23 UTF-8 encoded
@@ -74,7 +71,7 @@ namespace
7471

7572
void __cheri_callback publishCallback(const char *topicName,
7673
size_t topicNameLength,
77-
const void *payload,
74+
const void *payloadData,
7875
size_t payloadLength)
7976
{
8077
std::string_view topic{topicName, topicNameLength};
@@ -85,90 +82,39 @@ namespace
8582
if ((CodeTopic.size() == topic.size()) &&
8683
(memcmp(topic.data(), CodeTopic.data(), CodeTopic.size()) == 0))
8784
{
88-
Debug::log("Received new JavaScript code.");
89-
vm.reset();
90-
bytecode.clear();
91-
bytecode.reserve(payloadLength);
92-
bytecode.insert(bytecode.end(),
93-
static_cast<const uint8_t *>(payload),
94-
static_cast<const uint8_t *>(payload) +
95-
payloadLength);
96-
Debug::log("Copied JavaScript bytecode");
97-
mvm_VM *rawVm;
98-
auto err = mvm_restore(
99-
&rawVm, /* Out pointer to the VM */
100-
bytecode.data(), /* Bytecode data */
101-
bytecode.size(), /* Bytecode length */
102-
MALLOC_CAPABILITY, /* Capability used to allocate memory */
103-
::resolve_import); /* Callback used to resolve FFI imports */
104-
if (err == MVM_E_SUCCESS)
105-
{
106-
Debug::log("Successfully loaded bytecode.");
107-
vm.reset(rawVm);
108-
}
109-
else
110-
{
111-
// If this is not valid bytecode, give up.
112-
Debug::log("Failed to parse bytecode: {}", err);
113-
}
114-
// Don't try to handle the new-code message in JavaScript.
85+
load_javascript(payloadData, payloadLength);
11586
return;
11687
}
11788

118-
if (!vm)
119-
{
120-
return;
121-
}
122-
123-
mvm_Value callback;
124-
if (mvm_resolveExports(vm.get(), &ExportPublished, &callback, 1) ==
125-
MVM_E_SUCCESS)
126-
{
127-
mvm_Value args[2];
128-
args[0] = mvm_newString(vm.get(), topicName, topicNameLength);
129-
args[1] = mvm_newString(
130-
vm.get(), static_cast<const char *>(payload), payloadLength);
131-
// Set a limit of bytecodes to execute, to prevent infinite loops.
132-
mvm_stopAfterNInstructions(vm.get(), 20000);
133-
// Call the function:
134-
int err = mvm_call(vm.get(), callback, nullptr, args, 2);
135-
if (err != MVM_E_SUCCESS)
136-
{
137-
Debug::log("Failed to call publish callback function: {}", err);
138-
}
139-
}
89+
std::string_view payload{static_cast<const char *>(payloadData),
90+
payloadLength};
91+
publish(topic, payload);
14092
}
14193

14294
/// Handle to the MQTT connection.
14395
SObj handle;
14496

145-
bool export_mqtt_publish(std::string_view topic, std::string_view message)
146-
{
147-
Timeout t{UnlimitedTimeout};
148-
Debug::log("Publishing message to topic '{}' ({}): '{}' ({})",
149-
topic,
150-
topic.size(),
151-
message,
152-
message.size());
153-
auto ret = mqtt_publish(&t,
154-
handle,
155-
0, // Don't want acks for this one
156-
topic.data(),
157-
topic.size(),
158-
message.data(),
159-
message.size());
160-
Debug::log("Publish returned {}", ret);
161-
return ret == 0;
162-
}
97+
} // namespace
16398

164-
bool export_mqtt_subscribe(std::string_view topic)
165-
{
166-
Timeout t{MS_TO_TICKS(100)};
167-
auto ret = mqtt_subscribe(&t, handle, 1, topic.data(), topic.size());
168-
return ret >= 0;
169-
}
99+
bool mqtt_publish(std::string_view topic, std::string_view message)
100+
{
101+
Timeout t{UnlimitedTimeout};
102+
auto ret = mqtt_publish(&t,
103+
handle,
104+
0, // Don't want acks for this one
105+
topic.data(),
106+
topic.size(),
107+
message.data(),
108+
message.size());
109+
return ret != 0;
110+
}
170111

171-
} // namespace
112+
bool mqtt_subscribe(std::string_view topic)
113+
{
114+
Timeout t{MS_TO_TICKS(100)};
115+
auto ret = mqtt_subscribe(&t, handle, 1, topic.data(), topic.size());
116+
return ret >= 0;
117+
}
172118

173119
/// Main demo
174120

@@ -216,8 +162,7 @@ void __cheri_compartment("mqtt_demo") demo()
216162

217163
while (true)
218164
{
219-
vm.reset();
220-
bytecode.clear();
165+
load_javascript(nullptr, 0);
221166
Debug::log("Generating client ID...");
222167
mqtt_generate_client_id(clientID + clientIDPrefixLength,
223168
clientIDlength - clientIDPrefixLength - 1);
@@ -283,7 +228,6 @@ void __cheri_compartment("mqtt_demo") demo()
283228
}
284229
}
285230

286-
Timeout coolDown{0};
287231
Debug::log("Now entering the main loop.");
288232
while (true)
289233
{
@@ -297,27 +241,7 @@ void __cheri_compartment("mqtt_demo") demo()
297241
Debug::log("Failed to wait for PUBLISHes, error {}.", ret);
298242
break;
299243
}
300-
301-
if (!vm)
302-
{
303-
continue;
304-
}
305-
306-
mvm_Value callback;
307-
if (mvm_resolveExports(vm.get(), &ExportTick, &callback, 1) ==
308-
MVM_E_SUCCESS)
309-
{
310-
// Set a limit of bytecodes to execute, to prevent infinite
311-
// loops.
312-
mvm_stopAfterNInstructions(vm.get(), 20000);
313-
// Call the function:
314-
int err = mvm_call(vm.get(), callback, nullptr, nullptr, 0);
315-
if (err != MVM_E_SUCCESS)
316-
{
317-
Debug::log("Failed to call tick callback function: {}",
318-
err);
319-
}
320-
}
244+
tick();
321245
}
322246
Debug::log("Exiting main loop, cleaning up.");
323247
mqtt_disconnect(&t, STATIC_SEALED_VALUE(mqttTestMalloc), handle);

0 commit comments

Comments
 (0)