Clean up queue implementation, fix namespaces
This commit is contained in:
parent
0ffde34faa
commit
1f67abe0f3
13 changed files with 270 additions and 287 deletions
|
@ -9,7 +9,6 @@ add_executable(mmss
|
|||
log.cpp
|
||||
mmss.cpp
|
||||
protocol.cpp
|
||||
queue.cpp
|
||||
schedule.cpp
|
||||
${FLEX_mmss_config_lex_OUTPUTS}
|
||||
${BISON_mmss_config_parse_OUTPUTS}
|
||||
|
|
|
@ -28,13 +28,19 @@
|
|||
#include <config.ll.hpp>
|
||||
#include <config.yy.hpp>
|
||||
|
||||
#include <stack>
|
||||
|
||||
#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);
|
||||
namespace MMSS {
|
||||
|
||||
mmss_network_t *net = new mmss_network_t;
|
||||
namespace Config {
|
||||
|
||||
void add_network(context_t *mmss, config_t *conf, const char *name) {
|
||||
logf(mmss, LOG_NOTICE, "adding network `%s'", name);
|
||||
|
||||
network_t *net = new network_t;
|
||||
|
||||
net->name = strdup(name);
|
||||
net->mtu = 1500;
|
||||
|
@ -43,7 +49,9 @@ void mmss_config_add_network(mmss_t *mmss, mmss_config_t *conf, const char *name
|
|||
conf->networks = net;
|
||||
}
|
||||
|
||||
bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
||||
}
|
||||
|
||||
bool read_config(context_t *mmss, config_t *conf, const char *filename) {
|
||||
bool ret = true;
|
||||
char *oldcwd = get_current_dir_name();
|
||||
char *filename2 = NULL;
|
||||
|
@ -51,11 +59,11 @@ bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
|||
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;
|
||||
std::stack<char*> strings;
|
||||
|
||||
|
||||
mmss_config_yylex_init(&scanner);
|
||||
|
@ -67,7 +75,7 @@ bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
|||
else {
|
||||
file = fopen(filename, "r");
|
||||
if (!file) {
|
||||
mmss_logf(mmss, LOG_ERR, "can't open config file `%s': %s", filename, strerror(errno));
|
||||
logf(mmss, LOG_ERR, "can't open config file `%s': %s", filename, strerror(errno));
|
||||
ret = false;
|
||||
goto end_free;
|
||||
}
|
||||
|
@ -80,7 +88,7 @@ bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
|||
dir = dirname(filename2);
|
||||
|
||||
if (chdir(dir)) {
|
||||
mmss_logf(mmss, LOG_ERR, "change from directory `%s' to `%s' failed", oldcwd, dir);
|
||||
logf(mmss, LOG_ERR, "change from directory `%s' to `%s' failed", oldcwd, dir);
|
||||
ret = false;
|
||||
goto end_free;
|
||||
}
|
||||
|
@ -90,15 +98,14 @@ bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
|||
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);
|
||||
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;
|
||||
}
|
||||
if (token == TOK_STRING)
|
||||
strings.push(token_val.str);
|
||||
|
||||
|
||||
parse_ret = mmss_config_push_parse(ps, token, &token_val, &loc, mmss, conf, filename);
|
||||
} while (parse_ret == YYPUSH_MORE);
|
||||
|
@ -107,13 +114,16 @@ bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
|||
ret = false;
|
||||
|
||||
end_free:
|
||||
mmss_string_stack_free(strings);
|
||||
while (!strings.empty()) {
|
||||
std::free(strings.top());
|
||||
strings.pop();
|
||||
}
|
||||
|
||||
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));
|
||||
logf(mmss, LOG_ERR, "can't chdir to `%s': %s", oldcwd, strerror(errno));
|
||||
|
||||
free(filename2);
|
||||
free(oldcwd);
|
||||
|
@ -123,3 +133,5 @@ bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) {
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ network { TOKEN(TOK_NETWORK); }
|
|||
}
|
||||
}
|
||||
yytext[yyleng-esc-1] = 0;
|
||||
yylval->str = mmss_string_stack_dup(yytext);
|
||||
yylval->str = strdup(yytext);
|
||||
BEGIN(NEEDSPACE);
|
||||
yylloc->last_column++;
|
||||
return TOK_STRING;
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
%define api.push-pull push
|
||||
%name-prefix "mmss_config_"
|
||||
%locations
|
||||
%parse-param {mmss_t *mmss}
|
||||
%parse-param {mmss_config_t *conf}
|
||||
%parse-param {MMSS::context_t *mmss}
|
||||
%parse-param {MMSS::config_t *conf}
|
||||
%parse-param {const char *filename}
|
||||
|
||||
|
||||
|
@ -37,12 +37,13 @@
|
|||
#include <mmss.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
}
|
||||
|
||||
%union {
|
||||
int num;
|
||||
mmss_string_stack_t *str;
|
||||
bool boolean;
|
||||
char *str;
|
||||
|
||||
const char *error;
|
||||
}
|
||||
|
@ -56,7 +57,7 @@
|
|||
|
||||
|
||||
%code {
|
||||
void mmss_config_error(YYLTYPE *loc, mmss_t *mmss, mmss_config_t *conf, const char *filename, const char *s);
|
||||
void mmss_config_error(YYLTYPE *loc, MMSS::context_t *mmss, MMSS::config_t *conf, const char *filename, const char *s);
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,7 +76,7 @@ statement: TOK_NETWORK network '{' network_config '}'
|
|||
;
|
||||
|
||||
network: TOK_STRING {
|
||||
mmss_config_add_network(mmss, conf, $1->str);
|
||||
MMSS::Config::add_network(mmss, conf, $1);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -88,6 +89,6 @@ boolean: TOK_YES { $$ = true; }
|
|||
|
||||
%%
|
||||
|
||||
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);
|
||||
void mmss_config_error(YYLTYPE *loc, MMSS::context_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);
|
||||
}
|
||||
|
|
106
mmss/iface.cpp
106
mmss/iface.cpp
|
@ -26,62 +26,17 @@
|
|||
|
||||
#include "mmss.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) {
|
||||
return iface->address;
|
||||
}
|
||||
namespace MMSS {
|
||||
|
||||
const char* gmrf_iface_get_name(gmrf_t *gmrf, gmrf_iface_t *iface) {
|
||||
return iface->name;
|
||||
}
|
||||
|
||||
size_t gmrf_iface_get_mtu(gmrf_t *gmrf, gmrf_iface_t *iface) {
|
||||
return iface->net->mtu;
|
||||
}
|
||||
|
||||
static void enqueue(mmss_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, const void *data, size_t len) {
|
||||
mmss_packet_t *packet = reinterpret_cast<mmss_packet_t*>(calloc(1, sizeof(mmss_packet_t) + len));
|
||||
|
||||
packet->sent = mmss->now;
|
||||
packet->source = source;
|
||||
packet->dest = dest;
|
||||
packet->len = len;
|
||||
memcpy(packet->data, data, len);
|
||||
|
||||
mmss_queue_put(mmss, &mmss->packet_queue, packet, mmss->now+1);
|
||||
}
|
||||
|
||||
bool gmrf_iface_send(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len, const gmrf_addr_t *dest) {
|
||||
gmrf_iface_t *dest_iface;
|
||||
for (dest_iface = iface->net->interfaces; dest_iface; dest_iface = dest_iface->network_next) {
|
||||
if (gmrf_addr_equal(&dest_iface->address, dest)) {
|
||||
enqueue(gmrf->mmss, iface, dest_iface, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gmrf_iface_send_bc(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len) {
|
||||
gmrf_iface_t *dest_iface;
|
||||
for (dest_iface = iface->net->interfaces; dest_iface; dest_iface = dest_iface->network_next) {
|
||||
if (dest_iface != iface)
|
||||
enqueue(gmrf->mmss, iface, dest_iface, data, len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mmss_dispatch(mmss_packet_t *packet) {
|
||||
void dispatch(std::shared_ptr<packet_t> packet) {
|
||||
packet->dest->node->proto->handle_packet(packet->dest->node, packet->dest->node->ctx, packet->dest,
|
||||
&packet->source->address, packet->data, packet->len);
|
||||
free(packet);
|
||||
&packet->source->address, packet->data.get(), packet->len);
|
||||
}
|
||||
|
||||
void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address) {
|
||||
void add_iface(gmrf_t *node, network_t *net, const char *name, const gmrf_addr_t *address) {
|
||||
gmrf_iface_t *iface = new gmrf_iface_t;
|
||||
|
||||
iface->name = strdup(name);
|
||||
|
@ -98,3 +53,54 @@ void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const g
|
|||
|
||||
node->proto->add_iface(node, node->ctx, iface);
|
||||
}
|
||||
|
||||
static void enqueue(context_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, const void *data, size_t len) {
|
||||
std::shared_ptr<packet_t> packet = std::make_shared<packet_t>();
|
||||
|
||||
packet->sent = mmss->now;
|
||||
packet->source = source;
|
||||
packet->dest = dest;
|
||||
packet->len = len;
|
||||
|
||||
packet->data.reset(new uint8_t[len]);
|
||||
std::memcpy(packet->data.get(), data, len);
|
||||
|
||||
mmss->packet_queue.put(packet, mmss->now+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) {
|
||||
return iface->address;
|
||||
}
|
||||
|
||||
const char* gmrf_iface_get_name(gmrf_t *gmrf, gmrf_iface_t *iface) {
|
||||
return iface->name;
|
||||
}
|
||||
|
||||
size_t gmrf_iface_get_mtu(gmrf_t *gmrf, gmrf_iface_t *iface) {
|
||||
return iface->net->mtu;
|
||||
}
|
||||
|
||||
bool gmrf_iface_send(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len, const gmrf_addr_t *dest) {
|
||||
gmrf_iface_t *dest_iface;
|
||||
for (dest_iface = iface->net->interfaces; dest_iface; dest_iface = dest_iface->network_next) {
|
||||
if (gmrf_addr_equal(&dest_iface->address, dest)) {
|
||||
MMSS::enqueue(gmrf->mmss, iface, dest_iface, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gmrf_iface_send_bc(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len) {
|
||||
gmrf_iface_t *dest_iface;
|
||||
for (dest_iface = iface->net->interfaces; dest_iface; dest_iface = dest_iface->network_next) {
|
||||
if (dest_iface != iface)
|
||||
enqueue(gmrf->mmss, iface, dest_iface, data, len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
17
mmss/log.cpp
17
mmss/log.cpp
|
@ -26,13 +26,16 @@
|
|||
|
||||
#include "mmss.hpp"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace MMSS {
|
||||
|
||||
static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) {
|
||||
va_list ap;
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
int ret = vsnprintf(buffer, size, format, ap);
|
||||
int ret = std::vsnprintf(buffer, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret < 0 ? 0 : ret > size ? size : ret;
|
||||
|
@ -57,13 +60,13 @@ static inline const char* get_log_prefix(int log_level) {
|
|||
}
|
||||
}
|
||||
|
||||
void mmss_logf(mmss_t *mmss, int priority, const char *format, ...) {
|
||||
void logf(context_t *mmss, int priority, const char *format, ...) {
|
||||
char buf[1024];
|
||||
size_t pos = 0;
|
||||
|
||||
pos += snprintf_safe(buf, sizeof(buf), "[% 5u.%03u] ", mmss->now/1000, mmss->now%1000);
|
||||
|
||||
va_list ap;
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
vsnprintf(buf+pos, sizeof(buf)-pos, format, ap);
|
||||
va_end(ap);
|
||||
|
@ -71,16 +74,18 @@ void mmss_logf(mmss_t *mmss, int priority, const char *format, ...) {
|
|||
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));
|
||||
pos += MMSS::snprintf_safe(buf, sizeof(buf), "%s: %s", gmrf->name, MMSS::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);
|
||||
MMSS::logf(gmrf->mmss, priority, "%s", buf);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
gmrf_time_t gmrf_now(gmrf_t *gmrf) {
|
||||
|
@ -43,6 +42,7 @@ void gmrf_random_bytes(gmrf_t *gmrf, void *buffer, size_t len) {
|
|||
data[i] = rand_r(&gmrf->rand_seed);
|
||||
}
|
||||
|
||||
namespace MMSS {
|
||||
|
||||
static void init_nodes(gmrf_t *nodes) {
|
||||
gmrf_t *node;
|
||||
|
@ -62,27 +62,30 @@ static inline int timeout_min(int a, int b) {
|
|||
}
|
||||
|
||||
|
||||
static int get_queue_timeout(const mmss_t *mmss) {
|
||||
return timeout_min(mmss_queue_timeout(mmss, &mmss->packet_queue), mmss_queue_timeout(mmss, &mmss->scheduled_queue));
|
||||
static int get_queue_timeout(const context_t *mmss) {
|
||||
return timeout_min(mmss->packet_queue.timeout(), mmss->scheduled_queue.timeout());
|
||||
}
|
||||
|
||||
uint64_t now(const context_t *mmss) {
|
||||
return mmss->now;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void main(int argc, char *argv[]) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s protocol_module\n", argv[0]);
|
||||
return 1;
|
||||
std::fprintf(stderr, "usage: %s protocol_module\n", argv[0]);
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const mmss_protocol_t *proto = mmss_load_protocol(argv[1]);
|
||||
const protocol_t *proto = load_protocol(argv[1]);
|
||||
if (!proto)
|
||||
return 1;
|
||||
std::exit(1);
|
||||
|
||||
mmss_t mmss = { .now = 0 };
|
||||
mmss_config_t conf = {};
|
||||
context_t mmss;
|
||||
config_t conf = {};
|
||||
|
||||
mmss_read_config(&mmss, &conf, "babel_test.mmss");
|
||||
read_config(&mmss, &conf, "babel_test.mmss");
|
||||
|
||||
mmss_network_t net0 = { .mtu = 1500 }, net1 = { .mtu = 1500 };
|
||||
network_t net0 = { .mtu = 1500 }, net1 = { .mtu = 1500 };
|
||||
gmrf_t node1 = { .name = strdup("node1"), .mmss = &mmss, .rand_seed = 1, .proto = proto };
|
||||
gmrf_t node2 = { .name = strdup("node2"), .mmss = &mmss, .rand_seed = 2, .proto = proto };
|
||||
gmrf_t node3 = { .name = strdup("node3"), .mmss = &mmss, .rand_seed = 3, .proto = proto };
|
||||
|
@ -94,10 +97,10 @@ int main(int argc, char *argv[]) {
|
|||
init_nodes(nodes);
|
||||
|
||||
gmrf_addr_t addr1 = {{1}}, addr2 = {{2}}, addr3 = {{3}}, addr4 = {{4}};
|
||||
mmss_add_iface(&node1, &net0, "mmss0", &addr1);
|
||||
mmss_add_iface(&node2, &net0, "mmss0", &addr2);
|
||||
mmss_add_iface(&node2, &net1, "mmss1", &addr3);
|
||||
mmss_add_iface(&node3, &net1, "mmss1", &addr4);
|
||||
add_iface(&node1, &net0, "mmss0", &addr1);
|
||||
add_iface(&node2, &net0, "mmss0", &addr2);
|
||||
add_iface(&node2, &net1, "mmss1", &addr3);
|
||||
add_iface(&node3, &net1, "mmss1", &addr4);
|
||||
|
||||
while (true) {
|
||||
int timeout = get_queue_timeout(&mmss);
|
||||
|
@ -108,8 +111,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
assert(!mmss_queue_get(&mmss, &mmss.packet_queue));
|
||||
assert(!mmss_queue_get(&mmss, &mmss.scheduled_queue));
|
||||
assert(!mmss.packet_queue.get());
|
||||
assert(!mmss.scheduled_queue.get());
|
||||
|
||||
mmss.now += timeout;
|
||||
timeout = get_queue_timeout(&mmss);
|
||||
|
@ -118,20 +121,26 @@ int main(int argc, char *argv[]) {
|
|||
assert(timeout == 0);
|
||||
|
||||
while (timeout == 0) {
|
||||
mmss_packet_t *packet = reinterpret_cast<mmss_packet_t*>(mmss_queue_get(&mmss, &mmss.packet_queue));
|
||||
mmss_scheduled_t *scheduled = reinterpret_cast<mmss_scheduled_t*>(mmss_queue_get(&mmss, &mmss.scheduled_queue));
|
||||
std::shared_ptr<packet_t> packet = mmss.packet_queue.get();
|
||||
std::shared_ptr<scheduled_t> scheduled = mmss.scheduled_queue.get();
|
||||
|
||||
assert(packet || scheduled);
|
||||
|
||||
if (packet)
|
||||
mmss_dispatch(packet);
|
||||
dispatch(packet);
|
||||
|
||||
if (scheduled)
|
||||
mmss_run_scheduled(scheduled);
|
||||
run_scheduled(scheduled);
|
||||
|
||||
timeout = get_queue_timeout(&mmss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
MMSS::main(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
133
mmss/mmss.hpp
133
mmss/mmss.hpp
|
@ -24,34 +24,34 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef _GMRF_MMSS_MMSS_H_
|
||||
#define _GMRF_MMSS_MMSS_H_
|
||||
#ifndef _GMRF_MMSS_MMSS_HPP_
|
||||
#define _GMRF_MMSS_MMSS_HPP_
|
||||
|
||||
#include "queue.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <memory>
|
||||
|
||||
#include <gmrf/gmrf.h>
|
||||
#include <mmss/protocol.h>
|
||||
|
||||
}
|
||||
namespace MMSS {
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
struct mmss {
|
||||
class context_t {
|
||||
public:
|
||||
uint64_t now;
|
||||
mmss_queue_t packet_queue;
|
||||
mmss_queue_t scheduled_queue;
|
||||
timeout_queue_t<packet_t> packet_queue;
|
||||
timeout_queue_t<scheduled_t> scheduled_queue;
|
||||
|
||||
context_t() : now(0), packet_queue(this), scheduled_queue(this) {}
|
||||
};
|
||||
|
||||
struct mmss_config {
|
||||
mmss_network_t *networks;
|
||||
class config_t {
|
||||
public:
|
||||
network_t *networks;
|
||||
gmrf_t *nodes;
|
||||
};
|
||||
|
||||
struct mmss_network {
|
||||
mmss_network_t *next;
|
||||
class network_t {
|
||||
public:
|
||||
network_t *next;
|
||||
|
||||
char *name;
|
||||
|
||||
|
@ -59,66 +59,43 @@ struct mmss_network {
|
|||
size_t mtu;
|
||||
};
|
||||
|
||||
struct mmss_packet {
|
||||
class packet_t {
|
||||
public:
|
||||
uint64_t sent;
|
||||
|
||||
gmrf_iface_t *source;
|
||||
gmrf_iface_t *dest;
|
||||
|
||||
size_t len;
|
||||
uint8_t data[];
|
||||
std::unique_ptr<uint8_t> data;
|
||||
};
|
||||
|
||||
struct mmss_scheduled {
|
||||
class scheduled_t {
|
||||
public:
|
||||
gmrf_t *node;
|
||||
gmrf_scheduled_func f;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct mmss_string_stack {
|
||||
mmss_string_stack_t *next;
|
||||
char str[];
|
||||
};
|
||||
|
||||
const protocol_t* load_protocol(const char *module);
|
||||
|
||||
struct gmrf {
|
||||
gmrf_t *next;
|
||||
namespace Config {
|
||||
|
||||
char *name;
|
||||
void add_network(context_t *mmss, config_t *conf, const char *name);
|
||||
|
||||
mmss_t *mmss;
|
||||
gmrf_context_t *ctx;
|
||||
gmrf_iface_t *interfaces;
|
||||
}
|
||||
|
||||
unsigned rand_seed;
|
||||
bool read_config(context_t *mmss, config_t *conf, const char *filename);
|
||||
|
||||
const mmss_protocol_t *proto;
|
||||
};
|
||||
void add_iface(gmrf_t *node, network_t *net, const char *name, const gmrf_addr_t *address);
|
||||
|
||||
struct gmrf_iface {
|
||||
gmrf_iface_t *node_next;
|
||||
gmrf_iface_t *network_next;
|
||||
uint64_t now(const context_t *mmss);
|
||||
|
||||
char *name;
|
||||
gmrf_addr_t address;
|
||||
void dispatch(std::shared_ptr<packet_t> packet);
|
||||
void run_scheduled(std::shared_ptr<scheduled_t> scheduled);
|
||||
|
||||
gmrf_t *node;
|
||||
mmss_network_t *net;
|
||||
};
|
||||
|
||||
|
||||
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_dispatch(mmss_packet_t *packet);
|
||||
void mmss_run_scheduled(mmss_scheduled_t *scheduled);
|
||||
|
||||
void mmss_logf(mmss_t *mmss, int priority, const char *format, ...);
|
||||
void logf(context_t *mmss, int priority, const char *format, ...);
|
||||
|
||||
|
||||
static inline int max(int a, int b) {
|
||||
|
@ -134,39 +111,31 @@ 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;
|
||||
struct gmrf {
|
||||
gmrf_t *next;
|
||||
|
||||
return ret;
|
||||
}
|
||||
char *name;
|
||||
|
||||
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);
|
||||
MMSS::context_t *mmss;
|
||||
gmrf_context_t *ctx;
|
||||
gmrf_iface_t *interfaces;
|
||||
|
||||
return ret;
|
||||
}
|
||||
unsigned rand_seed;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
const MMSS::protocol_t *proto;
|
||||
};
|
||||
|
||||
struct gmrf_iface {
|
||||
gmrf_iface_t *node_next;
|
||||
gmrf_iface_t *network_next;
|
||||
|
||||
#endif /* _GMRF_MMSS_MMSS_H_ */
|
||||
char *name;
|
||||
gmrf_addr_t address;
|
||||
|
||||
gmrf_t *node;
|
||||
MMSS::network_t *net;
|
||||
};
|
||||
|
||||
#endif /* _GMRF_MMSS_MMSS_HPP_ */
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
#include <cstdio>
|
||||
|
||||
|
||||
const mmss_protocol_t* mmss_load_protocol(const char *module) {
|
||||
namespace MMSS {
|
||||
|
||||
const protocol_t* load_protocol(const char *module) {
|
||||
void *handle = dlopen(module, RTLD_NOW);
|
||||
if (!handle) {
|
||||
fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
|
||||
|
@ -38,7 +40,7 @@ const mmss_protocol_t* mmss_load_protocol(const char *module) {
|
|||
}
|
||||
|
||||
dlerror();
|
||||
const mmss_protocol_t *proto = reinterpret_cast<const mmss_protocol_t*>(dlsym(handle, "mmss_protocol_info"));
|
||||
const protocol_t *proto = reinterpret_cast<const protocol_t*>(dlsym(handle, "mmss_protocol_info"));
|
||||
if (!proto) {
|
||||
fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
|
||||
dlclose(handle);
|
||||
|
@ -49,3 +51,5 @@ const mmss_protocol_t* mmss_load_protocol(const char *module) {
|
|||
|
||||
return proto;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
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 "queue.hpp"
|
||||
#include "mmss.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
typedef struct mmss_queue_entry mmss_queue_entry_t;
|
||||
|
||||
struct mmss_queue_entry {
|
||||
mmss_queue_entry_t *next;
|
||||
uint64_t timeout;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
void mmss_queue_put(mmss_t *mmss, mmss_queue_t *queue, void *data, uint64_t timeout) {
|
||||
while (*queue && timeout >= (*queue)->timeout)
|
||||
queue = &(*queue)->next;
|
||||
|
||||
mmss_queue_entry_t *entry = new mmss_queue_entry_t;
|
||||
|
||||
entry->timeout = timeout;
|
||||
entry->data = data;
|
||||
|
||||
entry->next = *queue;
|
||||
*queue = entry;
|
||||
}
|
||||
|
||||
void* mmss_queue_get(mmss_t *mmss, mmss_queue_t *queue) {
|
||||
mmss_queue_entry_t *entry = *queue;
|
||||
|
||||
if (!entry || entry->timeout > mmss->now)
|
||||
return NULL;
|
||||
|
||||
*queue = entry->next;
|
||||
void *data = entry->data;
|
||||
free(entry);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int mmss_queue_timeout(const mmss_t *mmss, const mmss_queue_t *const queue) {
|
||||
if (!*queue)
|
||||
return -1;
|
||||
|
||||
int diff = (*queue)->timeout - mmss->now;
|
||||
|
||||
if (diff < 0)
|
||||
return 0;
|
||||
else
|
||||
return diff;
|
||||
}
|
|
@ -24,19 +24,61 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef _GMRF_MMSS_QUEUE_H_
|
||||
#define _GMRF_MMSS_QUEUE_H_
|
||||
#ifndef _GMRF_MMSS_QUEUE_HPP_
|
||||
#define _GMRF_MMSS_QUEUE_HPP_
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
namespace MMSS {
|
||||
|
||||
typedef struct mmss_queue_entry *mmss_queue_t;
|
||||
template<typename T> class timeout_queue_t {
|
||||
struct element_t {
|
||||
std::shared_ptr<T> data;
|
||||
uint64_t timeout;
|
||||
|
||||
element_t(std::shared_ptr<T> data0, uint64_t timeout0) : data(data0), timeout(timeout0) {}
|
||||
|
||||
void mmss_queue_put(mmss_t *mmss, mmss_queue_t *queue, void *data, uint64_t timeout);
|
||||
void* mmss_queue_get(mmss_t *mmss, mmss_queue_t *queue);
|
||||
int mmss_queue_timeout(const mmss_t *mmss, const mmss_queue_t *const queue);
|
||||
bool operator<(const element_t &e) const {
|
||||
return timeout < e.timeout;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _GMRF_MMSS_QUEUE_H_ */
|
||||
context_t *mmss;
|
||||
|
||||
std::priority_queue<element_t> queue;
|
||||
|
||||
public:
|
||||
timeout_queue_t(context_t *mmss0) : mmss(mmss0) {}
|
||||
|
||||
void put(std::shared_ptr<T> data, uint64_t timeout) {
|
||||
queue.push(element_t(data, timeout));
|
||||
}
|
||||
|
||||
std::shared_ptr<T> get() {
|
||||
if (queue.empty() || queue.top().timeout > now(mmss))
|
||||
return std::shared_ptr<T>();
|
||||
|
||||
std::shared_ptr<T> ret = queue.top().data;
|
||||
queue.pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int timeout() const {
|
||||
if (queue.empty())
|
||||
return -1;
|
||||
|
||||
int diff = queue.top().timeout - now(mmss);
|
||||
|
||||
if (diff < 0)
|
||||
return 0;
|
||||
else
|
||||
return diff;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _GMRF_MMSS_QUEUE_HPP_ */
|
||||
|
|
|
@ -27,17 +27,20 @@
|
|||
#include "mmss.hpp"
|
||||
|
||||
|
||||
namespace MMSS {
|
||||
|
||||
void run_scheduled(std::shared_ptr<scheduled_t> scheduled) {
|
||||
scheduled->f(scheduled->node, scheduled->node->ctx, scheduled->arg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned delay) {
|
||||
mmss_scheduled_t *scheduled = new mmss_scheduled_t;
|
||||
std::shared_ptr<MMSS::scheduled_t> scheduled = std::make_shared<MMSS::scheduled_t>();
|
||||
|
||||
scheduled->node = gmrf;
|
||||
scheduled->f = f;
|
||||
scheduled->arg = arg;
|
||||
|
||||
mmss_queue_put(gmrf->mmss, &gmrf->mmss->scheduled_queue, scheduled, gmrf->mmss->now+delay);
|
||||
}
|
||||
|
||||
void mmss_run_scheduled(mmss_scheduled_t *scheduled) {
|
||||
scheduled->f(scheduled->node, scheduled->node->ctx, scheduled->arg);
|
||||
delete scheduled;
|
||||
gmrf->mmss->scheduled_queue.put(scheduled, gmrf->mmss->now+delay);
|
||||
}
|
||||
|
|
|
@ -24,19 +24,30 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef _GMRF_MMSS_TYPES_H_
|
||||
#define _GMRF_MMSS_TYPES_H_
|
||||
#ifndef _GMRF_MMSS_TYPES_HPP_
|
||||
#define _GMRF_MMSS_TYPES_HPP_
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
typedef struct mmss mmss_t;
|
||||
typedef struct mmss_config mmss_config_t;
|
||||
typedef struct mmss_network mmss_network_t;
|
||||
typedef struct mmss_packet mmss_packet_t;
|
||||
typedef struct mmss_scheduled mmss_scheduled_t;
|
||||
extern "C" {
|
||||
|
||||
typedef struct mmss_string_stack mmss_string_stack_t;
|
||||
#include <gmrf/gmrf.h>
|
||||
#include <mmss/protocol.h>
|
||||
|
||||
#endif /* _GMRF_MMSS_TYPES_H_ */
|
||||
}
|
||||
|
||||
namespace MMSS {
|
||||
|
||||
class context_t;
|
||||
class config_t;
|
||||
class network_t;
|
||||
class packet_t;
|
||||
class scheduled_t;
|
||||
|
||||
typedef ::mmss_protocol_t protocol_t;
|
||||
|
||||
}
|
||||
|
||||
#endif /* _GMRF_MMSS_TYPES_HPP_ */
|
||||
|
|
Reference in a new issue