From 8bde857aee75e5865728ddb2a27525ea66a2554c Mon Sep 17 00:00:00 2001 From: Juri Glass Date: Thu, 16 Jun 2011 12:41:21 +0200 Subject: [PATCH] initial commit basic functionalities are in, though some parts are missing --- sml/Makefile | 50 ++++ sml/include/sml/sml.h | 34 +++ sml/include/sml/sml_attention_response.h | 31 +++ sml/include/sml/sml_boolean.h | 23 ++ sml/include/sml/sml_close_request.h | 28 +++ sml/include/sml/sml_close_response.h | 23 ++ sml/include/sml/sml_crc16.h | 22 ++ sml/include/sml/sml_get_list_request.h | 39 ++++ sml/include/sml/sml_get_list_response.h | 33 +++ .../sml/sml_get_proc_parameter_request.h | 32 +++ .../sml/sml_get_profile_pack_request.h | 42 ++++ .../sml/sml_get_profile_pack_response.h | 36 +++ sml/include/sml/sml_list.h | 43 ++++ sml/include/sml/sml_message.h | 70 ++++++ sml/include/sml/sml_number.h | 35 +++ sml/include/sml/sml_octet_string.h | 41 ++++ sml/include/sml/sml_open_request.h | 40 ++++ sml/include/sml/sml_open_response.h | 32 +++ .../sml/sml_set_proc_parameter_request.h | 32 +++ sml/include/sml/sml_shared.h | 101 ++++++++ sml/include/sml/sml_status.h | 26 +++ sml/include/sml/sml_time.h | 25 ++ sml/include/sml/sml_transport.h | 19 ++ sml/include/sml/sml_tree.h | 64 +++++ sml/include/sml/sml_value.h | 39 ++++ sml/src/sml.c | 133 +++++++++++ sml/src/sml_attention_response.c | 47 ++++ sml/src/sml_boolean.c | 22 ++ sml/src/sml_close_request.c | 52 +++++ sml/src/sml_close_response.c | 36 +++ sml/src/sml_crc16.c | 39 ++++ sml/src/sml_get_list_request.c | 88 +++++++ sml/src/sml_get_list_response.c | 61 +++++ sml/src/sml_get_proc_parameter_request.c | 45 ++++ sml/src/sml_get_profile_pack_request.c | 106 +++++++++ sml/src/sml_get_profile_pack_response.c | 18 ++ sml/src/sml_list.c | 114 +++++++++ sml/src/sml_message.c | 221 ++++++++++++++++++ sml/src/sml_number.c | 43 ++++ sml/src/sml_octet_string.c | 113 +++++++++ sml/src/sml_open_request.c | 105 +++++++++ sml/src/sml_open_response.c | 53 +++++ sml/src/sml_set_proc_parameter_request.c | 26 +++ sml/src/sml_shared.c | 123 ++++++++++ sml/src/sml_status.c | 50 ++++ sml/src/sml_time.c | 42 ++++ sml/src/sml_transport.c | 101 ++++++++ sml/src/sml_tree.c | 115 +++++++++ sml/src/sml_value.c | 108 +++++++++ 49 files changed, 2821 insertions(+) create mode 100644 sml/Makefile create mode 100644 sml/include/sml/sml.h create mode 100644 sml/include/sml/sml_attention_response.h create mode 100644 sml/include/sml/sml_boolean.h create mode 100644 sml/include/sml/sml_close_request.h create mode 100644 sml/include/sml/sml_close_response.h create mode 100644 sml/include/sml/sml_crc16.h create mode 100644 sml/include/sml/sml_get_list_request.h create mode 100644 sml/include/sml/sml_get_list_response.h create mode 100644 sml/include/sml/sml_get_proc_parameter_request.h create mode 100644 sml/include/sml/sml_get_profile_pack_request.h create mode 100644 sml/include/sml/sml_get_profile_pack_response.h create mode 100644 sml/include/sml/sml_list.h create mode 100644 sml/include/sml/sml_message.h create mode 100644 sml/include/sml/sml_number.h create mode 100644 sml/include/sml/sml_octet_string.h create mode 100644 sml/include/sml/sml_open_request.h create mode 100644 sml/include/sml/sml_open_response.h create mode 100644 sml/include/sml/sml_set_proc_parameter_request.h create mode 100644 sml/include/sml/sml_shared.h create mode 100644 sml/include/sml/sml_status.h create mode 100644 sml/include/sml/sml_time.h create mode 100644 sml/include/sml/sml_transport.h create mode 100644 sml/include/sml/sml_tree.h create mode 100644 sml/include/sml/sml_value.h create mode 100644 sml/src/sml.c create mode 100644 sml/src/sml_attention_response.c create mode 100644 sml/src/sml_boolean.c create mode 100644 sml/src/sml_close_request.c create mode 100644 sml/src/sml_close_response.c create mode 100644 sml/src/sml_crc16.c create mode 100644 sml/src/sml_get_list_request.c create mode 100644 sml/src/sml_get_list_response.c create mode 100644 sml/src/sml_get_proc_parameter_request.c create mode 100644 sml/src/sml_get_profile_pack_request.c create mode 100644 sml/src/sml_get_profile_pack_response.c create mode 100644 sml/src/sml_list.c create mode 100644 sml/src/sml_message.c create mode 100644 sml/src/sml_number.c create mode 100644 sml/src/sml_octet_string.c create mode 100644 sml/src/sml_open_request.c create mode 100644 sml/src/sml_open_response.c create mode 100644 sml/src/sml_set_proc_parameter_request.c create mode 100644 sml/src/sml_shared.c create mode 100644 sml/src/sml_status.c create mode 100644 sml/src/sml_time.c create mode 100644 sml/src/sml_transport.c create mode 100644 sml/src/sml_tree.c create mode 100644 sml/src/sml_value.c diff --git a/sml/Makefile b/sml/Makefile new file mode 100644 index 0000000..fdbe80f --- /dev/null +++ b/sml/Makefile @@ -0,0 +1,50 @@ +CFLAGS+=-I./include/ -fPIC -g -Wall + +LIB_DIR=./lib +OBJ_LIB=$(LIB_DIR)/libsml.o +DYN_LIB=$(LIB_DIR)/libsml.so +ST_LIB=$(LIB_DIR)/libsml.a + +OBJS = \ + src/sml.o \ + src/sml_attention_response.o \ + src/sml_transport.o \ + src/sml_octet_string.o \ + src/sml_shared.o \ + src/sml_number.o \ + src/sml_message.o \ + src/sml_time.o \ + src/sml_list.o \ + src/sml_status.o \ + src/sml_value.o \ + src/sml_tree.o \ + src/sml_boolean.o \ + src/sml_crc16.o \ + src/sml_open_request.o \ + src/sml_open_response.o \ + src/sml_get_list_request.o \ + src/sml_get_list_response.o \ + src/sml_close_request.o \ + src/sml_close_response.o \ + src/sml_set_proc_parameter_request.o \ + src/sml_get_proc_parameter_request.o \ + src/sml_get_profile_pack_request.o \ + src/sml_get_profile_pack_response.o \ + + +libsml: $(DYN_LIB) $(ST_LIB) $(OBJ_LIB) + +$(DYN_LIB): $(OBJS) + $(LD) -shared -o $@ $^ + +$(OBJ_LIB): $(OBJS) + $(LD) -r -o $@ $^ + +$(ST_LIB): $(OBJS) + $(AR) -rs $@ $^ + +.PHONY: clean +clean: + @rm -f src/*.o + @rm -f $(LIB_DIR)/*.so $(LIB_DIR)/*.a $(LIB_DIR)/*.o + diff --git a/sml/include/sml/sml.h b/sml/include/sml/sml.h new file mode 100644 index 0000000..707141f --- /dev/null +++ b/sml/include/sml/sml.h @@ -0,0 +1,34 @@ +#ifndef _SML_H +#define _SML_H + +#include "sml_message.h" +#include "sml_shared.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + sml_message **messages; + short messages_len; + sml_buffer *buf; +} sml_file; + +// Parses a SML file. +sml_file *sml_file_parse(unsigned char *buffer, size_t buffer_len); +sml_file *sml_file_init(); +void sml_file_add_message(sml_file *file, sml_message *message); +void sml_file_write(sml_file *file); +void sml_file_free(sml_file *file); +void sml_file_print(sml_file *file); + +void mc_sml_hexdump(unsigned char *buffer, size_t buffer_len); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_attention_response.h b/sml/include/sml/sml_attention_response.h new file mode 100644 index 0000000..4a616d1 --- /dev/null +++ b/sml/include/sml/sml_attention_response.h @@ -0,0 +1,31 @@ + +#ifndef _SML_ATTENTION_RESPONSE_H +#define _SML_ATTENTION_RESPONSE_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_tree.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *server_id; + octet_string *attention_number; + octet_string *attention_message; // optional + sml_tree *attention_details; // optional +} sml_attention_response; + +sml_attention_response *sml_attention_response_parse(sml_buffer *buf); + +void sml_attention_response_free(sml_attention_response *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_boolean.h b/sml/include/sml/sml_boolean.h new file mode 100644 index 0000000..8426237 --- /dev/null +++ b/sml/include/sml/sml_boolean.h @@ -0,0 +1,23 @@ +#ifndef _SML_BOOLEAN_H +#define _SML_BOOLEAN_H + +#define SML_BOOLEAN_TRUE 0xFF +#define SML_BOOLEAN_FALSE 0x00 + +#include "sml_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef u8 sml_boolean; + +sml_boolean sml_boolean_parse(sml_buffer *buf); +void sml_boolean_write(sml_boolean boolean, sml_buffer *buf); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_close_request.h b/sml/include/sml/sml_close_request.h new file mode 100644 index 0000000..dc76506 --- /dev/null +++ b/sml/include/sml/sml_close_request.h @@ -0,0 +1,28 @@ +#ifndef _SML_CLOSE_REQUEST_H +#define _SML_CLOSE_REQUEST_H + +#include "sml_shared.h" +#include "sml_octet_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + sml_signature *global_signature; // optional +} sml_close_request; + +sml_close_request *sml_close_request_init(); + +void sml_close_request_write(sml_close_request *msg, sml_buffer *buf); + +sml_close_request * sml_close_request_parse(sml_buffer *buf); + +void sml_close_request_free(sml_close_request *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_close_response.h b/sml/include/sml/sml_close_response.h new file mode 100644 index 0000000..a08c85d --- /dev/null +++ b/sml/include/sml/sml_close_response.h @@ -0,0 +1,23 @@ + +#ifndef _SML_CLOSE_RESPONSE_H +#define _SML_CLOSE_RESPONSE_H + +#include "sml_close_request.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef sml_close_request sml_close_response; + +sml_close_response *sml_close_response_parse(sml_buffer *buf); + +void sml_close_response_free(sml_close_response *msg); + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/sml/include/sml/sml_crc16.h b/sml/include/sml/sml_crc16.h new file mode 100644 index 0000000..2b22f9b --- /dev/null +++ b/sml/include/sml/sml_crc16.h @@ -0,0 +1,22 @@ +#ifndef SML_CRC16_H_ +#define SML_CRC16_H_ + +#include "sml_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// CRC16 FSC implementation based on DIN 62056-46 +u16 sml_crc16_calculate(unsigned char *cp, int len) ; + +#ifdef __cplusplus +} +#endif + + +#endif /* SML_CRC16_H_ */ + + + diff --git a/sml/include/sml/sml_get_list_request.h b/sml/include/sml/sml_get_list_request.h new file mode 100644 index 0000000..09d9927 --- /dev/null +++ b/sml/include/sml/sml_get_list_request.h @@ -0,0 +1,39 @@ +#ifndef _SML_GET_LIST_REQUEST_H +#define _SML_GET_LIST_REQUEST_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_time.h" +#include "sml_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *client_id; + octet_string *server_id; // optional + octet_string *username; // optional + octet_string *password; // optional + octet_string *list_name; // optional + + +} sml_get_list_request; + + + +sml_get_list_request *sml_get_list_request_parse(sml_buffer *buf); + +sml_get_list_request* sml_get_list_request_init(); + +void sml_get_list_request_write(sml_get_list_request *msg, sml_buffer *buf); + +void sml_get_list_request_free(sml_get_list_request *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_get_list_response.h b/sml/include/sml/sml_get_list_response.h new file mode 100644 index 0000000..b32225a --- /dev/null +++ b/sml/include/sml/sml_get_list_response.h @@ -0,0 +1,33 @@ +#ifndef _SML_GET_LIST_RESPONSE_H +#define _SML_GET_LIST_RESPONSE_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_time.h" +#include "sml_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *client_id; // optional + octet_string *server_id; + octet_string *list_name; // optional + sml_time *act_sensor_time; // optional + sml_list *val_list; + sml_signature *list_signature; // optional + sml_time *act_gateway_time; // optional +} sml_get_list_response; + +sml_get_list_response *sml_get_list_response_parse(sml_buffer *buf); + +void sml_get_list_response_free(sml_get_list_response *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_get_proc_parameter_request.h b/sml/include/sml/sml_get_proc_parameter_request.h new file mode 100644 index 0000000..32fe8b6 --- /dev/null +++ b/sml/include/sml/sml_get_proc_parameter_request.h @@ -0,0 +1,32 @@ +#ifndef _SML_GET_PROC_PARAMETER_REQUEST_H +#define _SML_GET_PROC_PARAMETER_REQUEST_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_tree.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *server_id; // optional + octet_string *username; // optional + octet_string *password; // optional + sml_tree_path *parameter_tree_path; + sml_tree *parameter_tree; +} sml_get_proc_parameter_request; + +sml_get_proc_parameter_request *sml_get_proc_parameter_request_init(); + +void sml_get_proc_parameter_request_write(sml_get_proc_parameter_request *msg, sml_buffer *buf); + +void sml_get_proc_parameter_request_free(sml_get_proc_parameter_request *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_get_profile_pack_request.h b/sml/include/sml/sml_get_profile_pack_request.h new file mode 100644 index 0000000..1af29c8 --- /dev/null +++ b/sml/include/sml/sml_get_profile_pack_request.h @@ -0,0 +1,42 @@ +#ifndef _SML_GET_PROFILE_PACK_REQUEST_H +#define _SML_GET_PROFILE_PACK_REQUEST_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_time.h" +#include "sml_list.h" +#include "sml_tree.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *server_id; // optional + octet_string *username; // optional + octet_string *password; // optional + sml_boolean with_rawdata; // optional + sml_time *begin_time; // optional + sml_time *end_time; // optional + sml_tree_path *parameter_tree_path; + // sml_object_list * object_list; // optional sml_object_list not implemented yet + sml_tree *das_details; // optional +} sml_get_profile_pack_request; + + +sml_get_profile_pack_request *sml_get_profile_pack_request_parse(sml_buffer *buf); + +sml_get_profile_pack_request *sml_get_profile_pack_request_init(); + +void sml_get_profile_pack_request_write(sml_get_profile_pack_request *msg, sml_buffer *buf); + +void sml_get_profile_pack_request_free(sml_get_profile_pack_request *msg); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_get_profile_pack_response.h b/sml/include/sml/sml_get_profile_pack_response.h new file mode 100644 index 0000000..ef21721 --- /dev/null +++ b/sml/include/sml/sml_get_profile_pack_response.h @@ -0,0 +1,36 @@ +#ifndef _SML_GET_PROFILE_PACK_RESPONSE_H +#define _SML_GET_PROFILE_PACK_RESPONSE_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_time.h" +#include "sml_list.h" +#include "sml_tree.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *server_id; + sml_time *act_time; // specified by germans (current time was meant) ;) + u32 *reg_period; + sml_tree_path *parameter_tree_path; + sml_list *list_of_sml_prof_obj_header_entry; + sml_list *list_of_sml_prof_obj_period_entry; + octet_string *rawdata; // optional + sml_signature *profile_signature; // optional + +} sml_get_profile_pack_response; + +sml_get_profile_pack_response *sml_get_profile_pack_response_parse(sml_buffer *buf); + +void sml_get_profile_pack_response_free(sml_get_profile_pack_response *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_list.h b/sml/include/sml/sml_list.h new file mode 100644 index 0000000..dad1091 --- /dev/null +++ b/sml/include/sml/sml_list.h @@ -0,0 +1,43 @@ + + +#ifndef _SML_LIST_H +#define _SML_LIST_H + +#include "sml_time.h" +#include "sml_octet_string.h" +#include "sml_number.h" +#include "sml_status.h" +#include "sml_value.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct sml_list_entry { + octet_string *obj_name; + sml_status *status; // optional + sml_time *val_time; // optional + sml_unit unit; // optional + i8 scaler; // optional + sml_value *value; + sml_signature *value_signature; // optional + + // list specific + struct sml_list_entry *next; +} sml_list; + +sml_list *sml_list_init(); + +void sml_list_write(sml_list *list, sml_buffer *buf); + +sml_list *sml_list_parse(sml_buffer *buf); + +void sml_list_free(sml_list *list); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_message.h b/sml/include/sml/sml_message.h new file mode 100644 index 0000000..6d5fb13 --- /dev/null +++ b/sml/include/sml/sml_message.h @@ -0,0 +1,70 @@ + +#ifndef _SML_MESSAGE_H +#define _SML_MESSAGE_H + +#include +#include "sml_octet_string.h" +#include "sml_time.h" +#include "sml_list.h" +#include "sml_tree.h" + +#include "sml_open_request.h" +#include "sml_open_response.h" +#include "sml_get_list_response.h" +#include "sml_close_request.h" +#include "sml_close_response.h" +#include "sml_set_proc_parameter_request.h" + +#define SML_MESSAGE_OPEN_REQUEST 0x00000100 +#define SML_MESSAGE_OPEN_RESPONSE 0x00000101 +#define SML_MESSAGE_CLOSE_REQUEST 0x00000200 +#define SML_MESSAGE_CLOSE_RESPONSE 0x00000201 +#define SML_MESSAGE_GET_PROFILE_PACK_REQUEST 0x00000300 +#define SML_MESSAGE_GET_PROFILE_PACK_RESPONSE 0x00000301 +#define SML_MESSAGE_GET_PROFILE_LIST_REQUEST 0x00000400 +#define SML_MESSAGE_GET_PROFILE_LIST_RESPONSE 0x00000401 +#define SML_MESSAGE_GET_PROC_PARAMETER_REQUEST 0x00000500 +#define SML_MESSAGE_GET_PROC_PARAMETER_RESPONSE 0x00000501 +#define SML_MESSAGE_SET_PROC_PARAMETER_REQUEST 0x00000600 +#define SML_MESSAGE_SET_PROC_PARAMETER_RESPONSE 0x00000601 +#define SML_MESSAGE_GET_LIST_REQUEST 0x00000700 +#define SML_MESSAGE_GET_LIST_RESPONSE 0x00000701 +#define SML_MESSAGE_ATTENTION_RESPONSE 0x0000FF01 + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + u16 tag; + void *data; +} sml_message_body; + +typedef struct { + octet_string *transaction_id; + u8 group_id; + u8 abort_on_error; + sml_message_body *message_body; + u16 crc; + /* end of message */ +} sml_message; + +// SML MESSAGE +sml_message *sml_message_parse(sml_buffer *buf); +sml_message *sml_message_init(); // Sets a transaction id. +void sml_message_free(sml_message *msg); +void sml_message_write(sml_message *msg, sml_buffer *buf); + +// SML_MESSAGE_BODY +sml_message_body *sml_message_body_parse(sml_buffer *buf); +sml_message_body *sml_message_body_init(u16 tag, void *data); +void sml_message_body_free(sml_message_body *message_body); +void sml_message_body_write(sml_message_body *message_body, sml_buffer *buf); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_number.h b/sml/include/sml/sml_number.h new file mode 100644 index 0000000..e637e85 --- /dev/null +++ b/sml/include/sml/sml_number.h @@ -0,0 +1,35 @@ + +#ifndef _SML_NUMBER_H +#define _SML_NUMBER_H + +#include "sml_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// Parses a number. Identified by type (SML_TYPE_INTEGER or SML_TYPE_UNSIGNED) +// and maximal number of bytes (SML_TYPE_NUMBER_8, SML_TYPE_NUMBER_16, +// SML_TYPE_NUMBER_32, SML_TYPE_NUMBER_64) +u64 mc_sml_parse_number(sml_buffer *buf, unsigned char type, int max_size); + +#define mc_sml_parse_u8(buf) (u8) mc_sml_parse_number(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_8) +#define mc_sml_parse_u16(buf) (u16) mc_sml_parse_number(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_16) +#define mc_sml_parse_u32(buf) (u32) mc_sml_parse_number(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_32) +#define mc_sml_parse_u64(buf) (u64) mc_sml_parse_number(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_64) +#define mc_sml_parse_i8(buf) (i8) mc_sml_parse_number(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_8) +#define mc_sml_parse_i16(buf) (i16) mc_sml_parse_number(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_16) +#define mc_sml_parse_i32(buf) (i32) mc_sml_parse_number(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_32) +#define mc_sml_parse_i64(buf) (i64) mc_sml_parse_number(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_64) + +void sml_number_write(unsigned char type, int size, u64 value, sml_buffer *buf); + +typedef u8 sml_unit; + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_octet_string.h b/sml/include/sml/sml_octet_string.h new file mode 100644 index 0000000..f405960 --- /dev/null +++ b/sml/include/sml/sml_octet_string.h @@ -0,0 +1,41 @@ +#ifndef _SML_OCTET_STRING_H +#define _SML_OCTET_STRING_H + +#include +#include "sml_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + unsigned char *str; + int len; +} octet_string; + +// sml signature +typedef octet_string sml_signature; + +octet_string *sml_octet_string_init(unsigned char *str, int length); + +octet_string *sml_octet_string_init_from_hex(char *str); + +void sml_octet_string_free(octet_string *str); + +// Parses a octet string, updates the buffer accordingly, memory must be free'd elsewhere. +octet_string *sml_octet_string_parse(sml_buffer *buf); + +void sml_octet_string_write(octet_string *str, sml_buffer *buf); + +int sml_octet_string_cmp_with_hex(octet_string *str, char *hex); + +octet_string *sml_octet_string_generate_uuid(); + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/sml/include/sml/sml_open_request.h b/sml/include/sml/sml_open_request.h new file mode 100644 index 0000000..5a84ba7 --- /dev/null +++ b/sml/include/sml/sml_open_request.h @@ -0,0 +1,40 @@ +#ifndef _SML_OPEN_REQUEST_H +#define _SML_OPEN_REQUEST_H + +#include "sml_shared.h" +#include "sml_octet_string.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *codepage; // optional + octet_string *client_id; + octet_string *req_file_id; + octet_string *server_id; // optional + octet_string *username; // optional + octet_string *password; // optional + u8 sml_version; // optional +} sml_open_request; + +//sml_open_request *sml_open_request_init(); + +//sml_open_request *sml_open_request_init(char* client_id,char* req_file_id, char* server_id); + +sml_open_request *sml_open_request_init(); + +void sml_open_request_write(sml_open_request *msg, sml_buffer *buf); + +sml_open_request *sml_open_request_parse(sml_buffer *buf); + +void sml_open_request_free(sml_open_request *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_open_response.h b/sml/include/sml/sml_open_response.h new file mode 100644 index 0000000..0006b64 --- /dev/null +++ b/sml/include/sml/sml_open_response.h @@ -0,0 +1,32 @@ + +#ifndef _SML_OPEN_RESPONSE_H +#define _SML_OPEN_RESPONSE_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *codepage; // optional + octet_string *client_id; // optional + octet_string *req_file_id; + octet_string *server_id; + sml_time *ref_time; // optional + u8 sml_version; // optional +} sml_open_response; + +sml_open_response *sml_open_response_parse(sml_buffer *buf); + +void sml_open_response_free(sml_open_response *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_set_proc_parameter_request.h b/sml/include/sml/sml_set_proc_parameter_request.h new file mode 100644 index 0000000..bb4295c --- /dev/null +++ b/sml/include/sml/sml_set_proc_parameter_request.h @@ -0,0 +1,32 @@ +#ifndef _SML_SET_PROC_PARAMETER_REQUEST_H +#define _SML_SET_PROC_PARAMETER_REQUEST_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_tree.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + octet_string *server_id; // optional + octet_string *username; // optional + octet_string *password; // optional + sml_tree_path *parameter_tree_path; + sml_tree *parameter_tree; +} sml_set_proc_parameter_request; + +sml_set_proc_parameter_request *sml_set_proc_parameter_request_init(); + +void sml_set_proc_parameter_request_write(sml_set_proc_parameter_request *msg, sml_buffer *buf); + +void sml_set_proc_parameter_request_free(sml_set_proc_parameter_request *msg); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_shared.h b/sml/include/sml/sml_shared.h new file mode 100644 index 0000000..4845db9 --- /dev/null +++ b/sml/include/sml/sml_shared.h @@ -0,0 +1,101 @@ +#ifndef _SML_SHARED_H +#define _SML_SHARED_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +#define SML_ANOTHER_TL 0x80 +#define SML_TYPE_FIELD 0x70 +#define SML_LENGTH_FIELD 0xF +#define SML_OPTIONAL_SKIPPED 0x1 +#define SML_MESSAGE_END 0x0 + +#define SML_TYPE_OCTET_STRING 0 +#define SML_TYPE_LIST 112 +#define SML_TYPE_BOOLEAN 64 +#define SML_TYPE_INTEGER 80 +#define SML_TYPE_UNSIGNED 96 + +#define SML_TYPE_NUMBER_8 sizeof(u8) +#define SML_TYPE_NUMBER_16 sizeof(u16) +#define SML_TYPE_NUMBER_32 sizeof(u32) +#define SML_TYPE_NUMBER_64 sizeof(u64) + + +// This sml_buffer is used in two different use-cases. +// +// Parsing: the raw data is in the buffer field, +// the buffer_len is the number of raw bytes received, +// the cursor points to the current position during parsing +// +// Writing: At the beginning the buffer field is malloced and zeroed with +// a default length, this default length is stored in buffer_len +// (i.e. the maximum bytes one can write to this buffer) +// cursor points to the position, where on can write during the +// writing process. If a file is completely written to the buffer, +// cursor is the number of bytes written to the buffer. +typedef struct { + unsigned char *buffer; + size_t buffer_len; + int cursor; + int error; + char *error_msg; +} sml_buffer; + +sml_buffer *sml_buffer_init(size_t length); + +void sml_buffer_free(sml_buffer *buf); + +// Returns the length of the following data structure. Sets the cursor position to +// the value field. +int mc_sml_get_length(sml_buffer *buf); + +void mc_sml_set_type_and_length(sml_buffer *buf, unsigned int type, unsigned int l); + +// Checks if a error is occured. +int mc_sml_buf_has_errors(sml_buffer *buf); + + +// Returns the type field of the current byte. +int mc_sml_buf_get_current_type(sml_buffer *buf); + +// Returns the current byte. +unsigned char mc_sml_buf_get_current_byte(sml_buffer *buf); + + +// Returns a pointer to the current buffer position. +unsigned char *mc_sml_buf_get_current_buf(sml_buffer *buf); + +void mc_sml_optional_write(sml_buffer *buf); + +// Sets the number of bytes read (moves the cursor forward) +void mc_sml_buf_update_read_bytes(sml_buffer *buf, int bytes); + +// Checks if the next field is a skipped optional field, updates the buffer accordingly +int mc_sml_is_optional_skipped(sml_buffer *buf); +#define SML_SKIP_OPTIONAL (mc_sml_is_optional_skipped(buf)) ? 0 : + +void hexdump(unsigned char *buffer, size_t buffer_len); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sml/include/sml/sml_status.h b/sml/include/sml/sml_status.h new file mode 100644 index 0000000..2d1af66 --- /dev/null +++ b/sml/include/sml/sml_status.h @@ -0,0 +1,26 @@ +#ifndef _SML_STATUS_H +#define _SML_STATUS_H + +#include "sml_number.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef union { + u8 status8; + u16 status16; + u32 status32; + u64 status64; +} sml_status; + +sml_status *sml_status_parse(sml_buffer *buf); + +void sml_status_free(sml_status *status); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sml/include/sml/sml_time.h b/sml/include/sml/sml_time.h new file mode 100644 index 0000000..01553be --- /dev/null +++ b/sml/include/sml/sml_time.h @@ -0,0 +1,25 @@ + +#ifndef _SML_TIME_H +#define _SML_TIME_H + +#include "sml_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + u8 tag; + u32 data; +} sml_time; + +// Parses a time, updates the buffer accordingly, memory must be free'd elsewhere. +sml_time *sml_time_parse(sml_buffer *buf); +void sml_time_write(sml_time *time, sml_buffer *buf); +void sml_time_free(sml_time *time); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sml/include/sml/sml_transport.h b/sml/include/sml/sml_transport.h new file mode 100644 index 0000000..d5adbea --- /dev/null +++ b/sml/include/sml/sml_transport.h @@ -0,0 +1,19 @@ +#ifndef _SML_TRANSPORT_H +#define _SML_TRANSPORT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +//void (*mc_sml_transport_receiver_fun)(unsigned char *buffer, size_t buffer_len) = 0; + +void mc_sml_transport_listen(int fd, void (*mc_sml_transport_receiver)(unsigned char *buffer, size_t buffer_len)); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sml/include/sml/sml_tree.h b/sml/include/sml/sml_tree.h new file mode 100644 index 0000000..80eba69 --- /dev/null +++ b/sml/include/sml/sml_tree.h @@ -0,0 +1,64 @@ +#ifndef _SML_TREE_H +#define _SML_TREE_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_value.h" +#include "sml_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SML_PROC_PAR_VALUE_TAG_VALUE 0x01 +#define SML_PROC_PAR_VALUE_TAG_PERIOD_ENTRY 0x02 +#define SML_PROC_PAR_VALUE_TAG_TUPEL_ENTRY 0x03 +#define SML_PROC_PAR_VALUE_TAG_TIME 0x04 + + +// TODO +typedef struct { + u8 tag; + union { + sml_value *value; + // sml_period_entry + // sml_tupel_entry + sml_time *time; + } data; +} sml_proc_par_value; + +typedef struct { + octet_string **path_entries; + int path_entries_len; +} sml_tree_path; + +typedef struct s_tree{ + octet_string *parameter_name; + sml_proc_par_value *parameter_value; // optional + struct s_tree **child_list; // optional + int child_list_len; +} sml_tree; + +// SML_TREE_PATH +sml_tree_path *sml_tree_path_init(); +void sml_tree_path_add_path_entry(sml_tree_path *tree_path, octet_string *entry); +void sml_tree_path_write(sml_tree_path *tree_path, sml_buffer *buf); +void sml_tree_path_free(sml_tree_path *tree_path); + +// SML_TREE +sml_tree *sml_tree_init(octet_string *parameter_name); +void sml_tree_write(sml_tree *tree, sml_buffer *buf); +sml_tree *sml_tree_parse(sml_buffer *buf); +void sml_tree_free(sml_tree *tree); + +// SML_PROC_PAR_VALUE +sml_proc_par_value *sml_proc_par_value_init(u8 tag, void *data); +void sml_proc_par_value_write(sml_proc_par_value *value, sml_buffer *buf); +void sml_proc_par_value_free(sml_proc_par_value *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sml/include/sml/sml_value.h b/sml/include/sml/sml_value.h new file mode 100644 index 0000000..15fc7b5 --- /dev/null +++ b/sml/include/sml/sml_value.h @@ -0,0 +1,39 @@ +#ifndef _SML_VALUE_H +#define _SML_VALUE_H + +#include "sml_shared.h" +#include "sml_octet_string.h" +#include "sml_number.h" +#include "sml_boolean.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + u8 type; + union { + sml_boolean boolean; + octet_string *bytes; // can has zero length + i8 int8; + i16 int16; + i32 int32; + i64 int64; + u8 uint8; + u16 uint16; + u32 uint32; + u64 uint64; + } data; +} sml_value; + +sml_value *sml_value_parse(sml_buffer *buf); +void sml_value_write(sml_value *value, sml_buffer *buf); +sml_value *sml_value_init(); +void sml_value_free(sml_value *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sml/src/sml.c b/sml/src/sml.c new file mode 100644 index 0000000..4e50aca --- /dev/null +++ b/sml/src/sml.c @@ -0,0 +1,133 @@ + +#include +#include +#include +#include +#include + +#include +#include + +// EDL meter must provide at least 250 bytes as a receive buffer +#define SML_FILE_BUFFER_LENGTH 512 + +/* +void mc_sml_hexdump_rest(sml_buffer *buf) { + int i; + unsigned char *rest = mc_sml_buf_get_current_buf(buf); + for (i = 0; i < buf->buffer_len - buf->cursor; i++) { + printf("%02X ", (unsigned char) rest[i]); + if ((i + 1) % 8 == 0) { + printf("\n"); + } + } + printf("\n"); +} +*/ + +void mc_sml_hexdump(unsigned char *buffer, size_t buffer_len) { + printf("SML dump (%zu bytes)\n", buffer_len); + hexdump(buffer, buffer_len); +} + +sml_file *sml_file_parse(unsigned char *buffer, size_t buffer_len) { + + //buffer += 8; + //buffer_len -= 16; + sml_file *file = (sml_file*) malloc(sizeof(sml_file)); + memset(file, 0, sizeof(sml_file)); + + sml_buffer *buf = sml_buffer_init(buffer_len); + memcpy(buf->buffer, buffer, buffer_len); + file->buf = buf; + + sml_message *msg; + + // parsing all messages + for (; buf->cursor < buf->buffer_len;) { + + if(mc_sml_buf_get_current_byte(buf) == SML_MESSAGE_END) { + // reading trailing zeroed bytes + mc_sml_buf_update_read_bytes(buf, 1); + continue; + } + + msg = sml_message_parse(buf); + + if (mc_sml_buf_has_errors(buf)) { + printf("warning: could not read the whole file\n"); + break; + } + + sml_file_add_message(file, msg); + + } + return file; +} + +sml_file *sml_file_init() { + sml_file *file = (sml_file*) malloc(sizeof(sml_file)); + memset(file, 0, sizeof(sml_file)); + + sml_buffer *buf = sml_buffer_init(SML_FILE_BUFFER_LENGTH); + file->buf = buf; + return file; +} + +void sml_file_add_message(sml_file *file, sml_message *message) { + file->messages_len++; + file->messages = (sml_message **) realloc(file->messages, sizeof(sml_message *) * file->messages_len); + file->messages[file->messages_len - 1] = message; +} + +void sml_file_write(sml_file *file) { + + int i; + if (file->messages && file->messages_len > 0) { + for (i = 0; i < file->messages_len; i++) { + sml_message_write(file->messages[i], file->buf); + } + } +} + +void sml_file_free(sml_file *file) { + if (file) { + + if (file->messages) { + int i; + for (i = 0; i < file->messages_len; i++) { + sml_message_free(file->messages[i]); + } + free(file->messages); + } + + if (file->buf) { + sml_buffer_free(file->buf); + } + + free(file); + } +} + +void sml_file_print(sml_file *file) { + int i; + printf("SML file (%d SML messages, %d bytes)\n", file->messages_len, file->buf->cursor); + for (i = 0; i < file->messages_len; i++) { + printf("SML message %4.X\n", file->messages[i]->message_body->tag); + } +} + + + + + + + + + + + + + + + diff --git a/sml/src/sml_attention_response.c b/sml/src/sml_attention_response.c new file mode 100644 index 0000000..23d0b42 --- /dev/null +++ b/sml/src/sml_attention_response.c @@ -0,0 +1,47 @@ + +#include +#include + +sml_attention_response *sml_attention_response_parse(sml_buffer *buf){ + sml_attention_response *msg = (sml_attention_response *) malloc(sizeof(sml_attention_response)); + memset(msg, 0, sizeof(sml_attention_response)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 4) { + buf->error = 1; + goto error; + } + + msg->server_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->attention_number = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->attention_message = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->attention_details = SML_SKIP_OPTIONAL sml_tree_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; + + error: + free(msg); + return 0; + +} + +void sml_attention_response_free(sml_attention_response *msg){ + if (msg) { + sml_octet_string_free(msg->server_id); + sml_octet_string_free(msg->attention_number); + sml_octet_string_free(msg->attention_message); + sml_tree_free(msg->attention_details); + free(msg); + } +} diff --git a/sml/src/sml_boolean.c b/sml/src/sml_boolean.c new file mode 100644 index 0000000..451cb24 --- /dev/null +++ b/sml/src/sml_boolean.c @@ -0,0 +1,22 @@ + +#include +#include + +sml_boolean sml_boolean_parse(sml_buffer *buf) { + printf("NYI: %s\n", __FUNCTION__); + return 0; +} + +void sml_boolean_write(sml_boolean boolean, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_BOOLEAN, 1); + if (boolean == SML_BOOLEAN_FALSE) { + buf->buffer[buf->cursor] = SML_BOOLEAN_FALSE; + } + else { + buf->buffer[buf->cursor] = SML_BOOLEAN_TRUE; + } + buf->cursor++; +} + + + diff --git a/sml/src/sml_close_request.c b/sml/src/sml_close_request.c new file mode 100644 index 0000000..f31b666 --- /dev/null +++ b/sml/src/sml_close_request.c @@ -0,0 +1,52 @@ + +#include + +#include + +sml_close_request *sml_close_request_init() { + sml_close_request *close_request = (sml_close_request *) malloc(sizeof(sml_close_request)); + memset(close_request, 0, sizeof(sml_close_request)); + return close_request; +} + +void sml_close_request_write(sml_close_request *msg, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 1); + + if (msg->global_signature != NULL){ + sml_octet_string_write(msg->global_signature,buf); + } else mc_sml_optional_write(buf); +} + +sml_close_request * sml_close_request_parse(sml_buffer *buf) { + sml_close_request *msg = (sml_close_request *) malloc(sizeof(sml_close_request)); + memset(msg, 0, sizeof(sml_close_request)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 1) { + buf->error = 1; + goto error; + } + + msg->global_signature = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; + +error: + free(msg); + return 0; +} + +void sml_close_request_free(sml_close_request *msg) { + if (msg) { + sml_octet_string_free(msg->global_signature); + free(msg); + + } +} + + diff --git a/sml/src/sml_close_response.c b/sml/src/sml_close_response.c new file mode 100644 index 0000000..609bced --- /dev/null +++ b/sml/src/sml_close_response.c @@ -0,0 +1,36 @@ + +#include +#include + +sml_close_response *sml_close_response_parse(sml_buffer *buf) { + + sml_close_response *msg = (sml_close_response *) malloc(sizeof(sml_close_response)); + memset(msg, 0, sizeof(sml_close_response)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 1) { + buf->error = 1; + goto error; + } + + msg->global_signature = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; + +error: + free(msg); + return 0; + +} + +void sml_close_response_free(sml_close_response *msg) { + if (msg) { + sml_octet_string_free(msg->global_signature); + free(msg); + } +} diff --git a/sml/src/sml_crc16.c b/sml/src/sml_crc16.c new file mode 100644 index 0000000..f4c43a7 --- /dev/null +++ b/sml/src/sml_crc16.c @@ -0,0 +1,39 @@ + +#include + +#define PPPINITFCS16 0xffff // initial FCS value + +// table taken from DIN EN 62056-46 +static u16 fcstab [256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, + 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, + 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, + 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, + 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, + 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, + 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, + 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, + 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, + 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, + 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, + 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, + 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, + 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, + 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, + 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, + 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, + 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +u16 sml_crc16_calculate(unsigned char *cp, int len) { + u16 fcs = PPPINITFCS16; + while (len--) { + fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff]; + } + fcs ^= 0xffff; + fcs = ((fcs & 0xff) << 8) | ((fcs & 0xff00) >> 8); + return fcs; +} + + diff --git a/sml/src/sml_get_list_request.c b/sml/src/sml_get_list_request.c new file mode 100644 index 0000000..5f29442 --- /dev/null +++ b/sml/src/sml_get_list_request.c @@ -0,0 +1,88 @@ + +#include +#include + +sml_get_list_request* sml_get_list_request_init(){ + sml_get_list_request *msg = (sml_get_list_request *) malloc(sizeof(sml_get_list_request)); + memset(msg, 0, sizeof(sml_get_list_request)); + + return msg; +} + +void sml_get_list_request_write(sml_get_list_request *msg, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 5); + + sml_octet_string_write(msg->client_id, buf); + + // optional server_id + if (msg->server_id != NULL){ + sml_octet_string_write(msg->server_id, buf); + } else mc_sml_optional_write(buf); + + // optional username + if (msg->username != NULL){ + sml_octet_string_write(msg->username, buf); + } else mc_sml_optional_write(buf); + + // optional password + if (msg->password != NULL){ + sml_octet_string_write(msg->password, buf); + } else mc_sml_optional_write(buf); + + // optional list_name + if (msg->list_name != NULL){ + sml_octet_string_write(msg->list_name,buf); + } else mc_sml_optional_write(buf); + +} + + +sml_get_list_request *sml_get_list_request_parse(sml_buffer *buf) { + + sml_get_list_request *msg = (sml_get_list_request *) malloc(sizeof(sml_get_list_request)); + memset(msg, 0, sizeof(sml_get_list_request)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 5) { + buf->error = 1; + goto error; + } + + msg->client_id = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->server_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->username = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->password = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->list_name = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; + +error: + free(msg); + return 0; + +} + + +void sml_get_list_request_free(sml_get_list_request *msg) { + if (msg) { + sml_octet_string_free(msg->client_id); + sml_octet_string_free(msg->server_id); + sml_octet_string_free(msg->list_name); + sml_octet_string_free(msg->username); + sml_octet_string_free(msg->password); + free(msg); + } +} diff --git a/sml/src/sml_get_list_response.c b/sml/src/sml_get_list_response.c new file mode 100644 index 0000000..71f4b30 --- /dev/null +++ b/sml/src/sml_get_list_response.c @@ -0,0 +1,61 @@ + +#include + + +sml_get_list_response *sml_get_list_response_parse(sml_buffer *buf) { + + + sml_get_list_response *msg = (sml_get_list_response *) malloc(sizeof(sml_get_list_response)); + memset(msg, 0, sizeof(sml_get_list_response)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 7) { + buf->error = 1; + goto error; + } + + msg->client_id = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->server_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->list_name = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->act_sensor_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->val_list = sml_list_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->list_signature = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->act_gateway_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; + +error: + free(msg); + return 0; + +} + +void sml_get_list_response_free(sml_get_list_response *msg) { + if (msg) { + sml_octet_string_free(msg->client_id); + sml_octet_string_free(msg->server_id); + sml_octet_string_free(msg->list_name); + sml_time_free(msg->act_sensor_time); + sml_list_free(msg->val_list); + sml_octet_string_free(msg->list_signature); + sml_time_free(msg->act_gateway_time); + free(msg); + } +} diff --git a/sml/src/sml_get_proc_parameter_request.c b/sml/src/sml_get_proc_parameter_request.c new file mode 100644 index 0000000..50b5ddc --- /dev/null +++ b/sml/src/sml_get_proc_parameter_request.c @@ -0,0 +1,45 @@ + + +#include +#include +#include + +sml_get_proc_parameter_request *sml_get_proc_parameter_request_init() { + sml_get_proc_parameter_request *msg = (sml_get_proc_parameter_request *) malloc(sizeof (sml_get_proc_parameter_request)); + memset(msg, 0, sizeof(sml_get_proc_parameter_request)); + return msg; +} + +void sml_get_proc_parameter_request_write(sml_get_proc_parameter_request *msg, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 5); + + // optional server_id + if (msg->server_id != NULL){ + sml_octet_string_write(msg->server_id, buf); + } else mc_sml_optional_write(buf); + + // optional username + if (msg->username != NULL) { + sml_octet_string_write(msg->username, buf); + } else mc_sml_optional_write(buf); + + // optional password + if (msg->password != NULL){ + sml_octet_string_write(msg->password, buf); + } else mc_sml_optional_write(buf); + + sml_tree_path_write(msg->parameter_tree_path, buf); + + sml_tree_write(msg->parameter_tree, buf); +} + +void sml_get_proc_parameter_request_free(sml_get_proc_parameter_request *msg) { + if (msg){ + sml_octet_string_free(msg->server_id); + sml_octet_string_free(msg->username); + sml_octet_string_free(msg->password); + sml_tree_path_free(msg->parameter_tree_path); + sml_tree_free(msg->parameter_tree); + free(msg); + } +} diff --git a/sml/src/sml_get_profile_pack_request.c b/sml/src/sml_get_profile_pack_request.c new file mode 100644 index 0000000..939319e --- /dev/null +++ b/sml/src/sml_get_profile_pack_request.c @@ -0,0 +1,106 @@ + +#include +#include +#include +#include +#include + + + +sml_get_profile_pack_request *sml_get_profile_pack_request_init(){ + sml_get_profile_pack_request *msg = (sml_get_profile_pack_request *) malloc(sizeof(sml_get_profile_pack_request)); + memset(msg, 0, sizeof(sml_get_profile_pack_request)); + msg->parameter_tree_path = sml_tree_path_init(); + return msg; +} + +void sml_get_profile_pack_request_write(sml_get_profile_pack_request *msg, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 9); + + // server_id + if (msg->server_id != NULL) { + sml_octet_string_write(msg->server_id,buf); + } else mc_sml_optional_write(buf); + + // username + if (msg->username != NULL) { + sml_octet_string_write(msg->username,buf); + } else mc_sml_optional_write(buf); + + // password + if (msg->password != NULL) { + sml_octet_string_write(msg->password,buf); + } else mc_sml_optional_write(buf); + + // with_rawdata + if (msg->with_rawdata != NULL) { + printf("TODO: %s - comparision is not valid", __FUNCTION__); + sml_boolean_write(msg->with_rawdata,buf); + } else mc_sml_optional_write(buf); // with_rawdata + + // begin_time + if (msg->begin_time != NULL){ + sml_time_write(msg->begin_time, buf); + } else mc_sml_optional_write(buf); // begin_time + mc_sml_optional_write(buf); // end_time + + // parameter_tree_path is not optional + sml_tree_path_write(msg->parameter_tree_path, buf); + + mc_sml_optional_write(buf); // object_list + mc_sml_optional_write(buf); // das_details + printf("request_write"); +} + + +sml_get_profile_pack_request *sml_get_profile_pack_request_parse(sml_buffer *buf) { + + sml_get_profile_pack_request *msg = (sml_get_profile_pack_request *) malloc(sizeof(sml_get_profile_pack_request)); + memset(msg, 0, sizeof(sml_get_profile_pack_request)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 9) { + buf->error = 1; + goto error; + } + + printf("TODO:sml_get_profile_pack_request_parse -> not implemented yet"); + +/* msg->client_id = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->server_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->list_name = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + */ + /*msg->act_sensor_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->val_list = sml_list_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->list_signature = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->act_gateway_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + */ + return msg; + + error: + free(msg); + return 0; + +} + +void sml_get_profile_pack_request_free(sml_get_profile_pack_request *msg){ + printf("NYI: %s\n", __FUNCTION__); +} + + diff --git a/sml/src/sml_get_profile_pack_response.c b/sml/src/sml_get_profile_pack_response.c new file mode 100644 index 0000000..1b1e7b2 --- /dev/null +++ b/sml/src/sml_get_profile_pack_response.c @@ -0,0 +1,18 @@ + +#include +#include +#include +#include +#include +#include +#include + + +sml_get_profile_pack_response *sml_get_profile_pack_response_parse(sml_buffer *buf){ + printf("NYI: %s\n", __FUNCTION__); + return 0; +} + +void sml_get_profile_pack_response_free(sml_get_profile_pack_response *msg){ + printf("NYI: %s\n", __FUNCTION__); +} diff --git a/sml/src/sml_list.c b/sml/src/sml_list.c new file mode 100644 index 0000000..4242a72 --- /dev/null +++ b/sml/src/sml_list.c @@ -0,0 +1,114 @@ + +#include +#include +#include +#include +#include +#include +#include + + + + +sml_list *sml_list_init(){ + sml_list *s = (sml_list *)malloc(sizeof(sml_list)); + memset(s, 0, sizeof(sml_list)); + + return s; +} + +sml_list *sml_list_parse(sml_buffer *buf) { + int elems, i; + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + return 0; + } + + elems = mc_sml_get_length(buf); + sml_list *start = 0; + sml_list *cur = 0; + sml_list *tmp; + + for (i = 0; i < elems; i++) { + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 7) { + buf->error = 1; + goto error; + } + + tmp = (sml_list *) malloc(sizeof(sml_list)); + if (i == 0) { + start = tmp; + cur = tmp; + } + else { + cur->next = tmp; + cur = tmp; + } + + cur->obj_name = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->status = SML_SKIP_OPTIONAL sml_status_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->val_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->unit = SML_SKIP_OPTIONAL mc_sml_parse_u8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->scaler = SML_SKIP_OPTIONAL mc_sml_parse_i8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->value = SML_SKIP_OPTIONAL sml_value_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->value_signature = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + cur->next = 0; + } + return start; + +error: + buf->error = 1; + return 0; +} + +void sml_list_write(sml_list *list, sml_buffer *buf){ + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 1); + mc_sml_optional_write(buf); + // +} + +void sml_list_entry_free(sml_list *list) { + if (list) { + sml_octet_string_free(list->obj_name); + sml_status_free(list->status); + sml_time_free(list->val_time); + sml_value_free(list->value); + sml_octet_string_free(list->value_signature); + free(list); + } +} + +void sml_list_free(sml_list *list) { + if (list) { + sml_list *f = list; + sml_list *n = list->next; + + while(f) { + sml_list_entry_free(f); + f = n; + if (f) { + n = f->next; + } + } + } +} diff --git a/sml/src/sml_message.c b/sml/src/sml_message.c new file mode 100644 index 0000000..f487f9e --- /dev/null +++ b/sml/src/sml_message.c @@ -0,0 +1,221 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SML_MESSAGE_TRANSACTION_MAGIC_NUMBER 0x6F4D654E + +// SML MESSAGE + +sml_message *sml_message_parse(sml_buffer *buf) { + sml_message *msg = (sml_message *) malloc(sizeof(sml_message)); + memset(msg, 0, sizeof(sml_message)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 6) { + buf->error = 1; + goto error; + } + + msg->transaction_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->group_id = mc_sml_parse_u8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->abort_on_error = mc_sml_parse_u8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->message_body = sml_message_body_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->crc = mc_sml_parse_u16(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + if (mc_sml_buf_get_current_byte(buf) == SML_MESSAGE_END) { + mc_sml_buf_update_read_bytes(buf, 1); + } + return msg; + +error: + // TODO: free encapsulated stuff + free(msg); + return 0; +} + +sml_message *sml_message_init() { + sml_message *msg = (sml_message *) malloc(sizeof(sml_message)); + memset(msg, 0, sizeof(sml_message)); + + int id = ((unsigned int) getpid()) | SML_MESSAGE_TRANSACTION_MAGIC_NUMBER; + msg->transaction_id = sml_octet_string_init((unsigned char *)&id, sizeof(int)); + + return msg; +} +void sml_message_free(sml_message *msg) { + if (msg) { + if (msg->transaction_id) + sml_octet_string_free(msg->transaction_id); + if (msg->message_body) + sml_message_body_free(msg->message_body); + free(msg); + } +} + +void sml_message_write(sml_message *msg, sml_buffer *buf) { + int msg_start = buf->cursor; + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 6); + sml_octet_string_write(msg->transaction_id, buf); + sml_number_write(SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_8, (u64) msg->group_id, buf); + sml_number_write(SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_8, (u64) msg->abort_on_error, buf); + sml_message_body_write(msg->message_body, buf); + + msg->crc = sml_crc16_calculate(&(buf->buffer[msg_start]), buf->cursor - msg_start); + + sml_number_write(SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_16, (u64) msg->crc, buf); + + // end of message + buf->buffer[buf->cursor] = 0x0; + buf->cursor++; +} + +// SML MESSAGE BODY + +sml_message_body *sml_message_body_parse(sml_buffer *buf) { + sml_message_body *msg_body = (sml_message_body *) malloc(sizeof(sml_message_body)); + memset(msg_body, 0, sizeof(sml_message_body)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 2) { + buf->error = 1; + goto error; + } + + msg_body->tag = mc_sml_parse_u16(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + switch (msg_body->tag) { + case SML_MESSAGE_OPEN_REQUEST: + msg_body->data = sml_open_request_parse(buf); + break; + case SML_MESSAGE_OPEN_RESPONSE: + msg_body->data = sml_open_response_parse(buf); + break; + case SML_MESSAGE_CLOSE_REQUEST: + msg_body->data = sml_close_request_parse(buf); + break; + case SML_MESSAGE_CLOSE_RESPONSE: + msg_body->data = sml_close_response_parse(buf); + break; + case SML_MESSAGE_GET_LIST_RESPONSE: + msg_body->data = sml_get_list_response_parse(buf); + break; + case SML_MESSAGE_GET_LIST_REQUEST: + msg_body->data = sml_get_list_request_parse(buf); + break; + case SML_MESSAGE_ATTENTION_RESPONSE: + msg_body->data = sml_attention_response_parse(buf); + break; + default: + printf("error: message type %04X not yet implemented\n", msg_body->tag); + break; + } + + return msg_body; + +error: + free(msg_body); + return 0; +} + +sml_message_body *sml_message_body_init(u16 tag, void *data) { + sml_message_body *message_body = (sml_message_body *) malloc(sizeof(sml_message_body)); + memset(message_body, 0, sizeof(sml_message_body)); + message_body->tag = tag; + message_body->data = data; + return message_body; +} + +void sml_message_body_write(sml_message_body *message_body, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 2); + sml_number_write(SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_16, (u64) message_body->tag, buf); + + switch (message_body->tag) { + case SML_MESSAGE_OPEN_REQUEST: + sml_open_request_write((sml_open_request *) message_body->data, buf); + break; + case SML_MESSAGE_CLOSE_REQUEST: + sml_close_request_write((sml_close_request *) message_body->data, buf); + break; + case SML_MESSAGE_SET_PROC_PARAMETER_REQUEST: + sml_set_proc_parameter_request_write((sml_set_proc_parameter_request *) message_body->data, buf); + break; + case SML_MESSAGE_GET_PROC_PARAMETER_REQUEST: + sml_get_proc_parameter_request_write((sml_get_proc_parameter_request *) message_body->data, buf); + break; + case SML_MESSAGE_GET_LIST_REQUEST: + sml_get_list_request_write((sml_get_list_request *)message_body->data, buf); + break; + case SML_MESSAGE_GET_PROFILE_PACK_REQUEST: + sml_get_profile_pack_request_write((sml_get_profile_pack_request *)message_body->data, buf); + break; + default: + printf("error: message type %04X not yet implemented\n", message_body->tag); + break; + } +} + +void sml_message_body_free(sml_message_body *message_body) { + if (message_body) { + switch (message_body->tag) { + case SML_MESSAGE_OPEN_REQUEST: + sml_open_request_free((sml_open_request *) message_body->data); + break; + case SML_MESSAGE_OPEN_RESPONSE: + sml_open_response_free((sml_open_response *) message_body->data); + break; + case SML_MESSAGE_CLOSE_REQUEST: + sml_close_request_free((sml_close_request *) message_body->data); + break; + case SML_MESSAGE_CLOSE_RESPONSE: + sml_close_response_free((sml_close_response *) message_body->data); + break; + case SML_MESSAGE_SET_PROC_PARAMETER_REQUEST: + sml_set_proc_parameter_request_free((sml_set_proc_parameter_request *) message_body->data); + break; + case SML_MESSAGE_GET_LIST_REQUEST: + sml_get_list_request_free((sml_get_list_request *) message_body->data); + break; + case SML_MESSAGE_GET_LIST_RESPONSE: + sml_get_list_response_free((sml_get_list_response *) message_body->data); + break; + default: + printf("NYI: %s for message type %04X\n", __FUNCTION__, message_body->tag); + break; + } + + free(message_body); + } +} + diff --git a/sml/src/sml_number.c b/sml/src/sml_number.c new file mode 100644 index 0000000..38205fc --- /dev/null +++ b/sml/src/sml_number.c @@ -0,0 +1,43 @@ + +#include +#include +#include + +u64 mc_sml_parse_number(sml_buffer *buf, unsigned char type, int max_size) { + + int l, i; + u64 n = 0; + if (mc_sml_buf_get_current_type(buf) != type) { + buf->error = 1; + return 0; + } + + l = mc_sml_get_length(buf); + if (l < 0 || l > max_size) { + buf->error = 1; + return 0; + } + + // TODO: this doesn't work for integers (leading 1's) + // mathias runge: -> fixed bug in sml_value_parse for SML_TYPE_INTEGER -> see comment in sml_value.cpp + // maybe this one is fixed too? + for (i = 0; i < l; i++) { + n <<= 8; + n |= mc_sml_buf_get_current_byte(buf); + mc_sml_buf_update_read_bytes(buf, 1); + } + return n; +} + +void sml_number_write(unsigned char type, int size, u64 value, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, type, size); + int i; + u64 mask = 0xFF; + mask <<= (8 * (size - 1)); + + for (i = 0; i < size; i++) { + buf->buffer[buf->cursor + i] = (unsigned char) ((mask & value) >> (8 * (size - i - 1))); + mask >>= 8; + } + buf->cursor += size; +} diff --git a/sml/src/sml_octet_string.c b/sml/src/sml_octet_string.c new file mode 100644 index 0000000..203507e --- /dev/null +++ b/sml/src/sml_octet_string.c @@ -0,0 +1,113 @@ + +#include + +#include + +#ifdef SML_WITH_UUID_LIB +#include +#endif + +octet_string *sml_octet_string_init(unsigned char *str, int length) { + octet_string *s = (octet_string *)malloc(sizeof(octet_string)); + memset(s, 0, sizeof(octet_string)); + if (length > 0) { + s->str = (unsigned char *)malloc(length); + memcpy(s->str, str, length); + s->len = length; + } + return s; +} + +uint8_t ctoi(uint8_t c){ + uint8_t ret = 0; + + if((c >= '0') && (c <= '9')){ + ret = c - '0'; + } else if((c >= 'a') && (c <= 'f')){ + ret = c - 'a' + 10; + } else if((c >= 'A') && (c <= 'F')){ + ret = c - 'A' + 10; + } + + return ret; +} + + +inline uint8_t c2toi(uint8_t c1, uint8_t c2){ + return ctoi(c1) << 4 | ctoi(c2); +} + +inline uint8_t c2ptoi(char* c){ + return ctoi((uint8_t)c[0]) << 4 | ctoi((uint8_t)c[1]); +} + +octet_string *sml_octet_string_init_from_hex(char *str) { + int i, len = strlen(str); + if (len % 2 != 0) { + return 0; + } + unsigned char bytes[len / 2]; + for (i = 0; i < (len / 2); i++) { + bytes[i] = c2ptoi(&(str[i * 2])); + } + return sml_octet_string_init(bytes, len / 2); +} + +void sml_octet_string_free(octet_string *str) { + if (str) { + if (str->str) { + free(str->str); + } + free(str); + } +} + +octet_string *sml_octet_string_parse(sml_buffer *buf) { + int l; + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_OCTET_STRING) { + buf->error = 1; + return 0; + } + + l = mc_sml_get_length(buf); + if (l < 0) { + buf->error = 1; + return 0; + } + + octet_string *str = sml_octet_string_init(mc_sml_buf_get_current_buf(buf), l); + mc_sml_buf_update_read_bytes(buf, l); + return str; +} + +void sml_octet_string_write(octet_string *str, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_OCTET_STRING, (unsigned int) str->len); + memcpy(mc_sml_buf_get_current_buf(buf), str->str, str->len); + buf->cursor += str->len; +} + +octet_string *sml_octet_string_generate_uuid() { +#ifdef SML_WITH_UUID_LIB + uuid_t uuid; + uuid_generate(uuid); + return sml_octet_string_init(uuid, 16); +#else + printf("TODO %s\n", __FUNCTION__); + return sml_octet_string_init((unsigned char*)"RANDOM", 6); +#endif +} + +int sml_octet_string_cmp_with_hex(octet_string *str, char *hex) { + octet_string *hstr = sml_octet_string_init_from_hex(hex); + if (str->len != hstr->len) { + sml_octet_string_free(hstr); + return -1; + } + int result = memcmp(str->str, hstr->str, str->len); + sml_octet_string_free(hstr); + return result; +} + + + + diff --git a/sml/src/sml_open_request.c b/sml/src/sml_open_request.c new file mode 100644 index 0000000..09a0e73 --- /dev/null +++ b/sml/src/sml_open_request.c @@ -0,0 +1,105 @@ + +#include + +#include +#include + + +sml_open_request *sml_open_request_init(){ + sml_open_request *open_request = (sml_open_request *) malloc(sizeof(sml_open_request)); + memset(open_request, 0, sizeof(sml_open_request)); + return open_request; +} + +/* +sml_open_request *sml_open_request_init(char* client_id,char* req_file_id, char* server_id){ + sml_open_request *open_request = (sml_open_request *) malloc(sizeof(sml_open_request)); + memset(open_request, 0, sizeof(sml_open_request)); + + // printf("TODO: %s\n", __FUNCTION__); + open_request->client_id = sml_octet_string_init((unsigned char *)client_id,strlen(client_id)); + open_request->req_file_id = sml_octet_string_init((unsigned char *)req_file_id,strlen(req_file_id)); + open_request->server_id = sml_octet_string_init((unsigned char *)server_id, strlen(server_id)); + return open_request; +} + +sml_open_request *sml_open_request_init() { + // sml_open_request *open_request = (sml_open_request *) malloc(sizeof(sml_open_request)); + //memset(open_request, 0, sizeof(sml_open_request)); + + // printf("TODO: %s\n", __FUNCTION__); + //open_request->username = sml_octet_string_init((unsigned char *)"kunde",5); + //open_request->username = sml_octet_string_init((unsigned char *)"kunde",5); + //open_request->client_id = sml_octet_string_init((unsigned char *)"SEDICMA", 7); + //open_request->req_file_id = sml_octet_string_init((unsigned char *)"01", 2); + char server_id[] ={0x06, 0x45, 0x4d, 0x48, 0x01, 0x02, 0x71, 0x53, 0x3b, 0xcd}; + //open_request->server_id = sml_octet_string_init(server_id, 10); + return sml_open_request_init("SEDICMA", "02", server_id); +} +*/ +void sml_open_request_write(sml_open_request *msg, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 7); + + mc_sml_optional_write(buf); + sml_octet_string_write(msg->client_id, buf); + sml_octet_string_write(msg->req_file_id, buf); + sml_octet_string_write(msg->server_id, buf); + sml_octet_string_write(msg->username,buf); + sml_octet_string_write(msg->password,buf); + mc_sml_optional_write(buf); + +} + +sml_open_request *sml_open_request_parse(sml_buffer *buf) { + sml_open_request *msg = (sml_open_request *) malloc(sizeof(sml_open_request)); + memset(msg, 0, sizeof(sml_open_request)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 7) { + buf->error = 1; + goto error; + } + + msg->codepage = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->client_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->req_file_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->server_id = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->username = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->password = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->sml_version = SML_SKIP_OPTIONAL mc_sml_parse_u8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; + +error: + free(msg); + return 0; +} + +void sml_open_request_free(sml_open_request *msg) { + free(msg->client_id); + free(msg->password); + free(msg->req_file_id); + free(msg->server_id); + free(msg->username); + free(msg); + // printf("NYI: %s\n", __FUNCTION__); +} + + diff --git a/sml/src/sml_open_response.c b/sml/src/sml_open_response.c new file mode 100644 index 0000000..668451f --- /dev/null +++ b/sml/src/sml_open_response.c @@ -0,0 +1,53 @@ + +#include + +#include + +sml_open_response *sml_open_response_parse(sml_buffer *buf) { + sml_open_response *msg = (sml_open_response *) malloc(sizeof(sml_open_response)); + memset(msg, 0, sizeof(sml_open_response)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 6) { + buf->error = 1; + goto error; + } + + msg->codepage = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->client_id = SML_SKIP_OPTIONAL sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->req_file_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->server_id = sml_octet_string_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->ref_time = SML_SKIP_OPTIONAL sml_time_parse(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + msg->sml_version = SML_SKIP_OPTIONAL mc_sml_parse_u8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return msg; +error: + free(msg); + return 0; +} + +void sml_open_response_free(sml_open_response *msg) { + if (msg) { + sml_octet_string_free(msg->codepage); + sml_octet_string_free(msg->client_id); + sml_octet_string_free(msg->req_file_id); + sml_octet_string_free(msg->server_id); + sml_time_free(msg->ref_time); + free(msg); + } +} diff --git a/sml/src/sml_set_proc_parameter_request.c b/sml/src/sml_set_proc_parameter_request.c new file mode 100644 index 0000000..b32b444 --- /dev/null +++ b/sml/src/sml_set_proc_parameter_request.c @@ -0,0 +1,26 @@ + +#include + +#include + +sml_set_proc_parameter_request *sml_set_proc_parameter_request_init() { + sml_set_proc_parameter_request *msg = (sml_set_proc_parameter_request *) malloc(sizeof (sml_set_proc_parameter_request)); + memset(msg, 0, sizeof(sml_set_proc_parameter_request)); + return msg; +} + +void sml_set_proc_parameter_request_write(sml_set_proc_parameter_request *msg, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 5); + mc_sml_optional_write(buf); + mc_sml_optional_write(buf); + mc_sml_optional_write(buf); + sml_tree_path_write(msg->parameter_tree_path, buf); + sml_tree_write(msg->parameter_tree, buf); +} + +void sml_set_proc_parameter_request_free(sml_set_proc_parameter_request *msg) { + printf("NYI: %s\n", __FUNCTION__); +} + + + diff --git a/sml/src/sml_shared.c b/sml/src/sml_shared.c new file mode 100644 index 0000000..0d203f1 --- /dev/null +++ b/sml/src/sml_shared.c @@ -0,0 +1,123 @@ + +#include +#include +#include + +int mc_sml_get_length(sml_buffer *buf) { + int length = 0; + unsigned char byte = mc_sml_buf_get_current_byte(buf); + int list = ((byte & SML_TYPE_FIELD) == SML_TYPE_LIST) ? 0 : -1; + + for (;buf->cursor < buf->buffer_len;) { + byte = mc_sml_buf_get_current_byte(buf); + length <<= 4; + length |= (byte & SML_LENGTH_FIELD); + + if ((byte & SML_ANOTHER_TL) != SML_ANOTHER_TL) { + break; + } + mc_sml_buf_update_read_bytes(buf, 1); + if(list) { + list += -1; + } + } + mc_sml_buf_update_read_bytes(buf, 1); + return length + list; +} + +void mc_sml_set_type_and_length(sml_buffer *buf, unsigned int type, unsigned int l) { + // set the type + buf->buffer[buf->cursor] |= type; + + if (type != SML_TYPE_LIST) { + l++; + } + + if (l > SML_LENGTH_FIELD) { + // how much shifts are necessary + int mask_pos = (sizeof(unsigned int) * 2) - 1; + + // the 4 most significant bits of l + unsigned int mask = 0xF0 << (8 * (sizeof(unsigned int) - 1)); + + // select the 4 most significant bits with a bit set + while (!(mask & l)) { + mask >>= 4; + mask_pos--; + } + + // copy the bits to the buffer + while (mask > SML_LENGTH_FIELD) { + buf->buffer[buf->cursor] |= SML_ANOTHER_TL; + buf->buffer[buf->cursor] |= ((mask & l) >> (4 * mask_pos)); + mask >>= 4; + mask_pos--; + buf->cursor++; + } + } + buf->buffer[buf->cursor] |= (l & SML_LENGTH_FIELD); + buf->cursor++; +} + +int mc_sml_buf_has_errors(sml_buffer *buf) { + return buf->error != 0; +} + +int mc_sml_buf_get_current_type(sml_buffer *buf) { + return (buf->buffer[buf->cursor] & SML_TYPE_FIELD); +} + +unsigned char mc_sml_buf_get_current_byte(sml_buffer *buf) { + return buf->buffer[buf->cursor]; +} + +unsigned char *mc_sml_buf_get_current_buf(sml_buffer *buf) { + return &(buf->buffer[buf->cursor]); +} + +void mc_sml_buf_update_read_bytes(sml_buffer *buf, int bytes) { + buf->cursor += bytes; +} + +sml_buffer *sml_buffer_init(size_t length) { + sml_buffer *buf = (sml_buffer *) malloc(sizeof(sml_buffer)); + memset(buf, 0, sizeof(sml_buffer)); + buf->buffer = (unsigned char *) malloc(length); + buf->buffer_len = length; + memset(buf->buffer, 0, buf->buffer_len); + return buf; +} + +void mc_sml_optional_write(sml_buffer *buf) { + buf->buffer[buf->cursor] = SML_OPTIONAL_SKIPPED; + buf->cursor++; +} + +void sml_buffer_free(sml_buffer *buf) { + if (buf) { + if (buf->buffer) + free(buf->buffer); + if (buf->error_msg) + free(buf->error_msg); + free(buf); + } +} + +int mc_sml_is_optional_skipped(sml_buffer *buf) { + if (mc_sml_buf_get_current_byte(buf) == SML_OPTIONAL_SKIPPED) { + mc_sml_buf_update_read_bytes(buf, 1); + return 1; + } + return 0; +} + +void hexdump(unsigned char *buffer, size_t buffer_len) { + int i; + for (i = 0; i < buffer_len; i++) { + printf("%02X ", (unsigned char) buffer[i]); + if ((i + 1) % 8 == 0) { + printf("\n"); + } + } + printf("\n"); +} diff --git a/sml/src/sml_status.c b/sml/src/sml_status.c new file mode 100644 index 0000000..59ebb7e --- /dev/null +++ b/sml/src/sml_status.c @@ -0,0 +1,50 @@ + +#include +#include + +sml_status *sml_status_parse(sml_buffer *buf) { + int type = mc_sml_buf_get_current_type(buf); + unsigned char byte = mc_sml_buf_get_current_byte(buf); + + sml_status *state = (sml_status *) malloc(sizeof(sml_status)); + switch (type) { + case SML_TYPE_UNSIGNED: + switch (byte & SML_LENGTH_FIELD) { + case SML_TYPE_NUMBER_8: + state->status8 = mc_sml_parse_u8(buf); + break; + case SML_TYPE_NUMBER_16: + state->status16 = mc_sml_parse_u16(buf); + break; + case SML_TYPE_NUMBER_16 + 1: + case SML_TYPE_NUMBER_32: + state->status32 = mc_sml_parse_u32(buf); + break; + case SML_TYPE_NUMBER_32 + 1: + case SML_TYPE_NUMBER_32 + 2: + case SML_TYPE_NUMBER_32 + 3: + case SML_TYPE_NUMBER_64: + state->status64 = mc_sml_parse_u64(buf); + break; + default: + buf->error = 1; + break; + } + break; + default: + buf->error = 1; + break; + } + if (mc_sml_buf_has_errors(buf)) { + free(state); + return 0; + } + + return state; +} + +void sml_status_free(sml_status *status) { + if (status) { + free(status); + } +} diff --git a/sml/src/sml_time.c b/sml/src/sml_time.c new file mode 100644 index 0000000..2e28f68 --- /dev/null +++ b/sml/src/sml_time.c @@ -0,0 +1,42 @@ + +#include +#include +#include +#include + +sml_time *sml_time_parse(sml_buffer *buf) { + sml_time *tme = (sml_time *) malloc(sizeof(sml_time)); + + if (mc_sml_buf_get_current_type(buf) != SML_TYPE_LIST) { + buf->error = 1; + goto error; + } + + if (mc_sml_get_length(buf) != 2) { + buf->error = 1; + goto error; + } + + tme->tag = mc_sml_parse_u8(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + tme->data = mc_sml_parse_u32(buf); + if (mc_sml_buf_has_errors(buf)) goto error; + + return tme; + +error: + free(tme); + return 0; +} + +void sml_time_write(sml_time *time, sml_buffer *buf){ + printf("NYI: %s (writing optional flag instead)\n", __FUNCTION__); + mc_sml_optional_write(buf); +} + +void sml_time_free(sml_time *time) { + if (time) { + free(time); + } +} diff --git a/sml/src/sml_transport.c b/sml/src/sml_transport.c new file mode 100644 index 0000000..e855d4a --- /dev/null +++ b/sml/src/sml_transport.c @@ -0,0 +1,101 @@ + +#include + +#include +#include +#include +#include +#include + +#define MC_SML_BUFFER_LEN 8096 + +// Invokes on every incoming SML message the given method. The buffer is freed afterwards. +void mc_sml_transport_listen(int fd, void (*mc_sml_transport_receiver)(unsigned char *buffer, size_t buffer_len)) { + + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + unsigned char byte; + unsigned char buf[MC_SML_BUFFER_LEN]; + int esc = 0, start = 0, i, end = 0, r; + + for (i = 0; i < MC_SML_BUFFER_LEN;) { + select(fd + 1, &readfds, 0, 0, 0); + if (FD_ISSET(fd, &readfds)) { + + if (!i) { // read until escaped start sequence; + r = read(fd, &byte, 1); + if (r <= 0) continue; + + if (esc == 4) { + if (byte == 0x01) { + buf[esc + start++] = byte; + if (start == 4) { + i = esc + start; + esc = 0; + start = 0; + } + } + else { + // no start sequence + esc = 0; + } + } + else { + if (byte == 0x1b) { + buf[esc++] = byte; + } + else { + // no escape sequence + esc = 0; + } + } + } + else { // read the message + r = read(fd, (void *)(&(buf[i])), 1); + if (r <= 0) continue; + + if (esc == 4) { + if (end) { + end++; + if (end == 5) { + char *sml_file = (char *) malloc(i); + memcpy(sml_file, &(buf[0]), i); + // without the SML transport stuff + mc_sml_transport_receiver((unsigned char *)(sml_file ), i); + free(sml_file); + i = -1; + esc = 0; + end = 0; + } + } + else { + if (buf[i] == 0x1a) { + end++; + } + else { + // dont read other escaped sequences yet + printf("error: unrecognized sequence"); + esc = 0; + } + } + } + else { + if (buf[i] == 0x1b) { + esc++; + } + else { + esc = 0; + } + } + i++; + } + } + } + printf("error: no end sequence found, buffer full."); +} + + + + diff --git a/sml/src/sml_tree.c b/sml/src/sml_tree.c new file mode 100644 index 0000000..14f2f01 --- /dev/null +++ b/sml/src/sml_tree.c @@ -0,0 +1,115 @@ + +#include +#include +#include + +sml_tree_path *sml_tree_path_init() { + sml_tree_path *tree_path = (sml_tree_path *) malloc(sizeof(sml_tree_path)); + memset(tree_path, 0, sizeof(sml_tree_path)); + return tree_path; +} + +void sml_tree_path_add_path_entry(sml_tree_path *tree_path, octet_string *entry) { + tree_path->path_entries_len++; + tree_path->path_entries = (octet_string **) realloc(tree_path->path_entries, sizeof(octet_string *) * tree_path->path_entries_len); + tree_path->path_entries[tree_path->path_entries_len - 1] = entry; +} + +void sml_tree_path_write(sml_tree_path *tree_path, sml_buffer *buf) { + int i; + if (tree_path->path_entries && tree_path->path_entries_len > 0) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, tree_path->path_entries_len); + for (i = 0; i < tree_path->path_entries_len; i++) { + sml_octet_string_write(tree_path->path_entries[i], buf); + } + } +} + +void sml_tree_path_free(sml_tree_path *tree_path){ + printf("NYI: %s\n", __FUNCTION__); +} + + +sml_tree *sml_tree_init(octet_string *parameter_name) { + sml_tree *tree = (sml_tree *) malloc(sizeof(sml_tree)); + memset(tree, 0, sizeof(sml_tree)); + tree->parameter_name = parameter_name; + return tree; +} + +sml_tree *sml_tree_parse(sml_buffer *buf){ + printf("ERROR : NYI sml_tree_parse() not implemented yet"); + return 0; +} + +void sml_tree_free(sml_tree *tree){ + printf("ERROR : NYI sml_tree_free() not implemented yet"); +} + +void sml_tree_write(sml_tree *tree, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 3); + sml_octet_string_write(tree->parameter_name, buf); + // TODO + sml_proc_par_value_write(tree->parameter_value, buf); + //mc_sml_optional_write(buf); + mc_sml_optional_write(buf); +} + +sml_proc_par_value *sml_proc_par_value_init(u8 tag, void *data) { + + sml_proc_par_value *value = (sml_proc_par_value *) malloc(sizeof(sml_proc_par_value)); + memset(value, 0, sizeof(sml_proc_par_value)); + value->tag = tag; + + switch (tag) { + case SML_PROC_PAR_VALUE_TAG_VALUE: + value->data.value = (sml_value*)data; + break; + case SML_PROC_PAR_VALUE_TAG_PERIOD_ENTRY: + printf("TODO: %s\n", __FUNCTION__); + break; + case SML_PROC_PAR_VALUE_TAG_TUPEL_ENTRY: + printf("TODO: %s\n", __FUNCTION__); + break; + case SML_PROC_PAR_VALUE_TAG_TIME: + printf("TODO: %s\n", __FUNCTION__); + break; + default: + if (value) { + free(value); + } + return 0; + } + + return value; +} + +void sml_proc_par_value_write(sml_proc_par_value *value, sml_buffer *buf) { + mc_sml_set_type_and_length(buf, SML_TYPE_LIST, 2); + sml_number_write(SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_8, (u64) value->tag, buf); + + switch (value->tag) { + case SML_PROC_PAR_VALUE_TAG_VALUE: + sml_value_write(value->data.value, buf); + break; + case SML_PROC_PAR_VALUE_TAG_PERIOD_ENTRY: + printf("TODO: %s\n", __FUNCTION__); + break; + case SML_PROC_PAR_VALUE_TAG_TUPEL_ENTRY: + printf("TODO: %s\n", __FUNCTION__); + break; + case SML_PROC_PAR_VALUE_TAG_TIME: + printf("TODO: %s\n", __FUNCTION__); + break; + default: + if (value) { + free(value); + } + buf->error = 1; + } +} + + +void sml_proc_par_value_free(sml_proc_par_value *value){ + printf("NYI: %s\n", __FUNCTION__); +} diff --git a/sml/src/sml_value.c b/sml/src/sml_value.c new file mode 100644 index 0000000..fd0a029 --- /dev/null +++ b/sml/src/sml_value.c @@ -0,0 +1,108 @@ + +#include + +#include + +sml_value *sml_value_parse(sml_buffer *buf) { + int type = mc_sml_buf_get_current_type(buf); + unsigned char byte = mc_sml_buf_get_current_byte(buf); + + sml_value *value = (sml_value *) malloc(sizeof(sml_value)); + value->type = type; + + switch (type) { + case SML_TYPE_OCTET_STRING: + value->data.bytes = sml_octet_string_parse(buf); + break; + case SML_TYPE_UNSIGNED: + switch (byte & SML_LENGTH_FIELD) { + case SML_TYPE_NUMBER_8: + value->data.uint8 = mc_sml_parse_u8(buf); + value->type |= SML_TYPE_NUMBER_8; + break; + case SML_TYPE_NUMBER_16: + value->data.uint16 = mc_sml_parse_u16(buf); + value->type |= SML_TYPE_NUMBER_16; + break; + case SML_TYPE_NUMBER_16 + 1: + case SML_TYPE_NUMBER_32: + value->data.uint32 = mc_sml_parse_u32(buf); + value->type |= SML_TYPE_NUMBER_32; + break; + case SML_TYPE_NUMBER_32 + 1: + case SML_TYPE_NUMBER_32 + 2: + case SML_TYPE_NUMBER_32 + 3: + case SML_TYPE_NUMBER_64: + value->data.uint64 = mc_sml_parse_u64(buf); + value->type |= SML_TYPE_NUMBER_64; + break; + default: + buf->error = 1; + break; + } + break; + + case SML_TYPE_INTEGER: + //switch (byte & SML_LENGTH_FIELD) { + // Integer 59 00 00 00 00 00 01 20 09 could'nt be evaluated cause (byte & SML_LENGTH_FIELD)=9 + // but 8 is maximum :( -> now it's working + // TODO: check if same problem exists for other SML_TYPEs too + switch ((byte & SML_LENGTH_FIELD)-1) { + case SML_TYPE_NUMBER_8: + value->data.int8 = mc_sml_parse_i8(buf); + value->type |= SML_TYPE_NUMBER_8; + break; + case SML_TYPE_NUMBER_16: + value->data.int16 = mc_sml_parse_i16(buf); + value->type |= SML_TYPE_NUMBER_16; + break; + case SML_TYPE_NUMBER_16 + 1: + case SML_TYPE_NUMBER_32: + value->data.int32 = mc_sml_parse_i32(buf); + value->type |= SML_TYPE_NUMBER_32; + break; + case SML_TYPE_NUMBER_32 + 1: + case SML_TYPE_NUMBER_32 + 2: + case SML_TYPE_NUMBER_32 + 3: + case SML_TYPE_NUMBER_64: + value->data.int64 = mc_sml_parse_i64(buf); + value->type |= SML_TYPE_NUMBER_64; + break; + default: + buf->error = 1; + break; + } + break; + default: + buf->error = 1; + break; + } + if (mc_sml_buf_has_errors(buf)) { + free(value); + return 0; + } + + return value; +} + +void sml_value_write(sml_value *value, sml_buffer *buf) { + if (value->type == SML_TYPE_BOOLEAN) { + sml_boolean_write(value->data.boolean, buf); + } +} + +sml_value *sml_value_init() { + sml_value *value = (sml_value *) malloc(sizeof(sml_value)); + memset(value, 0, sizeof(value)); + return value; +} + +void sml_value_free(sml_value *value) { + if (value) { + if (value->type == SML_TYPE_OCTET_STRING) { + sml_octet_string_free(value->data.bytes); + } + free(value); + } +} +