@foxglove/ros1
Version:
Standalone TypeScript implementation of the ROS 1 (Robot Operating System) protocol with a pluggable transport layer
60 lines • 2.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RosTcpMessageStream = void 0;
const eventemitter3_1 = require("eventemitter3");
const concatData_1 = require("./concatData");
// This is the maximum message length allowed by ros_comm. See
// <https://github.com/strawlab/ros_comm/blob/master/clients/cpp/roscpp/src/libros/transport_publisher_link.cpp#L164-L167>
const MAX_MSG_LENGTH = 1000000000;
// A stateful transformer that takes a raw TCPROS data stream and parses the
// TCPROS format of 4 byte length prefixes followed by message payloads into one
// complete message per "message" event, discarding the length prefix
class RosTcpMessageStream extends eventemitter3_1.EventEmitter {
constructor() {
super(...arguments);
this._inMessage = false;
this._bytesNeeded = 4;
this._chunks = [];
}
addData(chunk) {
let idx = 0;
while (idx < chunk.length) {
if (chunk.length - idx < this._bytesNeeded) {
// If we didn't receive enough bytes to complete the current message or
// message length field, store this chunk and continue on
this._chunks.push(new Uint8Array(chunk.buffer, chunk.byteOffset + idx));
this._bytesNeeded -= chunk.length - idx;
return;
}
// Store the final chunk needed to complete the current message or message
// length field
this._chunks.push(new Uint8Array(chunk.buffer, chunk.byteOffset + idx, this._bytesNeeded));
idx += this._bytesNeeded;
const payload = (0, concatData_1.concatData)(this._chunks);
this._chunks = [];
if (this._inMessage) {
// Produce a Uint8Array representing a single message and transition to
// reading a message length field
this._bytesNeeded = 4;
this.emit("message", payload);
this._inMessage = false;
}
else {
// Decode the message length field and transition to reading a message
this._bytesNeeded = new DataView(payload.buffer, payload.byteOffset, payload.byteLength).getUint32(0, true);
if (this._bytesNeeded > MAX_MSG_LENGTH) {
throw new Error(`Invalid message length of ${this._bytesNeeded} decoded in a tcp stream`);
}
else if (this._bytesNeeded === 0) {
this._bytesNeeded = 4;
this.emit("message", new Uint8Array());
}
else {
this._inMessage = true;
}
}
}
}
}
exports.RosTcpMessageStream = RosTcpMessageStream;
//# sourceMappingURL=RosTcpMessageStream.js.map