initial commit

basic functionalities are in, though some parts 
are missing
This commit is contained in:
Juri Glass 2011-06-16 12:41:21 +02:00
parent d105cd39b1
commit 8bde857aee
49 changed files with 2821 additions and 0 deletions

50
sml/Makefile Normal file
View file

@ -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

34
sml/include/sml/sml.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef _SML_H
#define _SML_H
#include "sml_message.h"
#include "sml_shared.h"
#include <stdlib.h>
#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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,70 @@
#ifndef _SML_MESSAGE_H
#define _SML_MESSAGE_H
#include <stdlib.h>
#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

View file

@ -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

View file

@ -0,0 +1,41 @@
#ifndef _SML_OCTET_STRING_H
#define _SML_OCTET_STRING_H
#include <string.h>
#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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,101 @@
#ifndef _SML_SHARED_H
#define _SML_SHARED_H
#include <stdlib.h>
#include <stdint.h>
#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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,19 @@
#ifndef _SML_TRANSPORT_H
#define _SML_TRANSPORT_H
#include <stdlib.h>
#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

View file

@ -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

View file

@ -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

133
sml/src/sml.c Normal file
View file

@ -0,0 +1,133 @@
#include <sml/sml.h>
#include <sml/sml_shared.h>
#include <sml/sml_message.h>
#include <sml/sml_number.h>
#include <sml/sml_time.h>
#include <stdio.h>
#include <string.h>
// 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);
}
}

View file

@ -0,0 +1,47 @@
#include <sml/sml_attention_response.h>
#include <sml/sml_tree.h>
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);
}
}

22
sml/src/sml_boolean.c Normal file
View file

@ -0,0 +1,22 @@
#include <sml/sml_boolean.h>
#include <stdio.h>
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++;
}

View file

@ -0,0 +1,52 @@
#include <sml/sml_close_request.h>
#include <stdio.h>
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);
}
}

View file

@ -0,0 +1,36 @@
#include <sml/sml_close_response.h>
#include <stdio.h>
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);
}
}

39
sml/src/sml_crc16.c Normal file
View file

@ -0,0 +1,39 @@
#include <sml/sml_crc16.h>
#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;
}

View file

@ -0,0 +1,88 @@
#include <sml/sml_get_list_request.h>
#include <stdio.h>
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);
}
}

View file

@ -0,0 +1,61 @@
#include <sml/sml_get_list_response.h>
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);
}
}

View file

@ -0,0 +1,45 @@
#include <sml/sml_get_proc_parameter_request.h>
#include <sml/sml_tree.h>
#include <stdio.h>
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);
}
}

View file

@ -0,0 +1,106 @@
#include <sml/sml_get_profile_pack_request.h>
#include <sml/sml_tree.h>
#include <sml/sml_boolean.h>
#include <sml/sml_time.h>
#include <stdio.h>
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__);
}

View file

@ -0,0 +1,18 @@
#include <sml/sml_get_profile_pack_response.h>
#include <sml/sml_shared.h>
#include <sml/sml_octet_string.h>
#include <sml/sml_time.h>
#include <sml/sml_list.h>
#include <sml/sml_tree.h>
#include <stdio.h>
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__);
}

114
sml/src/sml_list.c Normal file
View file

@ -0,0 +1,114 @@
#include <sml/sml_list.h>
#include <sml/sml_shared.h>
#include <sml/sml_time.h>
#include <sml/sml_octet_string.h>
#include <sml/sml_status.h>
#include <sml/sml_value.h>
#include <stdio.h>
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;
}
}
}
}

221
sml/src/sml_message.c Normal file
View file

@ -0,0 +1,221 @@
#include <sml/sml_message.h>
#include <sml/sml_number.h>
#include <sml/sml_octet_string.h>
#include <sml/sml_shared.h>
#include <sml/sml_list.h>
#include <sml/sml_time.h>
#include <sml/sml_crc16.h>
#include <sml/sml_get_proc_parameter_request.h>
#include <sml/sml_set_proc_parameter_request.h>
#include <sml/sml_get_profile_pack_request.h>
#include <sml/sml_get_list_request.h>
#include <sml/sml_get_list_response.h>
#include <sml/sml_attention_response.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#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);
}
}

43
sml/src/sml_number.c Normal file
View file

@ -0,0 +1,43 @@
#include <sml/sml_number.h>
#include <string.h>
#include <stdio.h>
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;
}

113
sml/src/sml_octet_string.c Normal file
View file

@ -0,0 +1,113 @@
#include <sml/sml_octet_string.h>
#include <stdio.h>
#ifdef SML_WITH_UUID_LIB
#include <uuid/uuid.h>
#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;
}

105
sml/src/sml_open_request.c Normal file
View file

@ -0,0 +1,105 @@
#include <sml/sml_open_request.h>
#include <sml/sml_number.h>
#include <stdio.h>
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__);
}

View file

@ -0,0 +1,53 @@
#include <sml/sml_open_response.h>
#include <sml/sml_number.h>
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);
}
}

View file

@ -0,0 +1,26 @@
#include <sml/sml_set_proc_parameter_request.h>
#include <stdio.h>
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__);
}

123
sml/src/sml_shared.c Normal file
View file

@ -0,0 +1,123 @@
#include <string.h>
#include <sml/sml_shared.h>
#include <stdio.h>
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");
}

50
sml/src/sml_status.c Normal file
View file

@ -0,0 +1,50 @@
#include <sml/sml_status.h>
#include <sml/sml_shared.h>
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);
}
}

42
sml/src/sml_time.c Normal file
View file

@ -0,0 +1,42 @@
#include <sml/sml_time.h>
#include <sml/sml_shared.h>
#include <sml/sml_number.h>
#include <stdio.h>
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);
}
}

101
sml/src/sml_transport.c Normal file
View file

@ -0,0 +1,101 @@
#include <sml/sml_transport.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#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.");
}

115
sml/src/sml_tree.c Normal file
View file

@ -0,0 +1,115 @@
#include <sml/sml_tree.h>
#include <sml/sml_value.h>
#include <stdio.h>
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__);
}

108
sml/src/sml_value.c Normal file
View file

@ -0,0 +1,108 @@
#include <sml/sml_value.h>
#include <stdio.h>
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);
}
}