Convert mmss to C++, add parser

This commit is contained in:
Matthias Schiffer 2013-07-26 14:22:18 +02:00
parent ac9f22678b
commit 0ffde34faa
15 changed files with 609 additions and 47 deletions

View file

@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 2.8.3) cmake_minimum_required(VERSION 2.8.3)
project(GMRF C) project(GMRF C CXX)
set(CMAKE_MODULE_PATH ${GMRF_SOURCE_DIR})
find_package(BISON 2.5 REQUIRED)
find_package(FLEX REQUIRED)
add_subdirectory(mmss) add_subdirectory(mmss)
add_subdirectory(mmss-protocol) add_subdirectory(mmss-protocol)

120
FindFLEX.cmake Normal file
View file

@ -0,0 +1,120 @@
#=============================================================================
# Copyright 2009 Kitware, Inc.
# Copyright 2006 Tristan Carel
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
# nor the names of their contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ------------------------------------------------------------------------------
#
# The above copyright and license notice applies to distributions of
# CMake in source and binary form. Some source files contain additional
# notices of original copyright by their contributors; see each source
# for details. Third-party software packages supplied with CMake under
# compatible licenses provide their own copyright notices documented in
# corresponding subdirectories.
#=============================================================================
FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable")
MARK_AS_ADVANCED(FLEX_EXECUTABLE)
FIND_LIBRARY(FL_LIBRARY NAMES fl
DOC "Path to the fl library")
FIND_PATH(FLEX_INCLUDE_DIR FlexLexer.h
DOC "Path to the flex headers")
MARK_AS_ADVANCED(FL_LIBRARY FLEX_INCLUDE_DIR)
SET(FLEX_INCLUDE_DIRS ${FLEX_INCLUDE_DIR})
SET(FLEX_LIBRARIES ${FL_LIBRARY})
IF(FLEX_EXECUTABLE)
EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version
OUTPUT_VARIABLE FLEX_version_output
ERROR_VARIABLE FLEX_version_error
RESULT_VARIABLE FLEX_version_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
IF(NOT ${FLEX_version_result} EQUAL 0)
IF(FLEX_FIND_REQUIRED)
MESSAGE(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}")
ELSE()
MESSAGE("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available")
ENDIF()
ELSE()
STRING(REGEX REPLACE "^flex (.*)$" "\\1"
FLEX_VERSION "${FLEX_version_output}")
ENDIF()
#============================================================
# FLEX_TARGET (public macro)
#============================================================
#
MACRO(FLEX_TARGET Name Input Output)
SET(FLEX_TARGET_usage "FLEX_TARGET(<Name> <Input> <Output> [COMPILE_FLAGS <string>]")
IF(${ARGC} GREATER 3)
IF(${ARGC} EQUAL 5)
IF("${ARGV3}" STREQUAL "COMPILE_FLAGS")
SET(FLEX_EXECUTABLE_opts "${ARGV4}")
SEPARATE_ARGUMENTS(FLEX_EXECUTABLE_opts)
ELSE()
MESSAGE(SEND_ERROR ${FLEX_TARGET_usage})
ENDIF()
ELSE()
MESSAGE(SEND_ERROR ${FLEX_TARGET_usage})
ENDIF()
ENDIF()
STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${Output}")
STRING(REPLACE "c" "h" _fileext ${_fileext})
STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}"
OutputHeader "${Output}")
ADD_CUSTOM_COMMAND(OUTPUT ${Output} ${OutputHeader}
COMMAND ${FLEX_EXECUTABLE}
ARGS ${FLEX_EXECUTABLE_opts} -o${Output} --header-file=${OutputHeader} ${Input}
DEPENDS ${Input}
COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
SET(FLEX_${Name}_DEFINED TRUE)
SET(FLEX_${Name}_OUTPUTS ${Output} ${OutputHeader})
SET(FLEX_${Name}_OUTPUT_HEADER ${OutputHeader})
SET(FLEX_${Name}_INPUT ${Input})
SET(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts})
ENDMACRO(FLEX_TARGET)
#============================================================
ENDIF(FLEX_EXECUTABLE)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX REQUIRED_VARS FLEX_EXECUTABLE
VERSION_VAR FLEX_VERSION)
# FindFLEX.cmake ends here

View file

