1
0
Fork 0
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:
Steffen Vogel 2017-04-24 13:22:55 +02:00
parent 9447d791f4
commit 8c4f291fd9
5 changed files with 107 additions and 49 deletions

35
include/villas/webmsg.h Normal file
View 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);

View file

@ -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. */

View file

@ -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
View 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;
}

View file

@ -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.
};
/** @} */