LabComm
LabComm is a binary protocol suitable for transmitting and storing samples of process data. LabComm has got it's inspiration from Sun RPC and ASN1. LabComm is primarily intended for situations where the overhead of communication has to be kept at a minimum, hence LabComm only requires one-way communication to operate. The one-way operation also has the added benefit of making LabComm suitable as a storage format.
LabComm communication starts with the transmission of an encoded description of all possible sample types that can occur, followed by any number of actual samples in any order the sending application sees fit.
The LabComm system consists of a protocol specification and a compiler that generates encoder/decoder routines for popular languages like C and Java.
The LabComm compiler accepts type and sample declarations in a small language that is similar to C or Java type-declarations. The following examples do not cover the entire language specification, but might serve as a gentle introduction to the LabComm language.
Primitive types
sample boolean a_boolean; sample byte a_byte; sample short a_short; sample int an_int; sample long a_long; sample float a_float; sample double a_double; sample string a_string;
Arrays
sample int fixed_array[3]; sample int variable_array[_]; // Note 1 sample int fixed_array_of_array[3][4]; // Note 2 sample int fixed_rectangular_array[3, 4]; // Note 2 sample int variable_array_of_array[_][_]; // Notes 1 & 2 sample int variable_rectangular_array[_, _]; // Notes 1 & 2
1 In contrast to C, LabComm supports both fixed and variable (denoted by '_') sized arrays.
2 In contrast to Java, LabComm supports multidimensional arrays and not only arrays of arrays.
Structures
sample struct {
int an_int_field;
double a_double_field;
} a_struct;
User defined types
typedef struct {
int field_1;
byte field_2;
} user_type[_];
sample user_type a_user_type_instance;
sample user_type another_user_type_instance;
Example and its encoding
With the following example.lc file:
sample struct {
int sequence;
struct {
boolean last;
string data;
} line[_];
} log_message;and this example_encoder.c file
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <labcomm_fd_reader_writer.h>
#include "example.h"
int main(int argc, char *argv[]) {
int fd;
struct labcomm_encoder *encoder;
int i, j;
fd = open("example.encoded", O_WRONLY|O_CREAT|O_TRUNC, 0644);
encoder = labcomm_encoder_new(labcomm_fd_writer, &fd);
labcomm_encoder_register_example_log_message(encoder);
for (i = 0 ; i < argc ; i++) {
example_log_message message;
message.sequence = i + 1;
message.line.n_0 = i;
message.line.a = malloc(message.line.n_0*sizeof(message.line));
for (j = 0 ; j < i ; j++) {
message.line.a[j].last = (j == message.line.n_0 - 1);
message.line.a[j].data = argv[j + 1];
}
labcomm_encode_example_log_message(encoder, &message);
free(message.line.a);
}
}Running './example_encoder one two', will yield the following result in example.encoded:
00000000 0000 0002 0000 0080 0000 000b 6c6f 675f ............log_ 00000010 6d65 7373 6167 6500 0000 1100 0000 0200 message......... 00000020 0000 0873 6571 7565 6e63 6500 0000 2300 ...sequence...#. 00000030 0000 046c 696e 6500 0000 1000 0000 0100 ...line......... 00000040 0000 0000 0000 1100 0000 0200 0000 046c ...............l 00000050 6173 7400 0000 2000 0000 0464 6174 6100 ast... ....data. 00000060 0000 2700 0000 8000 0000 0000 0000 0000 ..'............. 00000070 0000 8000 0000 0100 0000 0101 0000 0003 ................ 00000080 6f6e 6500 0000 8000 0000 0200 0000 0200 one............. 00000090 0000 0003 6f6e 6501 0000 0003 7477 6f ....one.....two