@ -1,11 +1,18 @@
include_directories(${GMRF_SOURCE_DIR}/include) include_directories(${GMRF_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
FLEX_TARGET(mmss_config_lex config.l ${CMAKE_CURRENT_BINARY_DIR}/config.ll.cpp)
BISON_TARGET(mmss_config_parse config.y ${CMAKE_CURRENT_BINARY_DIR}/config.yy.cpp)
add_executable(mmss add_executable(mmss
iface.c config.cpp
log.c iface.cpp
mmss.c log.cpp
protocol.c mmss.cpp
queue.c protocol.cpp
schedule.c queue.cpp
schedule.cpp
${FLEX_mmss_config_lex_OUTPUTS}
${BISON_mmss_config_parse_OUTPUTS}
) )
target_link_libraries(mmss dl) target_link_libraries(mmss dl)
set_target_properties(mmss PROPERTIES COMPILE_FLAGS -std=c++11)

125
mmss/config.cpp Normal file
View file

@ -0,0 +1,125 @@
/*
Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mmss.hpp"
#include <config.ll.hpp>
#include <config.yy.hpp>
#include <libgen.h>
void mmss_config_add_network(mmss_t *mmss, mmss_config_t *conf, const char *name) {
mmss_logf(mmss, LOG_NOTICE, "Adding network `%s'", name);
mmss_network_t *net = new mmss_network_t;
net->name = strdup(name);
net->mtu = 1500;
net->next = conf->networks;
conf->networks = net;
}
bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
bool ret = true;
char *oldcwd = get_current_dir_name();
char *filename2 = NULL;
char *dir = NULL;
FILE *file;
yyscan_t scanner;
mmss_config_pstate *ps;
mmss_string_stack_t *strings = NULL;
int token;
YYSTYPE token_val;
YYLTYPE loc = {1, 0, 1, 0};
int parse_ret;
mmss_config_yylex_init(&scanner);
ps = mmss_config_pstate_new();
if (!filename) {
file = stdin;
}
else {
file = fopen(filename, "r");
if (!file) {
mmss_logf(mmss, LOG_ERR, "can't open config file `%s': %s", filename, strerror(errno));
ret = false;
goto end_free;
}
}
mmss_config_yyset_in(file, scanner);
if (filename) {
filename2 = strdup(filename);
dir = dirname(filename2);
if (chdir(dir)) {
mmss_logf(mmss, LOG_ERR, "change from directory `%s' to `%s' failed", oldcwd, dir);
ret = false;
goto end_free;
}
}
do {
token = mmss_config_yylex(&token_val, &loc, scanner);
if (token < 0) {
mmss_logf(mmss, LOG_ERR, "config error: %s at %s:%i:%i", token_val.error, filename, loc.first_line, loc.first_column);
ret = false;
goto end_free;
}
if (token == TOK_STRING) {
token_val.str->next = strings;
strings = token_val.str;
}
parse_ret = mmss_config_push_parse(ps, token, &token_val, &loc, mmss, conf, filename);
} while (parse_ret == YYPUSH_MORE);
if (parse_ret)
ret = false;
end_free:
mmss_string_stack_free(strings);
mmss_config_pstate_delete(ps);
mmss_config_yylex_destroy(scanner);
if(chdir(oldcwd))
mmss_logf(mmss, LOG_ERR, "can't chdir to `%s': %s", oldcwd, strerror(errno));
free(filename2);
free(oldcwd);
if (filename && file)
fclose(file);
return ret;
}

129
mmss/config.l Normal file
View file

@ -0,0 +1,129 @@
/*
Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
%option prefix="mmss_config_yy"
%option noyywrap
%option nounput
%option noinput
%option bison-bridge
%option bison-locations
%option reentrant
%option warn
%top {
#include <config.yy.hpp>
}
%s NEEDSPACE
%s STRING
%s COMMENT
%%
%{
#define UPDATE_LOCATION do { \
yylloc->first_line = yylloc->last_line; \
yylloc->first_column = yylloc->last_column+1; \
yylloc->last_column += yyleng; \
} while (0)
#define TOKEN(tok) do { UPDATE_LOCATION; BEGIN(NEEDSPACE); return tok; } while (0)
%}
<INITIAL>{
[0-9]+ { UPDATE_LOCATION; yylval->num = atoi(yytext); BEGIN(NEEDSPACE); return TOK_INTEGER; }
yes { TOKEN(TOK_YES); }
no { TOKEN(TOK_NO); }
network { TOKEN(TOK_NETWORK); }
[;:\{\}] { UPDATE_LOCATION; return yytext[0]; }
[ \t] { yylloc->last_column++; }
\n { yylloc->last_column = 0; yylloc->last_line++; }
\r ;
}
<NEEDSPACE>{
[;:\{\}] { UPDATE_LOCATION; BEGIN(INITIAL); return yytext[0]; }
[ \t] { yylloc->last_column++; BEGIN(INITIAL); }
\n { yylloc->last_column = 0; yylloc->last_line++; BEGIN(INITIAL); }
\r ;
}
<INITIAL>\" { UPDATE_LOCATION; BEGIN(STRING); }
<STRING>[^"\\\n\r] { yylloc->last_column++; yymore(); }
<STRING>\n { yylloc->last_line++; yylloc->last_column = 0; yymore(); }
<STRING>\r { yymore(); }
<STRING>\\. { yylloc->last_column+=2; yymore(); }
<STRING>\\\n { yylloc->last_line++; yylloc->last_column = 0; yymore(); }
<STRING>\" {
int i, esc = 0;
for (i = 0; i < yyleng; i++) {
if (yytext[i] == '\\') {
i++;
if (yytext[i] == '\n') {
esc+=2;
}
else {
yytext[i-esc-1] = yytext[i];
esc++;
}
}
else if(esc) {
yytext[i-esc] = yytext[i];
}
}
yytext[yyleng-esc-1] = 0;
yylval->str = mmss_string_stack_dup(yytext);
BEGIN(NEEDSPACE);
yylloc->last_column++;
return TOK_STRING;
}
<INITIAL,NEEDSPACE>#.* { yylloc->last_column += yyleng; }
<INITIAL,NEEDSPACE>\/\/.* { yylloc->last_column += yyleng; }
<INITIAL,NEEDSPACE>\/\* { UPDATE_LOCATION; BEGIN(COMMENT); }
<COMMENT>\*\/ { yylloc->last_column += yyleng; BEGIN(INITIAL); }
<COMMENT>[^\n\r] { yylloc->last_column++; }
<COMMENT>\n { yylloc->last_line++; yylloc->last_column = 0; }
<COMMENT>\r {}
. {
yylloc->first_line = yylloc->last_line;
yylloc->first_column = yylloc->last_column+1;
yylval->error = "syntax error";
return -1;
}
<INITIAL><<EOF>> { return 0; }
<COMMENT><<EOF>> { yylval->error = "unterminated block comment"; return -1; }
<STRING><<EOF>> { yylval->error = "unterminated string"; return -1; }
%%

93
mmss/config.y Normal file
View file

@ -0,0 +1,93 @@
/*
Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
%define api.pure
%define api.push-pull push
%name-prefix "mmss_config_"
%locations
%parse-param {mmss_t *mmss}
%parse-param {mmss_config_t *conf}
%parse-param {const char *filename}
%code requires {
#include <mmss.hpp>
#include <cstdio>
}
%union {
int num;
mmss_string_stack_t *str;
bool boolean;
const char *error;
}
%token <num> TOK_INTEGER
%token <str> TOK_STRING
%token TOK_NETWORK
%token TOK_YES
%token TOK_NO
%code {
void mmss_config_error(YYLTYPE *loc, mmss_t *mmss, mmss_config_t *conf, const char *filename, const char *s);
}
%type <boolean> boolean
%%
start: config
;
config: config statement
|
;
statement: TOK_NETWORK network '{' network_config '}'
;
network: TOK_STRING {
mmss_config_add_network(mmss, conf, $1->str);
}
;
network_config:
;
boolean: TOK_YES { $$ = true; }
| TOK_NO { $$ = false; }
;
%%
void mmss_config_error(YYLTYPE *loc, mmss_t *mmss, mmss_config_t *conf, const char *filename, const char *s) {
mmss_logf(mmss, LOG_ERR, "config error: %s at %s:%i:%i", s, filename, loc->first_line, loc->first_column);
}

View file

@ -24,9 +24,9 @@
*/ */
#include "mmss.h" #include "mmss.hpp"
#include <stdlib.h> #include <cstdlib>
gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) { gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) {
@ -42,7 +42,7 @@ size_t gmrf_iface_get_mtu(gmrf_t *gmrf, gmrf_iface_t *iface) {
} }
static void enqueue(mmss_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, const void *data, size_t len) { static void enqueue(mmss_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, const void *data, size_t len) {
mmss_packet_t *packet = calloc(1, sizeof(mmss_packet_t) + len); mmss_packet_t *packet = reinterpret_cast<mmss_packet_t*>(calloc(1, sizeof(mmss_packet_t) + len));
packet->sent = mmss->now; packet->sent = mmss->now;
packet->source = source; packet->source = source;
@ -82,7 +82,7 @@ void mmss_dispatch(mmss_packet_t *packet) {
} }
void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address) { void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address) {
gmrf_iface_t *iface = calloc(1, sizeof(gmrf_iface_t)); gmrf_iface_t *iface = new gmrf_iface_t;
iface->name = strdup(name); iface->name = strdup(name);
iface->address = *address; iface->address = *address;

View file

@ -24,9 +24,9 @@
*/ */
#include "mmss.h" #include "mmss.hpp"
#include <stdio.h> #include <cstdio>
static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) { static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) {
@ -57,12 +57,11 @@ static inline const char* get_log_prefix(int log_level) {
} }
} }
void mmss_logf(mmss_t *mmss, int priority, const char *format, ...) {
void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) {
char buf[1024]; char buf[1024];
size_t pos = 0; size_t pos = 0;
pos += snprintf_safe(buf, sizeof(buf), "[% 5u.%03u] %s: %s", gmrf->mmss->now/1000, gmrf->mmss->now%1000, gmrf->name, get_log_prefix(priority)); pos += snprintf_safe(buf, sizeof(buf), "[% 5u.%03u] ", mmss->now/1000, mmss->now%1000);
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
@ -71,3 +70,17 @@ void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) {
fprintf(stderr, "%s\n", buf); fprintf(stderr, "%s\n", buf);
} }
void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) {
char buf[1024];
size_t pos = 0;
pos += snprintf_safe(buf, sizeof(buf), "%s: %s", gmrf->name, get_log_prefix(priority));
va_list ap;
va_start(ap, format);
vsnprintf(buf+pos, sizeof(buf)-pos, format, ap);
va_end(ap);
mmss_logf(gmrf->mmss, priority, "%s", buf);
}

