mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
changed byte-order for websocket messages to little-endian
This commit is contained in:
parent
9447d791f4
commit
8c4f291fd9
5 changed files with 107 additions and 49 deletions
35
include/villas/webmsg.h
Normal file
35
include/villas/webmsg.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/** Message related functions
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Forward declarations. */
|
||||
struct webmsg;
|
||||
|
||||
/** Swaps the byte-order of the message.
|
||||
*
|
||||
* Message are always transmitted in network (big endian) byte order.
|
||||
*
|
||||
* @param m A pointer to the message
|
||||
*/
|
||||
void webmsg_hdr_ntoh(struct webmsg *m);
|
||||
|
||||
void webmsg_hdr_hton(struct webmsg *m);
|
||||
|
||||
void webmsg_ntoh(struct webmsg *m);
|
||||
|
||||
void webmsg_hton(struct webmsg *m);
|
||||
|
||||
/** Check the consistency of a message.
|
||||
*
|
||||
* The functions checks the header fields of a message.
|
||||
*
|
||||
* @param m A pointer to the message
|
||||
* @retval 0 The message header is valid.
|
||||
* @retval <0 The message header is invalid.
|
||||
*/
|
||||
int msg_verify(struct webmsg *m);
|
|
@ -1,4 +1,7 @@
|
|||
/** Binary websocket message format
|
||||
/** Binary websocket message format.
|
||||
*
|
||||
* Note: Messages sent by the 'websocket' node-type are always send in little endian byte-order!
|
||||
* This is different from the messages send with the 'socket' node-type!
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
|
@ -20,7 +23,7 @@
|
|||
#define WEBMSG_TYPE_STOP 2 /**< Message marks the end of a simulation case */
|
||||
|
||||
/** The total size in bytes of a message */
|
||||
#define WEBMSG_LEN(values) (sizeof(struct webmsg) + MSG_DATA_LEN(values))
|
||||
#define WEBMSG_LEN(values) (sizeof(struct webmsg) + WEBMSG_DATA_LEN(values))
|
||||
|
||||
/** The length of \p values values in bytes. */
|
||||
#define WEBMSG_DATA_LEN(values) (sizeof(float) * (values))
|
||||
|
@ -32,7 +35,6 @@
|
|||
#define WEBMSG_INIT(len, seq) (struct webmsg) {\
|
||||
.version = WEBMSG_VERSION, \
|
||||
.type = WEBMSG_TYPE_DATA, \
|
||||
.endian = WEBMSG_ENDIAN_HOST, \
|
||||
.length = len, \
|
||||
.sequence = seq \
|
||||
}
|
||||
|
@ -49,9 +51,9 @@
|
|||
**/
|
||||
struct webmsg
|
||||
{
|
||||
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
|
||||
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
|
||||
unsigned rsvd1 : 2; /**< Reserved bits */
|
||||
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
|
||||
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
|
||||
|
||||
uint8_t id; /**< The node index from / to which this sample received / sent to.
|
||||
* Corresponds to the index of the node in the http://localhost/nodes.json array. */
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <libconfig.h>
|
||||
|
||||
#include "super_node.h"
|
||||
#include "webmsg.h"
|
||||
#include "webmsg_format.h"
|
||||
#include "timing.h"
|
||||
#include "utils.h"
|
||||
|
@ -119,7 +120,6 @@ static int websocket_connection_write(struct websocket_connection *c, struct sam
|
|||
|
||||
msg->version = WEBMSG_VERSION;
|
||||
msg->type = WEBMSG_TYPE_DATA;
|
||||
msg->endian = WEBMSG_ENDIAN_HOST;
|
||||
msg->length = smps[i]->length;
|
||||
msg->sequence = smps[i]->sequence;
|
||||
msg->id = c->node->id;
|
||||
|
|
54
lib/webmsg.c
Normal file
54
lib/webmsg.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/** Websocket message related functions.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
|
||||
*********************************************************************************/
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#include "webmsg.h"
|
||||
#include "msg_format.h"
|
||||
|
||||
void webmsg_ntoh(struct webmsg *m)
|
||||
{
|
||||
msg_hdr_ntoh(m);
|
||||
|
||||
for (int i = 0; i < m->length; i++)
|
||||
m->data[i].i = ntohl(m->data[i].i);
|
||||
}
|
||||
|
||||
void msg_hton(struct webmsg *m)
|
||||
{
|
||||
for (int i = 0; i < m->length; i++)
|
||||
m->data[i].i = htonl(m->data[i].i);
|
||||
|
||||
webmsg_hdr_hton(m);
|
||||
}
|
||||
|
||||
void webmsg_hdr_hton(struct webmsg *m)
|
||||
{
|
||||
m->length = htole16(m->length);
|
||||
m->sequence = htonle32(m->sequence);
|
||||
m->ts.sec = htonle32(m->ts.sec);
|
||||
m->ts.nsec = htonle32(m->ts.nsec);
|
||||
}
|
||||
|
||||
void webmsg_hdr_ntoh(struct webmsg *m)
|
||||
{
|
||||
m->length = le16tohs(m->length);
|
||||
m->sequence = le32tohl(m->sequence);
|
||||
m->ts.sec = le32tohl(m->ts.sec);
|
||||
m->ts.nsec = le32tohl(m->ts.nsec);
|
||||
}
|
||||
|
||||
int webmsg_verify(struct webmsg *m)
|
||||
{
|
||||
if (m->version != WEBMSG_VERSION)
|
||||
return -1;
|
||||
else if (m->type != WEBMSG_TYPE_DATA)
|
||||
return -2;
|
||||
else if ((m->rsvd1 != 0) || (m->rsvd2 != 0))
|
||||
return -3;
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
/** Javascript class for parsing binary messages
|
||||
/** Javascript class for parsing binary messages.
|
||||
*
|
||||
* Note: Messages sent by the 'websocket' node-type are always send in little endian byte-order!
|
||||
* This is different from the messages send with the 'socket' node-type!
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2016, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
|
||||
*********************************************************************************/
|
||||
/**
|
||||
* @addtogroup websocket
|
||||
|
@ -15,7 +18,6 @@ function Msg(c)
|
|||
{
|
||||
this.sequence = typeof c.sequence === 'undefined' ? 0 : c.sequence;
|
||||
this.length = typeof c.length === 'undefined' ? 0 : c.length;
|
||||
this.endian = typeof c.endian === 'undefined' ? Msg.prototype.ENDIAN_LITTLE : c.endian;
|
||||
this.version = typeof c.version === 'undefined' ? Msg.prototype.VERSION : c.version;
|
||||
this.type = typeof c.type === 'undefined' ? Msg.prototype.TYPE_DATA : c.type;
|
||||
this.id = typeof c.id === 'undefined' ? -1 : c.id;
|
||||
|
@ -32,11 +34,7 @@ Msg.prototype.VERSION = 1;
|
|||
|
||||
Msg.prototype.TYPE_DATA = 0; /**< Message contains float values */
|
||||
|
||||
Msg.prototype.ENDIAN_LITTLE = 0; /**< Message values are in little endian format (float too!) */
|
||||
Msg.prototype.ENDIAN_BIG = 1; /**< Message values are in bit endian format */
|
||||
|
||||
/* Some offsets in the binary message */
|
||||
Msg.prototype.OFFSET_ENDIAN = 1;
|
||||
Msg.prototype.OFFSET_TYPE = 2;
|
||||
Msg.prototype.OFFSET_VERSION = 4;
|
||||
|
||||
|
@ -48,30 +46,20 @@ Msg.bytes = function(len)
|
|||
Msg.fromArrayBuffer = function(data)
|
||||
{
|
||||
var bits = data.getUint8(0);
|
||||
var endian = (bits >> Msg.prototype.OFFSET_ENDIAN) & 0x1 ? 0 : 1;
|
||||
|
||||
var msg = new Msg({
|
||||
endian: (bits >> Msg.prototype.OFFSET_ENDIAN) & 0x1,
|
||||
version: (bits >> Msg.prototype.OFFSET_VERSION) & 0xF,
|
||||
type: (bits >> Msg.prototype.OFFSET_TYPE) & 0x3,
|
||||
id: data.getUint8( 0x01, endian),
|
||||
length: data.getUint16(0x02, endian),
|
||||
sequence: data.getUint32(0x04, endian),
|
||||
timestamp: data.getUint32(0x08, endian) * 1e3 +
|
||||
data.getUint32(0x0C, endian) * 1e-6,
|
||||
id: data.getUint8( 0x01),
|
||||
length: data.getUint16(0x02, 1),
|
||||
sequence: data.getUint32(0x04, 1),
|
||||
timestamp: data.getUint32(0x08, 1) * 1e3 +
|
||||
data.getUint32(0x0C, 1) * 1e-6,
|
||||
});
|
||||
|
||||
msg.blob = new DataView( data.buffer, data.byteOffset + 0x00, Msg.bytes(msg.length));
|
||||
msg.data = new Float32Array(data.buffer, data.byteOffset + 0x10, msg.length);
|
||||
|
||||
if (msg.endian != host_endianess()) {
|
||||
console.warn("Message is not given in host endianess!");
|
||||
|
||||
var data = new Uint32Array(msg.blob, 0x10);
|
||||
for (var i = 0; i < data.length; i++)
|
||||
data[i] = swap32(data[i]);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -101,7 +89,6 @@ Msg.prototype.toArrayBuffer = function()
|
|||
view = new DataView(buffer);
|
||||
|
||||
var bits = 0;
|
||||
bits |= (this.endian & 0x1) << Msg.prototype.OFFSET_ENDIAN;
|
||||
bits |= (this.version & 0xF) << Msg.prototype.OFFSET_VERSION;
|
||||
bits |= (this.type & 0x3) << Msg.prototype.OFFSET_TYPE;
|
||||
|
||||
|
@ -121,24 +108,4 @@ Msg.prototype.toArrayBuffer = function()
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/** @todo parsing of big endian messages not yet supported */
|
||||
function swap16(val)
|
||||
{
|
||||
return ((val & 0xFF) << 8)
|
||||
| ((val >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
function swap32(val) {
|
||||
return ((val & 0xFF) << 24)
|
||||
| ((val & 0xFF00) << 8)
|
||||
| ((val >> 8) & 0xFF00)
|
||||
| ((val >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
function host_endianess() {
|
||||
var buffer = new ArrayBuffer(2);
|
||||
new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
|
||||
return new Int16Array(buffer)[0] === 256 ? 0 : 1; // Int16Array uses the platform's endianness.
|
||||
};
|
||||
|
||||
/** @} */
|
Loading…
Add table
Reference in a new issue