Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • anders_blomdell/labcomm
  • klaren/labcomm
  • tommyo/labcomm
  • erikj/labcomm
  • sven/labcomm
5 results
Show changes
Showing
with 1602 additions and 24 deletions
#!/usr/bin/python
import labcomm2014
import sys,traceback
import test
def handle_twoInts(val):
print "got twoInts: %s" % val
def handle_twoLines(val):
print "got twoLines: %s" % val
if __name__ == "__main__":
version = sys.argv[2] if len(sys.argv) == 3 else "LabComm2014"
d = labcomm2014.Decoder(labcomm2014.StreamReader(open(sys.argv[1])), version)
d.register_handler(test.twoInts.signature, handle_twoInts)
d.register_handler(test.twoLines.signature, handle_twoLines)
while True:
try:
d.runOne()
except EOFError:
print "got EOF"
break
except Exception, e:
print "got Exception"
print e
traceback.print_exc()
break
typedef struct {
(foo:bar) int val;
} coord;
typedef int anInt;
typedef void avoid;
sample (function:"a trigger")(foo:bar) avoid doavoid;
sample (a:b) "A struct: an int and a ref." struct {
(e:f)(c:d) int x;
sample reference;
} intAndRef;
typedef struct {
coord x;
coord y;
} point;
typedef struct {
point start;
point end;
} line;
typedef struct {
int a;
int b;
boolean c;
} foo;
sample struct {
(name:l1)line l1;
(name:l2)line l2;
(b:"kalle anka")(c:hejdu)(a:"kalle anka")foo f;
} twoLines;
sample struct {
int a;
int b;
} twoInts;
sample anInt theFirstInt;
sample anInt theSecondInt;
sample struct {
struct {
int x;
int y;
} s1;
struct {
int a;
int b;
} s2;
int i;
double double_array[2,3,_][3][_];
} twoStructsAndInt;
data.java
example.c
example.cs
example.encoded
example.h
example.javaencoded
example.py
example_encoder
log_message.java
GENERATED=\
data.java \
example.c \
example.cs \
example.encoded \
example.h \
example.javaencoded \
example.py \
example_encoder \
log_message.java
all:
test:
./run
clean:
rm -f $(GENERATED) *.class
distclean: clean
sample struct {
int sequence;
struct {
boolean last;
string data;
} line[_];
} log_message;
sample float data;
#!/usr/bin/python
import labcomm2014
import sys
if __name__ == "__main__":
version = sys.argv[2] if len(sys.argv) == 3 else "LabComm2014"
d = labcomm2014.Decoder(labcomm2014.StreamReader(open(sys.argv[1])), version)
while True:
try:
data,decl = d.decode()
if data:
print data
except Exception, e:
print e
break
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import se.lth.control.labcomm2014.DecoderChannel;
import se.lth.control.labcomm2014.EncoderChannel;
public class example_decoder_encoder
implements data.Handler, log_message.Handler
{
DecoderChannel decoder;
EncoderChannel encoder;
public example_decoder_encoder(InputStream in, OutputStream out)
throws Exception
{
decoder = new DecoderChannel(in);
log_message.register(decoder, this);
data.register(decoder, this);
encoder = new EncoderChannel(out);
log_message.register(encoder);
data.register(encoder);
try {
decoder.run();
} catch (java.io.EOFException e) {
}
}
public void handle_data(float v) throws java.io.IOException {
System.out.println("Got data");
data.encode(encoder, v);
}
public void handle_log_message(log_message v) throws java.io.IOException {
System.out.println("Got log_message");
log_message.encode(encoder, v);
}
public static void main(String[] arg) throws Exception {
example_decoder_encoder example = new example_decoder_encoder(
new FileInputStream(new File(arg[0])),
new FileOutputStream(new File(arg[1])));
}
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <labcomm2014.h>
#include <labcomm2014_default_memory.h>
#include <labcomm2014_fd_reader.h>
#include <labcomm2014_fd_writer.h>
#include "example.h"
int main(int argc, char *argv[]) {
int fd;
struct labcomm2014_encoder *encoder;
struct labcomm2014_writer *labcomm2014_fd_writer;
int i, j;
fd = open("example.encoded", O_WRONLY|O_CREAT|O_TRUNC, 0644);
labcomm2014_fd_writer = labcomm2014_fd_writer_new(labcomm2014_default_memory, fd, 1);
encoder = labcomm2014_encoder_new(labcomm2014_fd_writer, NULL,
labcomm2014_default_memory, NULL);
labcomm2014_encoder_register_example_log_message(encoder);
labcomm2014_encoder_register_example_data(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];
}
labcomm2014_encode_example_log_message(encoder, &message);
free(message.line.a);
}
for (i = 0 ; i < argc ; i++) {
float f = i;
labcomm2014_encode_example_data(encoder, &f);
}
return 0;
}
#!/bin/sh
# Auto generate code from .lc file
java -jar ../../compiler/labcomm2014_compiler.jar \
--c=example.c --h=example.h \
--java=. \
--cs=example.cs \
--python=example.py \
example.lc || exit 1
# Compile executables
(cd ../../lib/c; make all || exit 1)
gcc -Wall -Werror -o example_encoder -I../../lib/c/2014 \
example_encoder.c \
example.c \
../../lib/c/liblabcomm2014.a || exit 1
javac -cp ../../lib/java/labcomm2014.jar:. *.java || exit 1
# Run through all executables (c->java->Python)
./example_encoder one two || exit 1
java -cp ../../lib/java/labcomm2014.jar:. example_decoder_encoder example.encoded example.javaencoded || exit 1
PYTHONPATH=../../lib/python ./example_decoder.py example.javaencoded || exit 1
*** Java_CodeGen.old 2010-05-31 10:13:44.000000000 +0200
--- Java_CodeGen.jrag 2010-05-31 10:22:55.000000000 +0200
***************
*** 445,450 ****
--- 445,452 ----
String prefix = "";
for (int i = 0 ; i < getNumExp() ; i++) {
String limit = getExp(i).Java_emitEncoder(env, name + prefix);
+ env.println("{");
+ env.indent();
env.println("int i_" + (baseDepth + i) + "_max = " + limit + ";");
prefix = prefix + "[0]";
}
***************
*** 456,461 ****
--- 458,465 ----
for (int i = 0 ; i < getNumExp() ; i++) {
env.print_for_end();
}
+ env.unindent();
+ env.println("}");
}
public String Exp.Java_emitEncoder(Java_env env, String name) {
SUBDIRS=c csharp java python
.PHONY: all
all: $(SUBDIRS:%=make-%)
.PHONY: make-%
make-%:
$(MAKE) -C $*
.PHONY: test
test: $(SUBDIRS:%=test-%)
.PHONY: test-%
test-%:
$(MAKE) -C $* test
.PHONY: clean
clean: $(SUBDIRS:%=clean-%)
.PHONY: clean-%
clean-%:
$(MAKE) -C $* clean
.PHONY: distclean
distclean: clean $(SUBDIRS:%=distclean-%)
.PHONY: distclean-%
distclean-%:
$(MAKE) -C $* distclean
MODULE LabComm(SYSMODULE)
RECORD LabComm_Stream
socketdev soc;
ENDRECORD
RECORD LabComm_Decoder_Sample
string prefix;
string name;
num user_id;
string handler;
ENDRECORD
RECORD LabComm_Encoder_Sample
string prefix;
string name;
num user_id;
ENDRECORD
RECORD Decoder
num user_id;
ENDRECORD
RECORD Encoder
num next_user_id;
ENDRECORD
! LabComm constants
CONST string LabCommVersion := "LabComm2013";
CONST num SAMPLE_DECL:=2;
CONST num SAMPLE_DATA:=64;
CONST num STRUCT_TYPE := 17;
CONST num ARRAY_TYPE := 16;
CONST num BYTE_TYPE := 37;
CONST num BOOL_TYPE := 37;
CONST num SHORT_TYPE := 34;
CONST num INT_TYPE := 37;
CONST num LONG_TYPE := 37;
CONST num FLOAT_TYPE := 37;
! Error declarations
CONST errnum INCORRECT_LABCOMM_VERSION := 50;
CONST errnum UNKNOWN_PACKET_TYPE := 51;
CONST errnum UNKNOWN_SAMPLE_TYPE := 52;
CONST errnum INCORRECT_SAMPLE_SIGNATURE := 53;
CONST errnum SAMPLE_TYPE_NOT_REGISTERED := 54;
CONST errnum IMPLEMENTATION_LIMIT_REACHED := 55;
PROC Decode_Packed(VAR LabComm_Stream s, VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
UnpackRawBytes buffer,\Network,1,v,\IntX:=USINT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Packed(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\IntX:=USINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
ERROR
RAISE ;
ENDPROC
PROC Decode_Boolean(VAR LabComm_Stream s, VAR bool v, \ VAR rawbytes collect)
VAR rawbytes buffer;
VAR num tmp;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
UnpackRawBytes buffer,\Network,1,tmp,\IntX:=USINT;
IF tmp = 0 THEN
v := FALSE;
ELSE
v := TRUE;
ENDIF
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Boolean(VAR LabComm_Stream s, bool v)
VAR rawbytes buffer;
VAR num tmp;
IF v THEN
tmp := 1;
ELSE
tmp := 0;
ENDIF
PackRawBytes tmp,buffer,\Network,1,\IntX:=USINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
ERROR
RAISE ;
ENDPROC
PROC Decode_Byte(VAR LabComm_Stream s, VAR byte v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
UnpackRawBytes buffer,\Network,1,v,\Hex1;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Byte(VAR LabComm_Stream s, byte v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\Hex1;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
ERROR
RAISE ;
ENDPROC
PROC Decode_Short(VAR LabComm_Stream s,VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=2;
UnpackRawBytes buffer,\Network,1,v,\IntX:=INT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Short(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v, buffer, \Network, 1, \IntX:=INT;
SocketSend s.soc, \RawData:=buffer, \NoOfBytes:=2;
ERROR
RAISE ;
ENDPROC
PROC Decode_Integer(VAR LabComm_Stream s, VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=4;
UnpackRawBytes buffer,\Network,1,v,\IntX:=DINT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Integer(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\IntX:=DINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=4;
ERROR
RAISE ;
ENDPROC
PROC Decode_Long(VAR LabComm_Stream s, VAR dnum v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=8;
UnpackRawBytes buffer,\Network,1,v,\IntX:=LINT;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Long(VAR LabComm_Stream s, dnum v)
VAR rawbytes buffer;
PackRawBytes v,buffer,\Network,1,\IntX:=LINT;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=8;
ERROR
RAISE ;
ENDPROC
PROC Decode_Float(VAR LabComm_Stream s,VAR num v, \ VAR rawbytes collect)
VAR rawbytes buffer;
SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=4;
UnpackRawBytes buffer,\Network,1,v,\Float4;
IF Present(collect) THEN
CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_Float(VAR LabComm_Stream s, num v)
VAR rawbytes buffer;
PackRawBytes v, buffer,\Network,1,\Float4;
SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=4;
ERROR
RAISE ;
ENDPROC
PROC Decode_String(VAR LabComm_Stream st,VAR string s, \ VAR rawbytes collect)
VAR rawbytes buffer;
VAR num length;
IF Present(collect) THEN
Decode_Packed st, length, \collect:=collect;
ELSE
Decode_Packed st, length;
ENDIF
SocketReceive st.soc,\Str:=s,\ReadNoOfBytes:=length;
IF Present(collect) THEN
PackRawBytes s, collect, (RawBytesLen(collect)+1), \ASCII;
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Encode_String(VAR LabComm_Stream st, string s)
VAR rawbytes buffer;
VAR num length;
length := StrLen(s);
Encode_Packed st, length;
SocketSend st.soc,\Str:=s,\NoOfBytes:=length;
ERROR
RAISE ;
ENDPROC
PROC Encoder_Register_Sample(VAR Encoder e, VAR LabComm_Stream st, VAR LabComm_Encoder_Sample s)
s.user_id := e.next_user_id;
e.next_user_id := e.next_user_id + 1;
Encode_Packed st, SAMPLE_DECL;
Encode_Packed st, s.user_id;
Encode_String st, s.name;
% s.prefix + ":Encode_Signature_" + s.name % e, st;
ERROR
RAISE ;
ENDPROC
PROC Collect_Array(VAR LabComm_Stream s, VAR rawbytes sig)
VAR num num_dim;
VAR num dims;
Decode_Packed s, num_dim, \collect:=sig;
FOR i FROM 1 TO num_dim DO
Decode_Packed s, dims, \collect:=sig;
ENDFOR
Collect_Signature s, sig;
ERROR
RAISE ;
ENDPROC
PROC Collect_Struct(VAR LabComm_Stream s, VAR rawbytes sig)
VAR num num_elements;
VAR string tmp;
Decode_Packed s, num_elements, \collect:=sig;
FOR i FROM 1 TO num_elements DO
Decode_String s, tmp, \collect:=sig;
Collect_Signature s, sig;
ENDFOR
ERROR
RAISE ;
ENDPROC
PROC Collect_Signature(VAR LabComm_Stream s, VAR rawbytes sig)
VAR num type_id;
Decode_Packed s, type_id, \collect:=sig;
TEST type_id
CASE STRUCT_TYPE:
Collect_Struct s, sig;
CASE ARRAY_TYPE:
Collect_Array s, sig;
CASE BYTE_TYPE, BOOL_TYPE, SHORT_TYPE, INT_TYPE, LONG_TYPE, SHORT_TYPE:
DEFAULT:
RAISE IMPLEMENTATION_LIMIT_REACHED;
ENDTEST
ERROR
RAISE ;
ENDPROC
PROC Decode_One(VAR Decoder d, VAR LabComm_Stream s, VAR LabComm_Decoder_Sample samples{*})
VAR rawbytes buffer;
VAR num packet_type;
VAR num user_id;
VAR string type_name;
Decode_Packed s, packet_type;
WHILE packet_type = SAMPLE_DECL DO
Decode_Packed s, user_id;
Decode_String s, type_name;
Collect_Signature s, buffer;
FOR i FROM 1 TO Dim(samples, 1) DO
% samples{i}.prefix + ":Reg_If_Signature_Of_" + samples{i}.name % samples{i}, buffer, user_id;
ENDFOR
Decode_Packed s, packet_type;
ENDWHILE
IF packet_type >= SAMPLE_DATA THEN
FOR i FROM 1 TO Dim(samples, 1) DO
IF samples{i}.user_id = packet_type THEN
% samples{i}.prefix + ":Decode_And_Handle_" + samples{i}.name % d, s, samples{i};
ENDIF
ENDFOR
RETURN ;
ENDIF
RAISE UNKNOWN_PACKET_TYPE;
ERROR
RAISE ;
ENDPROC
PROC Init_Decoder(VAR Decoder d, VAR LabComm_Stream s)
VAR string version;
Decode_String s,version;
IF version<>LabCommVersion THEN
RAISE INCORRECT_LABCOMM_VERSION;
ENDIF
ERROR
RAISE ;
ENDPROC
PROC Init_Encoder(VAR Encoder e, VAR LabComm_Stream s)
Encode_String s, LabCommVersion;
e.next_user_id := SAMPLE_DATA;
ERROR
RAISE ;
ENDPROC
ENDMODULE
The implementation of LabComm in RAPID
Limitations of this implementation:
- The type double is not available due to limitations in RAPID. There is a
non-integer type with 64 bits but there is not marshalling utilities for it.
- Variable sized arrays is not available. There is no dynamic allocation,
possible solution is a max-size array (1024) and a integervalue denoting the
size.
- A RECORD (struct) cannot contain an array, but fixed size arrays are
available both in structs and stand alone. The current implementation creates
a RECORD with one member for each index in the array. Not an omptimal
solution, the alternativ would be a seperate variable.
- Decoding and encoding is done directly from a TCP socket.
- Every generated procedure is namespaced by declaring them LOCAL to the
generated module. They must be called by using runtime binding of procedure
names ( % proc_name % arg1, arg2, ...;). The generated types are not
declared local.
Usage:
# Declare a stream, LabComm_Stream:
$ VAR LabComm_Stream st;
This contains a socketdev wich must be created and connected or instatiated
through an accept.
$ SocketCreate st.soc;
$ SocketConnect st.soc, "127.0.0.1", 55555;
or
$ SocketAccept server_socket, st.soc;
# Initiate Encoder and/or Decoder with the stream:
$ VAR Decoder d;
$ Init_Decoder d, st;
$ VAR Encoder e;
$ Init_Encoder e, st;
This will read/write the version of LabComm to ensure compatibility, current
version is "LabComm2014".
# Initiate the labcomm samples:
LabComm trusts the application to manage each sample. It requests the samples,
as a list, when performing decoding or encoding.
This is done through the generated code which implies the procedures are LOCAL
and must be called with runtime bindings.
When initiating a decoder sample the name of the callback procedure to receive
such samples is suplied as a string.
$ PROC handle_samplename(prefix_samplename val)
$ ...
$ ENDPROC
$ VAR LabComm_Decoder_Sample ds{1};
$ % prefix:Dec_Reg_samplename % ds{1}, "handle_samplename";
NOTE: The callback must be of type procedure and not function. Functions cannot
be called with runtime bindings.
When initiating an encoder sample the stream must be supplied to let the
encoder send the sample signature.
$ VAR LabComm_Encoder_Sample es{1};
$ % prefix:Enc_Reg_samplename % e, st, es{1};
# Encode and/or decode samples:
$ Decode_One d, st, ds;
It returns as soon as any sample is decoded. The decoded sample is supplied as
argument to the callback procedure registered with the corresponding sample.
$ VAR prefix_samplename val;
$ <init val>
$ % prefix:Encode_samplename % e, st, es{1}, val;
# Complete example:
## LabComm definition:
example.lc >>
sample struct {
short sum;
short terms[2];
} foo;
<< EOF
## RAPID CODE
PROC handle_foo(example_foo val)
IF val.sum = val.terms.e1 + val.terms.e2 THEN
TPWrite "Verification successfull!";
ELSE
TPWrite "Verification failed!";
ENDIF
ENDPROC
PROC main()
VAR Decoder d;
VAR Encoder e;
VAR LabComm_Stream st;
VAR LabComm_Encoder_Sample es{1};
VAR LabComm_Decoder_Sample ds{1};
VAR example_foo val := [2,[1,1]];
SocketCreate st.soc;
SocketConnect st.soc, "127.0.0.1", 55555;
Init_Decoder d, st;
Init_Encoder e, st;
% "example:Enc_Reg_foo" % e, st, es{1};
% "example:Dec_Reg_foo" % ds{1}, "handle_foo";
% "example:Encode_foo" % e, st, es{1}, val;
Decode_One d, st, ds;
SocketClose st.soc;
ENDPROC
liblabcomm.a
liblabcomm.so
liblabcomm.so.1
liblabcomm2006.so.1
liblabcomm2006.so
liblabcomm2006.a
liblabcomm2014.so.1
liblabcomm2014.so
liblabcomm2014.a
## Macros
VERSION=2014
LIBVERSION=2014
include ../os_compat.mk
ALL_DEPS=../liblabcomm$(LIBVERSION).a ../liblabcomm$(LIBVERSION).so
# TODO: Support for Codesourcery ARM toolchain.
OBJS=labcomm$(VERSION).o \
labcomm$(VERSION)_memory.o \
labcomm$(VERSION)_error.o \
labcomm$(VERSION)_default_error_handler.o \
labcomm$(VERSION)_default_memory.o \
labcomm$(VERSION)_default_scheduler.o \
labcomm$(VERSION)_time.o \
labcomm$(VERSION)_scheduler.o \
labcomm$(VERSION)_encoder.o \
labcomm$(VERSION)_decoder.o \
labcomm$(VERSION)_dynamic_buffer_writer.o \
labcomm$(VERSION)_fd_reader.o \
labcomm$(VERSION)_type_signature.o \
labcomm$(VERSION)_fd_writer.o \
labcomm$(VERSION)_pthread_scheduler.o \
labcomm$(VERSION)_renaming.o \
labcomm$(VERSION)_renaming_registry.o \
labcomm$(VERSION)_renaming_encoder.o \
labcomm$(VERSION)_renaming_decoder.o
# Enable experimental objects by `make LABCOMM_EXPERIMENTAL=true`
ifeq ($(LABCOMM_EXPERIMENTAL),true)
OBJS += experimental/udp_hack.o experimental/ethaddr.o \
experimental/labcomm_thr_reader_writer.o \
experimental/ThrottleDrv/ethernet_drv.o \
experimental/ThrottleDrv/throttle_drv.o \
experimental/labcomm_udp_reader_writer.o
endif
# Enable experimental objects by `make LABCOMM_SIG_PARSER=true`
ifeq ($(LABCOMM_SIG_PARSER),true)
OBJS += experimental/labcomm2014_sig_parser.o
endif
LABCOMM_JAR=../../../compiler/labcomm$(LIBVERSION)_compiler.jar
LABCOMM=java -jar $(LABCOMM_JAR)
TESTS=test_labcomm_basic_type_encoding \
test_labcomm_generated_encoding \
test_signature_numbers \
test_labcomm \
test_labcomm_pthread_scheduler \
test_labcomm_copy \
test_labcomm_renaming_registry \
test_labcomm_renaming_encoder \
test_labcomm_renaming_decoder
#FIXME: test_labcomm_errors
TEST_DIR=test
## Targets
.PHONY: all
all: $(ALL_DEPS)
.PHONY: test
test: all $(TESTS:%=run-test-%)
.PHONY: clean
clean:
$(RM) *.o
$(RM) experimental/*.o
$(RM) experimental/ThrottleDrv/*.o
$(RM) test/*.o
$(RM) test/*.gch
$(RM) test/test_labcomm_errors
$(RM) test/testdata/gen/*.[cho]
$(RM) test/gen/*.[cho]
$(RM) -rf test/gen
.PHONY: distclean
distclean: clean
$(RM) ../liblabcomm$(LIBVERSION).so.1
$(RM) ../liblabcomm$(LIBVERSION).a
# rules invoked by 'all'
../liblabcomm$(LIBVERSION).so: ../liblabcomm$(LIBVERSION).so.1
if [ -h $@ ] ; then rm $@ ; fi
ln -s $(<:../%=%) $@
../liblabcomm$(LIBVERSION).so.1: $(OBJS:%.o=%.pic.o)
$(call MAKESHARED,$@,$(@:../%=%),$^)
../liblabcomm$(LIBVERSION).a: $(OBJS)
ar -r $@ $^
# Enable sig parser objects by `make labcomm2014_sig_PARSER=true`
ifeq ($(LABCOMM_SIG_PARSER),true)
experimental/test_sig_parser : experimental/labcomm2014_sig_parser.o experimental/test_sig_parser.c
endif
# compilation rules
%.pic.o: %.c
$(CC) -fPIC $(CFLAGS) -c -o $@ $<
%.o: %.c %.h
$(CC) $(CFLAGS) -c -o $@ $<
# rules invoked by 'test'
.PHONY: run-test-%
run-test-%: $(TEST_DIR)/gen/% | $(TEST_DIR)/gen
$(VALGRIND) $<
.PRECIOUS: $(TEST_DIR)/gen/%
$(TEST_DIR)/gen/%: $(TEST_DIR)/gen/%.o | $(TEST_DIR)/gen
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(TEST_DIR)/gen/%.o: $(TEST_DIR)/%.c | $(TEST_DIR)/gen
$(CC) $(CFLAGS_TEST) -o $@ -c $<
.PRECIOUS: $(TEST_DIR)/gen/%.c
.PRECIOUS: $(TEST_DIR)/gen/%.h
$(TEST_DIR)/gen/%.c $(TEST_DIR)/gen/%.h: $(TEST_DIR)/%.lc | $(TEST_DIR)/gen
$(LABCOMM) \
--c=$(TEST_DIR)/gen/$*.c \
--h=$(TEST_DIR)/gen/$*.h \
$<
$(LABCOMM_JAR):
@echo "======Building LabComm compiler======"
cd $(shell dirname $(LABCOMM_JAR)); ant jar
@echo "======End building LabComm compiler======"
$(TEST_DIR)/gen:
mkdir -p $@
# Extra compilation dependencies
labcomm$(VERSION).o: \
labcomm$(VERSION).c \
labcomm$(VERSION).h \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_fd_reader.o: \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_fd_writer.o: \
labcomm$(VERSION)_private.h
labcomm$(VERSION)_dynamic_buffer_writer.o: \
labcomm$(VERSION)_private.h
$(TEST_DIR)/gen/test_labcomm_basic_type_encoding.o: \
labcomm$(VERSION)_private.h
$(TEST_DIR)/gen/test_labcomm_generated_encoding.o: \
labcomm$(VERSION)_private.h \
$(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/gen/test_labcomm_generated_encoding: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_signature_numbers.c: \
$(TEST_DIR)/gen/another_encoding.h \
$(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/gen/test_signature_numbers: \
$(TEST_DIR)/gen/another_encoding.o \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm: \
$(TEST_DIR)/gen/test_sample.o
$(TEST_DIR)/gen/test_labcomm_copy: \
$(TEST_DIR)/gen/generated_encoding.o \
$(TEST_DIR)/gen/test_sample.o \
$(TEST_DIR)/gen/more_types.o
$(TEST_DIR)/gen/test_labcomm_renaming_registry: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm_renaming_encoder: \
$(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/gen/test_labcomm_renaming_decoder: \
$(TEST_DIR)/gen/generated_encoding.o
#define PC_MODE
#ifdef PC_MODE
#define DISPLAY_ERR(s) perror(s);
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
#else
#define DISPLAY_ERR(s) ;
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
//#include <linux/if_ether.h>
//#include <linux/if_packet.h>
//#include <linux/if_arp.h>
#include <net/if.h>
#include <netpacket/packet.h>
//#include <netinet/in.h>
#include "ethernet_drv.h"
#include "display.h"
// Some projects can not use stdio.h.
#ifndef LABCOMM_NO_STDIO
#include <stdio.h>
#endif
/** LOCAL FUNCTIONS **/
/* local type for the ethernet interface */
struct eth_int_t
{
struct ether_addr mac_adr; /* MAC address */
int socket_id; /* socket file descriptor */
int index; /* index of the eth interface */
unsigned char validity;
};
/***
Open an Ethernet Raw packet connection
***/
struct eth_int_t* eth_open(const char* eth_int_name)
{
struct eth_int_t* tmp_eth = NULL; /* pointer to ethernet interface struct */
struct ifreq ifr; /* struct used by ioctl function */
/* TO-DO: check if a ethernet socket has already been created for eth_int_name interface */
/* Ethernet interface name pointer valid ? */
if (NULL == eth_int_name)
{
errno = EINVAL;
DISPLAY_ERR("Input parameter NULL");
}
else
{
/* allocate memory for the Ethernet Interface */
tmp_eth = (struct eth_int_t*)malloc(sizeof(struct eth_int_t));
if (NULL == tmp_eth)
{
DISPLAY_ERR("Error allocating memory!");
}
else
{
/* creates a Packet Socket, raw delivery, accept all protocol */
tmp_eth->socket_id = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (-1 == tmp_eth->socket_id) /* error occurred during socket creation ? */
{
free(tmp_eth); /* deallocate the memory */
tmp_eth = NULL;
DISPLAY_ERR("Error in creating socket");
}
else
{
/* retrieve the Ethernet card MAC address */
strcpy(ifr.ifr_name, eth_int_name);
if (ioctl(tmp_eth->socket_id, SIOCGIFHWADDR, &ifr) == -1) /* error during the retrieve of MAC address ? */
{
close(tmp_eth->socket_id); /* close the socket */
free(tmp_eth); /* deallocate the memory */
tmp_eth = NULL;
DISPLAY_ERR("ioctl error SIOCGIFHWADDR");
}
else
{
/* copy the MAC address into the eth interface struct */
memcpy(tmp_eth->mac_adr.ether_addr_octet, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
/*retrieve the Ethernet interface index*/
if (ioctl(tmp_eth->socket_id, SIOCGIFINDEX, &ifr) == -1)/* error during the retrieve of index */
{
close(tmp_eth->socket_id); /* close the socket */
free(tmp_eth); /* deallocate the memory */
tmp_eth = NULL;
DISPLAY_ERR("ioctl error SIOCGIFINDEX");
}
else
{
/* copy the interface index into the eth interface struct */
tmp_eth->index = ifr.ifr_ifindex;
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
tmp_eth->mac_adr.ether_addr_octet[0],tmp_eth->mac_adr.ether_addr_octet[1],tmp_eth->mac_adr.ether_addr_octet[2],tmp_eth->mac_adr.ether_addr_octet[3],tmp_eth->mac_adr.ether_addr_octet[4],tmp_eth->mac_adr.ether_addr_octet[5]);
printf("Successfully got interface index for %s: %i\n",eth_int_name, tmp_eth->index);
}
}
}
}
}
return(tmp_eth);
}
/***
Close the Ethernet Raw packet connection
***/
int eth_close(struct eth_int_t* eth_int)
{
int ret = 0;
/* Ethernet interface pointer valid ? */
if (NULL == eth_int)
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter NULL");
}
else
{
if (-1 == close(eth_int->socket_id)) /* error during the closure of the socket ? */
{
ret = -1;
DISPLAY_ERR("Socket closure error");
}
else
{
free(eth_int); /* deallocate the memory */
eth_int = NULL;
}
}
return(ret);
}
/***
Returns the MAC address of the Ethernet Interface
***/
int eth_getMACadr(const struct eth_int_t* eth_int, struct ether_addr * mac_adr)
{
int ret = 0;
if ((NULL == eth_int) || (NULL == mac_adr)) /* Input parameters valid ? */
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
/* TO-DO: introduce a validity flag to be check before accessing to eth_int (better a crc) */
memcpy(mac_adr, &eth_int->mac_adr, sizeof(mac_adr));
}
return(ret);
}
/***
send a complete Ethernet Raw Packet
***/
int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length)
{
struct ethhdr *eth_header = NULL; /* Pointer to Ethernet frame header (Dest,Source,Type) */
struct sockaddr_ll socket_address;
int ret;
if ((NULL == eth_int) || (NULL == eth_frame))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) Null!");
}
else
{
eth_header = (struct ethhdr*)eth_frame;
/*prepare sockaddr_ll (address structure for PACKET_SOCKET) */
socket_address.sll_family = AF_PACKET;
socket_address.sll_addr[0] = eth_header->h_dest[0];
socket_address.sll_addr[1] = eth_header->h_dest[1];
socket_address.sll_addr[2] = eth_header->h_dest[2];
socket_address.sll_addr[3] = eth_header->h_dest[3];
socket_address.sll_addr[4] = eth_header->h_dest[4];
socket_address.sll_addr[5] = eth_header->h_dest[5];
socket_address.sll_addr[6] = 0x00; /* not used */
socket_address.sll_addr[7] = 0x00; /* not used */
socket_address.sll_halen = ETH_ALEN; /* Length of the MAC address */
socket_address.sll_ifindex = eth_int->index; /* Ethernet Interface index */
// The rest should be zero for sending, and are set by the system for receiving.
socket_address.sll_hatype = 0;
socket_address.sll_protocol = 0;
socket_address.sll_pkttype = 0;
//socket_address.sll_protocol = htons(ETH_P_IP); /* Physical layer protocol */
//socket_address.sll_hatype = ARPHRD_ETHER; /* ARP hardware identifier: Ethernet */
//socket_address.sll_pkttype = PACKET_OTHERHOST; /* Packet type: Another host */
/*send the Ethernet frame */
ret = sendto(eth_int->socket_id, eth_frame, length, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (ret == -1) /* error during the trasmission of the Ethernet frame ? */
{
DISPLAY_ERR("sendto error!");
}
}
return(ret);
}
/***
receive a complete Ethernet Raw Packet
***/
int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length)
{
int ret;
if ((NULL == eth_int) || (NULL == eth_frame))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) Null!");
}
else
{
/*Wait for incoming packet...*/
ret = recvfrom(eth_int->socket_id, (void*)eth_frame, length, 0, NULL, NULL);
if (ret == -1) /* error during the reception of the Ethernet frame ? */
{
DISPLAY_ERR("recvfrom error!");
}
}
return(ret);
}
#ifndef _ETHERNET_DRV_H_
#define _ETHERNET_DRV_H_
#include <net/ethernet.h>
struct eth_int_t;
struct eth_int_t* eth_open(const char* eth_int_name);
int eth_close(struct eth_int_t* eth_int);
int eth_getMACadr(const struct eth_int_t* eth_int, struct ether_addr *mac_adr);
int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length);
int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length);
#endif
#include "throttle_drv.h"
#include "ethernet_drv.h"
#include <errno.h>
#include "display.h"
#include "stdlib.h"
#include <string.h>
#include <time.h>
// #include <arpa/inet.h>
#define THROTTLENET_PROTO 0x544e
#define THR_DST_ADR_POS 0
#define THR_SRC_ADR_POS (THR_DST_ADR_POS + sizeof(((thr_header_t*)0)->dst_adr)) //6
#define THR_ETH_TYP_POS (THR_SRC_ADR_POS + sizeof(((thr_header_t*)0)->src_adr)) //12
#define THR_CHN_ID_POS (THR_ETH_TYP_POS + sizeof(((thr_header_t*)0)->eth_type)) //14
#define THR_FRAG_NUM_POS (THR_CHN_ID_POS + sizeof(((thr_header_t*)0)->chn_id)) //15
#define THR_FRAG_TOT_NUM_POS (THR_FRAG_NUM_POS + sizeof(((thr_header_t*)0)->frag_num)) //17
#define THR_FRAG_LEN_POS (THR_FRAG_TOT_NUM_POS + sizeof(((thr_header_t*)0)->frag_num_tot)) //19
#define THR_PAYLOAD_POS (THR_FRAG_LEN_POS + sizeof(((thr_header_t*)0)->frag_len)) //21
#define THR_MSG_HEADER_LEN THR_PAYLOAD_POS
#define THR_MSG_DST_ADR(thr_msg) (struct ether_addr*)(&thr_msg[THR_DST_ADR_POS])
#define THR_MSG_SRC_ADR(thr_msg) (struct ether_addr*)(&thr_msg[THR_SRC_ADR_POS])
#define THR_MSG_ETH_TYP(thr_msg) *(unsigned short*)(&thr_msg[THR_ETH_TYP_POS])
#define THR_MSG_CHN_ID(thr_msg) *(unsigned char*)(&thr_msg[THR_CHN_ID_POS])
#define THR_MSG_FRAG_NUM(thr_msg) *(unsigned short*)(&thr_msg[THR_FRAG_NUM_POS])
#define THR_MSG_FRAG_TOT_NUM(thr_msg) *(unsigned short*)(&thr_msg[THR_FRAG_TOT_NUM_POS])
#define THR_MSG_FRAG_LEN(thr_msg) *(unsigned short*)(&thr_msg[THR_FRAG_LEN_POS])
#define THR_MSG_PAYLOAD(thr_msg) (unsigned char*)(&thr_msg[THR_PAYLOAD_POS])
/* local type for the Throttle Channel structure */
struct thr_chn_t
{
struct ether_addr dst_adr; /* destination MAC address */
unsigned char id; /* Channel id */
unsigned short frag_size; /* Fragment size */
unsigned short freq; /* Message transmission frequency */
thr_msg_handler_t funct; /* Callback function invoked at the reception */
unsigned short msg_length;
unsigned char* p_msg;
struct ether_addr last_sender_adr;/* src MAC address of last message */
};
/* Type for the Throttle message */
typedef struct
{
struct ether_addr dst_adr; /* destination MAC address */
struct ether_addr src_adr; /* source MAC address */
unsigned short eth_type; /* ethernet packet type */
unsigned char chn_id; /* channel identification */
unsigned short frag_num; /* fragment number */
unsigned short frag_num_tot; /* total fragment number */
unsigned short frag_len; /* fragment length */
}thr_header_t;
/* Local functions */
static int thr_msg_check(const unsigned char* thr_msg, unsigned short chn_id, unsigned short length);
static struct eth_int_t* eth_int = NULL;
/**
* @fn int thr_init(const char* eth_int_name)
*
* @brief Initializes the Throttle Net Driver, enabling the Ethernet Raw communication for the eth_int_name interface.
*
* @param [in] eth_int_name: ethernet interface name (e.g. "eth0","eth1")
*
* @retval int: 0 on success; -1 on error and errno is set appropriately
*
*******************************************************************************/
int thr_init(const char* eth_int_name)
{
int ret = 0;
if (NULL == eth_int_name)
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter NULL");
}
else
{
eth_int = eth_open(eth_int_name); /* open the Ethernet socket */
if (NULL == eth_int)
{
ret = -1;
}
}
return(ret);
}
/**
* @fn struct thr_chn_t* thr_open_chn(const char* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, const thr_msg_handler_t funct);
*
* @brief Open a logic channel
*
* @param [in] dst_adr: destination MAC address;
* @param [in] chn_id: identification of the channel;
* @param [in] frag_size: fragment size;
* @param [in] freq: frequency of trasmission for each fragment;
* @param [in] msg_handler: callback invoked when a message is completely received;
*
* @retval struct thr_chn_t*: pointer to the Channel structure. NULL on error and errno is set appropriately.
*
*******************************************************************************/
struct thr_chn_t* thr_open_chn(const struct ether_addr* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, const thr_msg_handler_t funct)
{
struct thr_chn_t* tmp_chn = NULL; /* pointer to Channel structure */
/* TO-DO: check if a similar channel has already been created */
/* Input parameters not valid ? */
if ((NULL == dst_adr) || (0 == frag_size))
{
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
/* allocate memory for the Channel structure */
tmp_chn = (struct thr_chn_t*)malloc(sizeof(struct thr_chn_t));
if (NULL == tmp_chn)
{
DISPLAY_ERR("Error allocating memory!");
}
else
{
/* Update the Channel structure */
memcpy(&tmp_chn->dst_adr, dst_adr, sizeof(tmp_chn->dst_adr));
tmp_chn->id = chn_id;
tmp_chn->frag_size = frag_size;
tmp_chn->freq = freq;
tmp_chn->funct = funct;
}
#ifdef DEBUG
printf("thr_open_chn: callback = %x\n", tmp_chn->funct);
#endif
}
return(tmp_chn);
}
void thr_close_chn(struct thr_chn_t* c){
free(c);
}
/**
* @fn int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length)
*
* @brief Sends a Throttle message. A channel must be opened first.
*
* @param [in] thr_chn: pointer to the Throttle channel descriptor;
* @param [in] data: data buffer to be sent;
* @param [in] length: length of the data buffer;
*
* @retval int: number of byte sent, on success. -1 on error and errno is set appropriately.
*
*******************************************************************************/
int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length)
{
unsigned char* thr_msg;
unsigned char i;
int ret = 0;
/* Check the input parameters */
if ((NULL == thr_chn) || (NULL == data) || (0 == length))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
if (0 == thr_chn->frag_size)
{
ret = -1;
errno = ERANGE;
DISPLAY_ERR("Division by zero");
}
else
{
/* allocate memory for the Throttle Message */
thr_msg = (unsigned char*)malloc(THR_MSG_HEADER_LEN + thr_chn->frag_size);
if (NULL == thr_msg)
{
ret = -1;
DISPLAY_ERR("Error allocating memory!");
}
else
{
/* Compose the Ethernet Frame to be sent */
memcpy(THR_MSG_DST_ADR(thr_msg), &thr_chn->dst_adr, sizeof(thr_chn->dst_adr)); /* Destiantion MAC Address */
eth_getMACadr(eth_int, THR_MSG_SRC_ADR(thr_msg)); /* Source MAC Address */
THR_MSG_ETH_TYP(thr_msg) = htons(THROTTLENET_PROTO); /* Ethernet Packet Type */
THR_MSG_CHN_ID(thr_msg) = thr_chn->id; /* Channel identification */
THR_MSG_FRAG_TOT_NUM(thr_msg) = ((length - 1) / thr_chn->frag_size) + 1; /* Total number of fragment */
struct timespec thr_time;
thr_time.tv_sec = thr_chn->freq / 1000;
thr_time.tv_nsec = (thr_chn->freq % 1000) * 1000000;
/* Message is splitted into fragments and they are sent */
for (i = 1; i <= THR_MSG_FRAG_TOT_NUM(thr_msg); i++)
{
THR_MSG_FRAG_NUM(thr_msg) = i; /* fragment number */
/* update the fragment length */
if (length >= thr_chn->frag_size)
{
THR_MSG_FRAG_LEN(thr_msg) = thr_chn->frag_size;
length -= thr_chn->frag_size;
}
else
{
THR_MSG_FRAG_LEN(thr_msg) = length;
}
memcpy ((void*)THR_MSG_PAYLOAD(thr_msg), (void*)data, THR_MSG_FRAG_LEN(thr_msg)); /* update the payload */
ret = eth_send(eth_int, &thr_msg[0], (THR_MSG_HEADER_LEN + THR_MSG_FRAG_LEN(thr_msg))); /* send the message */
if (-1 == ret) /*Error during the Ethernet trasmission ? */
{
DISPLAY_ERR("Error during Throttle msg trasmission!");
break;
}
else
{
data += THR_MSG_FRAG_LEN(thr_msg);
nanosleep(&thr_time, NULL);
}
}
/*deallocate the memory */
free(thr_msg);
thr_msg = NULL;
}
}
}
return(ret);
}
int thr_receive(struct thr_chn_t* thr_chn, unsigned char* data, void* param)
{
unsigned char* thr_msg = NULL;
unsigned char* p_data = NULL;
unsigned short frag_index = 1;
short byte_rec = 0;
unsigned char msg_received = 0;
int ret;
if ((NULL == thr_chn) || (NULL == data) || (NULL == thr_chn->funct) || (NULL == param))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
/* allocate memory for the Throttle Message */
thr_msg = (unsigned char*)malloc(THR_MSG_HEADER_LEN + thr_chn->frag_size);
if (NULL == thr_msg)
{
ret = -1;
DISPLAY_ERR("Error allocating memory!");
}
else
{
p_data = data;
do
{
byte_rec = eth_receive(eth_int, thr_msg, (THR_MSG_HEADER_LEN + thr_chn->frag_size)); /* receive the Ethernet Raw packet */
if (-1 == byte_rec)
{
/* discard the message */
DISPLAY_ERR("Error during Throttle msg reception: Fragment discarded.");
}
else
{
/* check if the Ethernet Raw message is correct (Ethernet protocol, Channel ID, length) */
ret = thr_msg_check(thr_msg, thr_chn->id, byte_rec);
if (ret < 0)
{
//printf("Throttle msg mismatch: Fragment discarded.\n");
}
else
{
#ifdef DEBUG
printf("thr_receive: Message Index %d on %d. Actual Index %d\n", THR_MSG_FRAG_NUM(thr_msg), THR_MSG_FRAG_TOT_NUM(thr_msg), frag_index);
#endif
if (frag_index == THR_MSG_FRAG_NUM(thr_msg)) /* The fragment is the one expected ? */
{
/* Rebuild the original data linking the payloads of each fragment */
memcpy((void*)p_data, (void*)THR_MSG_PAYLOAD(thr_msg), THR_MSG_FRAG_LEN(thr_msg));
p_data += THR_MSG_FRAG_LEN(thr_msg); /* update the pointer to the buffer */
frag_index++; /* update the fragment index */
ret = p_data - data; /* update the number of received byte */
if (frag_index > THR_MSG_FRAG_TOT_NUM(thr_msg))
{
msg_received = 1;
}
}
else
{
printf("thr_receive: Fragment mismatch: Fragment discarded.\n");
frag_index = 1;
p_data = data;
}
}
}
}while (msg_received != 1);
thr_chn->p_msg = (unsigned char*)malloc(ret);
if (NULL == thr_chn->p_msg)
{
ret = -1;
DISPLAY_ERR("Error allocating memory!");
}
else
{
#ifdef DEBUG
printf("thr_receive: Number of byte receive %d\n",ret);
#endif
thr_chn->msg_length = ret;
memcpy(thr_chn->p_msg, data, ret); /* copy the msg into the thr structure */
memcpy(&thr_chn->last_sender_adr, THR_MSG_SRC_ADR(thr_msg), 6); /* ... and the address of the sender */
#ifdef DEBUG
printf("thr_receive: calling %x\n", thr_chn->funct);
#endif
(thr_chn->funct)(param);
free(thr_chn->p_msg);
thr_chn->p_msg = NULL;
}
/* deallocate memory for the Throttle Message */
free(thr_msg);
thr_msg = NULL;
p_data = NULL;
}
}
return(ret);
}
static int thr_msg_check(const unsigned char* thr_msg, unsigned short chn_id, unsigned short length)
{
int ret = 0;
if (length > THR_MSG_HEADER_LEN) /* Ethernet Raw Packet contains a valid Payload ? */
{
if (THROTTLENET_PROTO == ntohs(THR_MSG_ETH_TYP(thr_msg))) /* Is Ethernet Type THROTTLENET Protocol ? */
{
if (THR_MSG_CHN_ID(thr_msg) == chn_id) /* Is Channel identification correct ? */
{
/* throttle message is correct */
}
else
{
ret = -1;
}
}
else
{
/* discard the message */
ret = -2;
}
}
else
{
/* discard the message */
ret = -3;
}
return(ret);
}
int thr_read(struct thr_chn_t* thr_chn, unsigned char* data, int length)
{
int ret = 0;
if ((NULL == thr_chn) || (NULL == data))
{
ret = -1;
errno = EINVAL;
DISPLAY_ERR("Input parameter(s) NULL");
}
else
{
if (length > thr_chn->msg_length)
{
length = thr_chn->msg_length;
#ifdef DEBUG
printf("thr_read: truncating length to %d\n", length);
#endif
}
#ifdef DEBUG
printf("thr_read: calling memcpy(%x, %x, %d\n", data, thr_chn->p_msg, length);
#endif
memcpy(data, thr_chn->p_msg, length); /* copy the msg into the thr structure */
ret = length;
thr_chn->msg_length = 0;
}
return(ret);
}
struct ether_addr* get_sender_addr(struct thr_chn_t* ch) {
return &ch->last_sender_adr;
}
unsigned char get_channel(struct thr_chn_t* ch) {
return ch->id;
}
#ifndef _THROTTLE_DRV_H_
#define _THROTTLE_DRV_H_
//#define ETH_ADR_SIZE 6
#include <net/ethernet.h>
/* typedef of the callback used to manage the received Ethernet Frame (the User Data)*/
typedef int (*thr_msg_handler_t)(void* data);
struct thr_chn_t;
int thr_init(const char* eth_int);
struct thr_chn_t* thr_open_chn(const struct ether_addr* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, thr_msg_handler_t funct);
void thr_close_chn(struct thr_chn_t* c);
int thr_receive (struct thr_chn_t* thr_chn, unsigned char* data, void* param);
int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length);
int thr_read(struct thr_chn_t* thr_chn, unsigned char* data, int length);
struct ether_addr * get_sender_addr(struct thr_chn_t* ch);
unsigned char get_channel(struct thr_chn_t* ch);
#endif