1616#include < vector>
1717
1818#include " host.cert.h"
19- #include " microvium-ffi.h "
19+ #include " javascript.hh "
2020
2121using 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