View file

@ -24,11 +24,11 @@
*/ */
#include "mmss.h" #include "mmss.hpp"
#include <assert.h> #include <cassert>
#include <stdio.h> #include <cstdio>
#include <stdlib.h> #include <cstdlib>
gmrf_time_t gmrf_now(gmrf_t *gmrf) { gmrf_time_t gmrf_now(gmrf_t *gmrf) {
@ -36,7 +36,7 @@ gmrf_time_t gmrf_now(gmrf_t *gmrf) {
} }
void gmrf_random_bytes(gmrf_t *gmrf, void *buffer, size_t len) { void gmrf_random_bytes(gmrf_t *gmrf, void *buffer, size_t len) {
uint8_t *data = buffer; uint8_t *data = reinterpret_cast<uint8_t*>(buffer);
size_t i; size_t i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
@ -78,11 +78,14 @@ int main(int argc, char *argv[]) {
return 1; return 1;
mmss_t mmss = { .now = 0 }; mmss_t mmss = { .now = 0 };
mmss_config_t conf = {};
mmss_read_config(&mmss, &conf, "babel_test.mmss");
mmss_network_t net0 = { .mtu = 1500 }, net1 = { .mtu = 1500 }; mmss_network_t net0 = { .mtu = 1500 }, net1 = { .mtu = 1500 };
gmrf_t node1 = { .name = "node1", .mmss = &mmss, .rand_seed = 1, .proto = proto }; gmrf_t node1 = { .name = strdup("node1"), .mmss = &mmss, .rand_seed = 1, .proto = proto };
gmrf_t node2 = { .name = "node2", .mmss = &mmss, .rand_seed = 2, .proto = proto }; gmrf_t node2 = { .name = strdup("node2"), .mmss = &mmss, .rand_seed = 2, .proto = proto };
gmrf_t node3 = { .name = "node3", .mmss = &mmss, .rand_seed = 3, .proto = proto }; gmrf_t node3 = { .name = strdup("node3"), .mmss = &mmss, .rand_seed = 3, .proto = proto };
node2.next = &node1; node2.next = &node1;
node3.next = &node2; node3.next = &node2;
@ -115,12 +118,12 @@ int main(int argc, char *argv[]) {
assert(timeout == 0); assert(timeout == 0);
while (timeout == 0) { while (timeout == 0) {
mmss_packet_t *packet = mmss_queue_get(&mmss, &mmss.packet_queue); mmss_packet_t *packet = reinterpret_cast<mmss_packet_t*>(mmss_queue_get(&mmss, &mmss.packet_queue));
mmss_scheduled_t *scheduled = mmss_queue_get(&mmss, &mmss.scheduled_queue); mmss_scheduled_t *scheduled = reinterpret_cast<mmss_scheduled_t*>(mmss_queue_get(&mmss, &mmss.scheduled_queue));
assert(packet || scheduled); assert(packet || scheduled);
if(packet) if (packet)
mmss_dispatch(packet); mmss_dispatch(packet);
if (scheduled) if (scheduled)

View file

@ -27,11 +27,17 @@
#ifndef _GMRF_MMSS_MMSS_H_ #ifndef _GMRF_MMSS_MMSS_H_
#define _GMRF_MMSS_MMSS_H_ #define _GMRF_MMSS_MMSS_H_
#include "queue.hpp"
extern "C" {
#include <gmrf/gmrf.h> #include <gmrf/gmrf.h>
#include <mmss/protocol.h> #include <mmss/protocol.h>
#include "queue.h" }
#include <cstdlib>
#include <cstring>
struct mmss { struct mmss {
uint64_t now; uint64_t now;
@ -39,11 +45,17 @@ struct mmss {
mmss_queue_t scheduled_queue; mmss_queue_t scheduled_queue;
}; };
struct mmss_config {
mmss_network_t *networks;
gmrf_t *nodes;
};
struct mmss_network { struct mmss_network {
mmss_network_t *next; mmss_network_t *next;
gmrf_iface_t *interfaces; char *name;
gmrf_iface_t *interfaces;
size_t mtu; size_t mtu;
}; };
@ -63,11 +75,16 @@ struct mmss_scheduled {
void *arg; void *arg;
}; };
struct mmss_string_stack {
mmss_string_stack_t *next;
char str[];
};
struct gmrf { struct gmrf {
gmrf_t *next; gmrf_t *next;
const char *name; char *name;
mmss_t *mmss; mmss_t *mmss;
gmrf_context_t *ctx; gmrf_context_t *ctx;
@ -92,11 +109,17 @@ struct gmrf_iface {
const mmss_protocol_t* mmss_load_protocol(const char *module); const mmss_protocol_t* mmss_load_protocol(const char *module);
void mmss_config_add_network(mmss_t *mmss, mmss_config_t *conf, const char *name);
bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename);
void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address); void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address);
void mmss_dispatch(mmss_packet_t *packet); void mmss_dispatch(mmss_packet_t *packet);
void mmss_run_scheduled(mmss_scheduled_t *scheduled); void mmss_run_scheduled(mmss_scheduled_t *scheduled);
void mmss_logf(mmss_t *mmss, int priority, const char *format, ...);
static inline int max(int a, int b) { static inline int max(int a, int b) {
return (a > b) ? a : b; return (a > b) ? a : b;
@ -107,4 +130,43 @@ static inline int min(int a, int b) {
} }
static inline size_t alignto(size_t l, size_t a) {
return ((l+a-1)/a)*a;
}
static inline mmss_string_stack_t* mmss_string_stack_dup(const char *str) {
mmss_string_stack_t *ret = reinterpret_cast<mmss_string_stack_t*>(std::malloc(alignto(sizeof(mmss_string_stack_t) + strlen(str) + 1, 8)));
ret->next = NULL;
std::strcpy(ret->str, str);
return ret;
}
static inline mmss_string_stack_t* mmss_string_stack_dupn(const char *str, size_t len) {
size_t str_len = strnlen(str, len);
mmss_string_stack_t *ret = reinterpret_cast<mmss_string_stack_t*>(std::malloc(alignto(sizeof(mmss_string_stack_t) + str_len + 1, 8)));
ret->next = NULL;
std::strncpy(ret->str, str, str_len);
ret->str[str_len] = 0;
return ret;
}
static inline mmss_string_stack_t* mmss_string_stack_push(mmss_string_stack_t *stack, const char *str) {
mmss_string_stack_t *ret = reinterpret_cast<mmss_string_stack_t*>(std::malloc(alignto(sizeof(mmss_string_stack_t) + strlen(str) + 1, 8)));
ret->next = stack;
std::strcpy(ret->str, str);
return ret;
}
static inline void mmss_string_stack_free(mmss_string_stack_t *str) {
while(str) {
mmss_string_stack_t *next = str->next;
std::free(str);
str = next;
}
}
#endif /* _GMRF_MMSS_MMSS_H_ */ #endif /* _GMRF_MMSS_MMSS_H_ */

View file

@ -24,10 +24,10 @@
*/ */
#include "mmss.h" #include "mmss.hpp"
#include <dlfcn.h> #include <dlfcn.h>
#include <stdio.h> #include <cstdio>
const mmss_protocol_t* mmss_load_protocol(const char *module) { const mmss_protocol_t* mmss_load_protocol(const char *module) {
@ -38,7 +38,7 @@ const mmss_protocol_t* mmss_load_protocol(const char *module) {
} }
dlerror(); dlerror();
const mmss_protocol_t *proto = dlsym(handle, "mmss_protocol_info"); const mmss_protocol_t *proto = reinterpret_cast<const mmss_protocol_t*>(dlsym(handle, "mmss_protocol_info"));
if (!proto) { if (!proto) {
fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror()); fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
dlclose(handle); dlclose(handle);

View file

@ -24,10 +24,10 @@
*/ */
#include "queue.h" #include "queue.hpp"
#include "mmss.h" #include "mmss.hpp"
#include <stdlib.h> #include <cstdlib>
typedef struct mmss_queue_entry mmss_queue_entry_t; typedef struct mmss_queue_entry mmss_queue_entry_t;
@ -43,7 +43,7 @@ void mmss_queue_put(mmss_t *mmss, mmss_queue_t *queue, void *data, uint64_t time
while (*queue && timeout >= (*queue)->timeout) while (*queue && timeout >= (*queue)->timeout)
queue = &(*queue)->next; queue = &(*queue)->next;
mmss_queue_entry_t *entry = malloc(sizeof(mmss_queue_entry_t)); mmss_queue_entry_t *entry = new mmss_queue_entry_t;
entry->timeout = timeout; entry->timeout = timeout;
entry->data = data; entry->data = data;

View file

@ -27,9 +27,9 @@
#ifndef _GMRF_MMSS_QUEUE_H_ #ifndef _GMRF_MMSS_QUEUE_H_
#define _GMRF_MMSS_QUEUE_H_ #define _GMRF_MMSS_QUEUE_H_
#include <stdint.h> #include "types.hpp"
#include "types.h" #include <cstdint>
typedef struct mmss_queue_entry *mmss_queue_t; typedef struct mmss_queue_entry *mmss_queue_t;

View file

@ -24,13 +24,11 @@
*/ */
#include "mmss.h" #include "mmss.hpp"
#include <stdlib.h>
void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned delay) { void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned delay) {
mmss_scheduled_t *scheduled = calloc(1, sizeof(mmss_scheduled_t)); mmss_scheduled_t *scheduled = new mmss_scheduled_t;
scheduled->node = gmrf; scheduled->node = gmrf;
scheduled->f = f; scheduled->f = f;
@ -41,5 +39,5 @@ void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned dela
void mmss_run_scheduled(mmss_scheduled_t *scheduled) { void mmss_run_scheduled(mmss_scheduled_t *scheduled) {
scheduled->f(scheduled->node, scheduled->node->ctx, scheduled->arg); scheduled->f(scheduled->node, scheduled->node->ctx, scheduled->arg);
free(scheduled); delete scheduled;
} }

View file

@ -27,9 +27,16 @@
#ifndef _GMRF_MMSS_TYPES_H_ #ifndef _GMRF_MMSS_TYPES_H_
#define _GMRF_MMSS_TYPES_H_ #define _GMRF_MMSS_TYPES_H_
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
typedef struct mmss mmss_t; typedef struct mmss mmss_t;
typedef struct mmss_config mmss_config_t;
typedef struct mmss_network mmss_network_t; typedef struct mmss_network mmss_network_t;
typedef struct mmss_packet mmss_packet_t; typedef struct mmss_packet mmss_packet_t;
typedef struct mmss_scheduled mmss_scheduled_t; typedef struct mmss_scheduled mmss_scheduled_t;
typedef struct mmss_string_stack mmss_string_stack_t;
#endif /* _GMRF_MMSS_TYPES_H_ */ #endif /* _GMRF_MMSS_TYPES_H_ */