Curt Welch
Member
I'm running into a bug on a Teensy4.1 used in a robotics application using WebSockets to receive information from a web server. If the packets sent are over about the size of a single ethernet packet, they are corrupted. This appears to be a memory overflow bug somewhere. I've removed all our code and reproduced the bug in a simple modified version of the Teensy4.1 example code from the WebSockets release.
The Teensy Code:
The server sending the messages is in typescript (I don't know typescript -- written by a co-worker):
When I run the server on my Mac, with the command:
bun teensyStress.ts 100 50
The above waits for a connection and they starts sending json packets with a random text string of 50 bytes, every 100 ms.
For the small packets, the output of the Teensy looks like this:
Everything is fiue until the packet gets over around 1440 bytes in size and the message sent to my handling routine is obviously corrupted and the teensy will soon crash.
Output for when I run the server with 2000-byte packets looks like this:
bun teensyStress.ts 100 2000
The Teensy shows 1523 bytes in the message instead of over 2000 as it should for the size of the full Json message. And it obviously gets garbled values at the end (scroll to the right to see it).
I've tested with NativeEthernet as well as QNEthernet.
The version of WebSockets I'm using is 0.5.4
Anyone have a clue what could be causing this? Is it a bug in websociets maybe I need to report? Ideas on how to narrow down the problem or tests to try?
I"m compiling and downloading to the Teensy using vscode and PlatformIO on my Macbook and I'm running the test with a USB ethernet connection connected to the Tensey direclty without an external router or switch. Using static IPs so no DHCP at play.
The Teensy Code:
C++:
/*
Teensy41 Websockets Client (using NativeEthernet)
2024-08-24 Websociet test example modified by Curt Welch curt@kcwc.com
*/
#include <ArduinoWebsockets.h>
#include <TeensyID.h>
// #include <NativeEthernet.h>
#include <QNEthernet.h>
using namespace websockets;
WebsocketsClient client;
// We will set the MAC address at the beginning of `setup()` using TeensyID's
// `teensyMac` helper.
byte mac[6];
IPAddress ip(192, 168, 1, 100); // Curt's Mac
// Enter websockets url.
// Note: wss:// currently not working.
// const char* url = "ws://echo.websocket.org";
const char *url = "ws://192.168.1.10:9000"; // Curt's Mac
auto MessageNow = millis();
auto MessageLast = MessageNow;
void setup() {
// Start Serial and wait until it is ready.
Serial.begin(9600);
while (!Serial)
;
Serial.printf("Start websocket test\n");
// Configure Ethernet
teensyMAC(mac); // Get the mac address for this Teensy from rom
Ethernet.begin(mac, ip); // Sets the mac and ip address
Serial.print("Ethernet connected (");
Serial.print(Ethernet.localIP());
Serial.println(")");
// Set up callback when messages are received.
client.onMessage([](WebsocketsMessage message) {
MessageNow = millis();
Serial.printf("Got Message len is %d ms is %d\n", message.data().length(), MessageNow-MessageLast);
MessageLast = MessageNow;
Serial.println(message.data());
});
}
bool connected = false;
void loop() {
// Check for incoming messages.
if (!connected) {
Serial.printf("Connecting to server.\n");
if (client.connect(url)) {
connected = true;
Serial.printf("Connected!\n");
Serial.printf("Sending ID\n");
client.send("{\"connect\" : \"true\"}");
// {
// teensyId: "ins",
// connect: true,
// }
} else {
Serial.print("Connection Failed.\n");
}
return;
}
if (!client.available()) {
connected = false;
Serial.printf("Lost connection to server.\n");
return;
}
if (client.poll()) {
Serial.printf("M ");
}
}
The server sending the messages is in typescript (I don't know typescript -- written by a co-worker):
JavaScript:
import { ServerWebSocket } from 'bun'
const frequency = parseInt(process.argv[2])
const characterCount = parseInt(process.argv[3])
if (isNaN(frequency) || isNaN(characterCount)) {
console.log('Usage: bun teensyStress.ts <frequency>ms <characterCount>')
process.exit(1)
}
let wes: ServerWebSocket
Bun.serve({
fetch(req, server) {
const success = server.upgrade(req)
if (success) {
return undefined
}
return new Response('Teensy Stress Test API')
},
websocket: {
async message(ws, message) {
let msg = JSON.parse(message as string)
console.log(msg)
if (msg.connect) {
wes = ws
console.log('Connected to Teensy!')
}
},
},
port: 9000,
})
setInterval(() => {
if (!wes) return
const characters =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
let message = ''
for (let i = 0; i < characterCount; i++) {
message += characters[Math.floor(Math.random() * characters.length)]
}
// console.log("Send message")
wes.send(
JSON.stringify({
type: 'mock',
message,
})
)
}, frequency)
When I run the server on my Mac, with the command:
bun teensyStress.ts 100 50
The above waits for a connection and they starts sending json packets with a random text string of 50 bytes, every 100 ms.
For the small packets, the output of the Teensy looks like this:
Code:
Start websocket test
Ethernet connected (192.168.1.100)
Connecting to server.
Connected!
Sending ID
Got Message len is 78 ms is 8029
{"type":"mock","message":"j3JMfwvh5gFaDUxN88dZ2P3w63rqLaIWyzYtg2Kd2WrddcZUXk"}
M Got Message len is 78 ms is 99
{"type":"mock","message":"ZhdspgbsfIxXYlumNLZHnWlM7yyObMLTHARNGwZCx6Eg6ktp2W"}
M Got Message len is 78 ms is 101
{"type":"mock","message":"VZAposqDgpv189iDqp4yzdkPlIOEzztfGUEO6nqtnkQ0qSWRh8"}
M Got Message len is 78 ms is 101
{"type":"mock","message":"04ofBze49paexr93c8N8bk971U5NbPaLheudn9sv7NOYAri6kJ"}
M Got Message len is 78 ms is 101
{"type":"mock","message":"mVzBdCgevJNq9H3W5qtM67GAPhHgsGFVd4ETS8Jmf94oqg6V9c"}
M Got Message len is 78 ms is 101
{"type":"mock","message":"gfqCKqtZNe9oWLnRwauTWSj77wJolrkyzDoMzvvPknAoTNh6jQ"}
M Got Message len is 78 ms is 100
{"type":"mock","message":"DMpdjWYZw80ml55cJIEnvJAf0MXqpGpPBe2prbwscEOGnjo2nD"}
M Got Message len is 78 ms is 101
{"type":"mock","message":"8td2Swdf24FERJL4YGH34SgX22KknzXs8do11lXP5ejhsdzYSE"}
M Got Message len is 78 ms is 101
{"type":"mock","message":"oNrLsH77EZ92bhUETW640ekifDKsgqRczdz5YKZwz2o2PsYU3T"}
Everything is fiue until the packet gets over around 1440 bytes in size and the message sent to my handling routine is obviously corrupted and the teensy will soon crash.
Output for when I run the server with 2000-byte packets looks like this:
bun teensyStress.ts 100 2000
Code:
Start websocket test
Ethernet connected (192.168.1.100)
Connecting to server.
Connected!
Sending ID
Got Message len is 1523 ms is 8023
{"type":"mock","message":"XqtcWNLkiRwQxDKyIoVDHzEQl3sSZQpQP3lU9udFZoSRCtU0SpXmf7oFVmiTLfB2EqLHVWUjpzyFqzje1ywq2yP6jG5q1F8RDiAMNh2kRgJK1tL4tYPS4OUnko4vzL5P0J4jyg3LIoTsczKDXBn1KOJXLJQbC7pthGPX65GdlOvLmuVAp84jMkLeYiCcoXIepmeeb7OONsljDIGoTugFHstOutJ63ZMwZGMBqtTDZykYejqra8MsjRHHVTqowZzrNlCDSIpi8B4lYcTUlsCGiCG0LUfjaT9WrIJuL2as3pHYucEUGTx0kWMh0hNfS1hBjHrakU7rGrfkVXVqQx6yInA9Wjwcwr8qHLKuXcTGVtrYETZNUPj3TEY6SGNEcJypZnu5wt2SeL4mZZhr0vmXRyGoeUGwjWOrpsCHvAok6FRK1zPSEUXadvo6Csiv6tBmj1QoqWZH7GpcmZz78E5rNUiUIMwvBsQuLxFLhGyvpPSe5TJaiRfylVWbILrwnKStgxg7NU5CI6yTJuSXqGvH07lYcOvmJUUfRn9bnv4tjoBjIvYTHg2Q4qp01dJHzx3DeuH0iRYNebnpb9a1yhO3fwMlXzjtI6MvxaQmF7fQuXUTC6VFPrHQHo2sqFI4OcbnzROoeV13tpyylUEgIYtSkFQapuFVdOcPwJUNvX7oHDCZioBkyD5tFxlD6D9yh4dcf8UD63NX5wIuej4eV00FTUBH2ViO7o6rPKGIabQHWnHC68YGXIccCMIzoZodv1qdGS0M5tKtgRuKJG6ije9V8dky25W8VRduavkpVrMSAVlU8WRRslhtALuCD0o4lJt82TXf372F3TbdcGTSesgS7q8bvmWroFagYJA0E45C8eC7fIvRGocua3Q6LfPUcvBCKCpBJDkfbl5s3TuNyJrs2r2UqoSyRkbpxTvtRKbs533pov4gKew3Xta6gY98nzQiV7JpaJn7hQ7wZmVgnFLgfQFPOt1kSYRbtT5pumn1QG492UsDfYqPHu5t0ss8CUQwwqG98r7MbZo4gRbrj9BTpUrDAbd8KLF9ozqmrb5WDrQvHSGOnnOm2ZrOKQ0Xq0AVau13HE7L3ISukmr6zSi3doSJNaYHJjrRIKguAm0f52Kw43G0SsOcJ4wFwahNy6eKPcHfVtYfSwwplb5aE4Cd7uK1eom7LEHD1FBo2ISIYOm5HVf1LsooePm4BJobPJFhb7gGVEXyJW6QyX4npkTBIFPBS7vb0T4DUKPgIs5wgOENl6lxkHkZrwRG7o81AoQHnaysU1EAZtWzJNFSQ8w3TMMbwL1cbEj6I1YvXnO6DfCkbzpNmrjSoiuBVtpxOViSmbiVnPMM7y7gdWzM5G2hB6KrqCqfGPJWAHQsJib1ktAHgcNvhKa6pgtrJA1jNHqLyrRu00yYluLF2KueF9YnW9qD1gfXVZS2"}9d1w0Ef5olzRVvQAMAA5AWfxl3Yy"}}���SD����~␂�D0�␆)��,�m>�
The Teensy shows 1523 bytes in the message instead of over 2000 as it should for the size of the full Json message. And it obviously gets garbled values at the end (scroll to the right to see it).
I've tested with NativeEthernet as well as QNEthernet.
The version of WebSockets I'm using is 0.5.4
Anyone have a clue what could be causing this? Is it a bug in websociets maybe I need to report? Ideas on how to narrow down the problem or tests to try?
I"m compiling and downloading to the Teensy using vscode and PlatformIO on my Macbook and I'm running the test with a USB ethernet connection connected to the Tensey direclty without an external router or switch. Using static IPs so no DHCP at play.