diff options
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | include/salticidae/event.h | 25 | ||||
-rw-r--r-- | include/salticidae/msg.h | 15 | ||||
-rw-r--r-- | include/salticidae/network.h | 18 | ||||
-rw-r--r-- | include/salticidae/stream.h | 16 | ||||
-rw-r--r-- | include/salticidae/type.h | 27 | ||||
-rw-r--r-- | src/event.cpp | 24 | ||||
-rw-r--r-- | src/msg.cpp | 23 | ||||
-rw-r--r-- | src/network.cpp | 22 | ||||
-rw-r--r-- | src/stream.cpp | 27 | ||||
-rw-r--r-- | src/type.cpp | 20 | ||||
-rw-r--r-- | test/test_msgnet_c.c | 128 |
12 files changed, 270 insertions, 84 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 29ea67d..e0bcae2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,11 +31,14 @@ find_package(OpenSSL REQUIRED) include_directories(include) add_library(salticidae OBJECT + src/type.cpp src/util.cpp - src/conn.cpp - src/network.cpp + src/event.cpp src/stream.cpp - src/netaddr.cpp) + src/msg.cpp + src/netaddr.cpp + src/conn.cpp + src/network.cpp) option(BUILD_SHARED "build shared library." OFF) if(BUILD_SHARED) diff --git a/include/salticidae/event.h b/include/salticidae/event.h index 19bd250..27d081a 100644 --- a/include/salticidae/event.h +++ b/include/salticidae/event.h @@ -645,9 +645,34 @@ class ThreadCall { } +#ifdef SALTICIDAE_CBINDINGS using eventcontext_t = salticidae::EventContext; +using sigev_t = salticidae::SigEvent; +#endif #else + +#ifdef SALTICIDAE_CBINDINGS typedef struct eventcontext_t; +typedef struct sigevent_t; +#endif + #endif + +#ifdef SALTICIDAE_CBINDINGS +extern "C" { + +eventcontext_t *eventcontext_new(); +void eventcontext_dispatch(eventcontext_t *self); +void eventcontext_stop(eventcontext_t *self); +void eventcontext_free(eventcontext_t *self); + +typedef void (*sigev_callback_t)(int fd, int events); +sigev_t *sigev_new(const eventcontext_t *self, sigev_callback_t cb); +void sigev_add(sigev_t *self, int sig); +void sigev_free(sigev_t *self); + +} +#endif + #endif diff --git a/include/salticidae/msg.h b/include/salticidae/msg.h index 128e287..6964ab2 100644 --- a/include/salticidae/msg.h +++ b/include/salticidae/msg.h @@ -267,14 +267,27 @@ const size_t MsgBase<OpcodeType>::header_size = 0; } +#ifdef SALTICIDAE_CBINDINGS using msg_t = salticidae::MsgBase<_opcode_t>; +#endif + #else + +#ifdef SALTICIDAE_CBINDINGS typedef struct msg_t msg_t; #endif +#endif + +#ifdef SALTICIDAE_CBINDINGS extern "C" { -void msg_new(); +msg_t *msg_new(_opcode_t opcode, bytearray_t *_moved_payload); +datastream_t *msg_get_payload(msg_t *msg); +const _opcode_t &msg_get_opcode(const msg_t *msg); +void msg_free(msg_t *msg); + } +#endif #endif diff --git a/include/salticidae/network.h b/include/salticidae/network.h index 12fe720..b176b65 100644 --- a/include/salticidae/network.h +++ b/include/salticidae/network.h @@ -782,22 +782,28 @@ const O PeerNetwork<O, _, OPCODE_PONG>::MsgPong::opcode = OPCODE_PONG; } +#ifdef SALTICIDAE_CBINDINGS using msgnetwork_t = salticidae::MsgNetwork<_opcode_t>; using msgnetwork_config_t = msgnetwork_t::Config; using msgnetwork_conn_t = msgnetwork_t::conn_t; +#endif #else + +#ifdef SALTICIDAE_CBINDINGS typedef struct msg_t; typedef struct msgnetwork_t; typedef struct msgnetwork_config_t; typedef struct msgnetwork_conn_t; #endif +#endif + +#ifdef SALTICIDAE_CBINDINGS extern "C" { void salticidae_injected_msg_callback(const msg_t *msg, msgnetwork_conn_t *conn); -msg_t _test_create_msg(); msgnetwork_t *msgnetwork_new(const eventcontext_t *ec, const msgnetwork_config_t *config); bool msgnetwork_send_msg(msgnetwork_t *self, const msg_t *msg, const msgnetwork_conn_t *conn); @@ -806,13 +812,21 @@ msgnetwork_conn_t *msgnetwork_connect(msgnetwork_t *self, const netaddr_t *addr) void msgnetwork_listen(msgnetwork_t *self, const netaddr_t *listen_addr); -typedef void (*msgnetwork_msg_callback_t)(const msg_t *msg, const msgnetwork_conn_t *conn); +typedef void (*msgnetwork_msg_callback_t)(const msg_t *, const msgnetwork_conn_t *); #ifdef SALTICIDAE_CBINDINGS_STR_OP void msgnetwork_reg_handler(msgnetwork_t *self, const char *opcode, msgnetwork_msg_callback_t cb); #else void msgnetwork_reg_handler(msgnetwork_t *self, uint8_t opcode, msgnetwork_msg_callback_t cb); #endif + +typedef void (*msgnetwork_conn_callback_t)(const msgnetwork_conn_t *, bool); + +void msgnetwork_reg_conn_handler(msgnetwork_t *self, msgnetwork_conn_callback_t cb); + +msgnetwork_t *msgnetwork_conn_get_net(const msgnetwork_conn_t *conn); + } +#endif #endif diff --git a/include/salticidae/stream.h b/include/salticidae/stream.h index 9eda2bd..e146273 100644 --- a/include/salticidae/stream.h +++ b/include/salticidae/stream.h @@ -467,14 +467,21 @@ namespace std { }; } +#ifdef SALTICIDAE_CBINDINGS using uint256_t = salticidae::uint256_t; using datastream_t = salticidae::DataStream; +#endif #else + +#ifdef SALTICIDAE_CBINDINGS typedef struct datastream_t; typedef struct uint256_t; #endif +#endif + +#ifdef SALTICIDAE_CBINDINGS extern "C" { uint256_t *uint256_new(); @@ -499,8 +506,17 @@ void datastream_put_i16(datastream_t *self, int16_t val); void datastream_put_i32(datastream_t *self, int32_t val); void datastream_put_data(datastream_t *self, uint8_t *begin, uint8_t *end); + +uint8_t datastream_get_u8(datastream_t *self); +uint16_t datastream_get_u16(datastream_t *self); +uint32_t datastream_get_u32(datastream_t *self); +int8_t datastream_get_i8(datastream_t *self); +int16_t datastream_get_i16(datastream_t *self); +int32_t datastream_get_i32(datastream_t *self); const uint8_t *datastream_get_data_inplace(datastream_t *self, size_t len); uint256_t *datastream_get_hash(const datastream_t *self); } #endif + +#endif diff --git a/include/salticidae/type.h b/include/salticidae/type.h index 3ec202a..0ebcce7 100644 --- a/include/salticidae/type.h +++ b/include/salticidae/type.h @@ -35,6 +35,9 @@ #include <functional> #include <mutex> +#include "config.h" + +#ifdef __cplusplus namespace salticidae { const auto _1 = std::placeholders::_1; @@ -89,10 +92,32 @@ inline auto generic_bind(ReturnType(ClassType::* f)(Args...), FArgs&&... fargs) } +#ifdef SALTICIDAE_CBINDINGS +using bytearray_t = salticidae::bytearray_t; +#endif + +#else + +#ifdef SALTICIDAE_CBINDINGS +typedef struct bytearray_t bytearray_t; +#endif + +#endif + #ifdef SALTICIDAE_CBINDINGS_STR_OP -using _opcode_t = std::string; +using _opcode_t = char *; #else using _opcode_t = uint8_t; #endif +#ifdef SALTICIDAE_CBINDINGS +extern "C" { + +uint8_t *bytearray_data(bytearray_t *arr); +size_t bytearray_size(bytearray_t *arr); +void bytearray_free(); + +} +#endif + #endif diff --git a/src/event.cpp b/src/event.cpp new file mode 100644 index 0000000..050914c --- /dev/null +++ b/src/event.cpp @@ -0,0 +1,24 @@ +#ifdef SALTICIDAE_CBINDINGS +#include "salticidae/event.h" + +extern "C" { + +eventcontext_t *eventcontext_new() { return new eventcontext_t(); } + +void eventcontext_dispatch(eventcontext_t *self) { return self->dispatch(); } + +void eventcontext_stop(eventcontext_t *self) { return self->stop(); } + +void eventcontext_free(eventcontext_t *self) { delete self; } + +void sigev_new(const eventcontext_t *self, sigev_callback_t cb) { + return new SigEvent(*self, cb); +} + +void sigev_add(sigev_t *self, int sig) { self->add(sig); } + +void sigev_delete() { delete self; } + +} + +#endif diff --git a/src/msg.cpp b/src/msg.cpp index e69de29..e75d7d4 100644 --- a/src/msg.cpp +++ b/src/msg.cpp @@ -0,0 +1,23 @@ +#ifdef SALTICIDAE_CBINDINGS +#include "salticidae/msg.h" + +extern "C" { + +msg_t *msg_new(_opcode_t opcode, bytearray_t *_moved_payload) { + auto res = new msg_t(opcode, *payload); + bytearray_free(payload); +} + +datastream_t *msg_get_payload(msg_t *msg) { + return new datastream_t(msg->get_payload()); +} + +const _opcode_t msg_get_opcode(const msg_t *msg) { + return msg->get_opcode(); +} + +void msg_free(msg_t *msg) { delete msg; } + +} + +#endif diff --git a/src/network.cpp b/src/network.cpp index cefe723..0b12131 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -1,16 +1,11 @@ -#include "salticidae/network.h" #ifdef SALTICIDAE_CBINDINGS +#include "salticidae/network.h" using namespace salticidae; extern "C" { -msg_t _test_create_msg() { - return msg_t(0x0, bytearray_t()); -} - - -msgnetwork_t *msgnetwork_new(const EventContext *ec, const msgnetwork_config_t *config) { +msgnetwork_t *msgnetwork_new(const eventcontext_t *ec, const msgnetwork_config_t *config) { return new msgnetwork_t(*ec, *config); } @@ -47,6 +42,19 @@ void msgnetwork_reg_handler(msgnetwork_t *self, } #endif +void msgnetwork_reg_conn_handler(msgnetwork_t *self, msgnetwork_conn_callback_t cb) { + self->reg_conn_handler([cb](const ConnPool::conn_t &_conn, bool connected) { + auto conn = salticidae::static_pointer_cast<msgnetwork_t::Conn>(_conn); + cb(&conn, connected); + }); +} + +msgnetwork_t *msgnetwork_conn_get_net(const msgnetwork_conn_t *conn) { + return (*conn)->get_net(); +} + +void msgnetwork_start(msgnetwork_t *self) { self->start(); } + } #endif diff --git a/src/stream.cpp b/src/stream.cpp index 8846414..f3dd322 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -1,9 +1,8 @@ +#ifdef SALTICIDAE_CBINDINGS #include "salticidae/stream.h" using namespace salticidae; -#ifdef __cplusplus - extern "C" { uint256_t *uint256_new() { return new uint256_t(); } @@ -56,6 +55,30 @@ void datastream_put_data(datastream_t *self, self->put_data(begin, end); } +uint8_t datastream_get_u8(datastream_t *self) { + uint8_t val; *self >> val; return val; +} + +uint16_t datastream_get_u16(datastream_t *self) { + uint16_t val; *self >> val; return val; +} + +uint32_t datastream_get_u32(datastream_t *self) { + uint32_t val; *self >> val; return val; +} + +int8_t datastream_get_i8(datastream_t *self) { + int8_t val; *self >> val; return val; +} + +int16_t datastream_get_i16(datastream_t *self) { + int16_t val; *self >> val; return val; +} + +int32_t datastream_get_i32(datastream_t *self) { + int32_t val; *self >> val; return val; +} + const uint8_t *datastream_get_data_inplace(datastream_t *self, size_t len) { return self->get_data_inplace(len); } diff --git a/src/type.cpp b/src/type.cpp new file mode 100644 index 0000000..8290a07 --- /dev/null +++ b/src/type.cpp @@ -0,0 +1,20 @@ +#ifdef SALTICIDAE_CBINDINGS +#include "salticidae/type.h" + +extern "C" { + +uint8_t *bytearray_data(bytearray_t *arr) { + return &(*arr)[0]; +} + +size_t bytearray_size(bytearray_t *arr) { + return arr->size(); +} + +void bytearray_free(bytearray_t *arr) { + delete arr; +} + +} + +#endif diff --git a/test/test_msgnet_c.c b/test/test_msgnet_c.c index 1098e19..b6ba5a0 100644 --- a/test/test_msgnet_c.c +++ b/test/test_msgnet_c.c @@ -36,73 +36,81 @@ typedef struct MsgHello { const char *text; } MsgHello; /** Defines how to serialize the msg. */ -datastream_t msg_hello_serialize(const char *name, const char *text) { - datastream_t *serialized = msgnet_ +datastream_t *msg_hello_serialize(const char *name, const char *text) { + datastream_t *serialized = datastream_new(); serialized << htole((uint32_t)name.length()); serialized << name << text; + return serialized; } /** Defines how to parse the msg. */ -MsgHello MsgHello(DataStream &&s) { +MsgHello msg_hello_unserialize(datastream_t *s) { MsgHello res; uint32_t len; - s >> len; + len = datastream_get_u32(s); len = letoh(len); - res.name = std::string((const char *)s.get_data_inplace(len), len); - len = s.size(); - res.text = std::string((const char *)s.get_data_inplace(len), len); - return res; -} -/** Acknowledgement Message. */ -struct MsgAck { - static const uint8_t opcode = 0x1; - DataStream serialized; - MsgAck() {} - MsgAck(DataStream &&s) {} -}; + const char *name = (const char *)malloc(len + 1); + memmove(name, datastream_get_data_inplace(s, len), len); + name[len] = 0; -const uint8_t MsgHello::opcode; -const uint8_t MsgAck::opcode; + len = datastream_size(s); + const char *text = (const char *)malloc(len + 1); + memmove(text, datastream_get_data_inplace(s, len), len); + text[len] = 0; -using MsgNetworkByteOp = MsgNetwork<uint8_t>; + res.name = name; + res.text = text; + return res; +} + +datastream_t *msg_ack_serialize() { return datastream_new(); } -typedef struct MyNet { +struct MyNet { msgnetwork_t *net; - const std::string name; + const char *name; const NetAddr peer; -} MyNet; +} alice, bob; -void msg_hello_handler(const msg_t *msg, const msgnetwork_conn_t *conn) { +void on_receive_hello(const msg_t *msg, const msgnetwork_conn_t *conn) { + msgnetwork_t *net = msgnetwork_conn_get_net(conn); + printf("[%s] %s says %s\n", name, msg.name, msg.text); + msg_t *msg = msg_new(0x1, msg_ack_serialize()); + /* send acknowledgement */ + send_msg(msg, conn); + msg_free(msg); } -void msg_ack_handler(const msg_t *msg, const msgnetwork_conn_t *conn) { +void on_receive_ack(const msg_t *msg, const msgnetwork_conn_t *conn) { + auto net = static_cast<MyNet *>(conn->get_net()); + printf("[%s] the peer knows\n", net->name.c_str()); } -void alice_conn_handler(const msgnetwork_conn_t *conn, bool connected) { +void conn_handler(const msgnetwork_conn_t *conn, bool connected) { + msgnetwork_t *net = msgnetwork_conn_get_net(conn); + const char *name = net == alice.net ? alice.name : bob.name; if (connected) { if (conn->get_mode() == ConnPool::Conn::ACTIVE) { - puts("[alice] Connected, sending hello."); + puts("[%s] Connected, sending hello.", name); /* send the first message through this connection */ msgnetwork_send_msg(alice, msg_hello_serialize("alice", "Hello there!"), conn); } else - printf("[alice] Accepted, waiting for greetings.\n", - this->name.c_str()); + printf("[%s] Accepted, waiting for greetings.\n", name); } else { - printf("[alice] Disconnected, retrying.\n", this->name.c_str()); + printf("[%s] Disconnected, retrying.\n", name); /* try to reconnect to the same address */ connect(conn->get_addr()); } } -MyNet mynet_new(const salticidae::EventContext &ec, +MyNet gen_mynet(const eventcontext_t *ec, const char *name, const netaddr_t *peer) { MyNet res; @@ -110,62 +118,46 @@ MyNet mynet_new(const salticidae::EventContext &ec, res.net = msgnetwork_new(ec, netconfig); res.name = name; res.peer = peer; - - /* message handler could be a bound method */ - reg_handler(salticidae::generic_bind(&MyNet::on_receive_hello, this, _1, _2)); - - reg_conn_handler([this](const ConnPool::conn_t &conn, bool connected) { - }); - } - - void on_receive_hello(MsgHello &&msg, const MyNet::conn_t &conn) { - printf("[%s] %s says %s\n", - name.c_str(), - msg.name.c_str(), msg.text.c_str()); - /* send acknowledgement */ - send_msg(MsgAck(), conn); - } }; -void on_receive_ack(MsgAck &&msg, const MyNet::conn_t &conn) { - auto net = static_cast<MyNet *>(conn->get_net()); - printf("[%s] the peer knows\n", net->name.c_str()); +void on_term_signal(int) { + ec.stop(); } int main() { - salticidae::EventContext ec; - NetAddr alice_addr("127.0.0.1:12345"); - NetAddr bob_addr("127.0.0.1:12346"); + eventcontext_t *ec = eventcontext_new(); + netaddr_t *alice_addr = netaddr_new_from_sipport("127.0.0.1:12345"); + netaddr_t *bob_addr = netaddr_new_from_sipport("127.0.0.1:12346"); /* test two nodes in the same main loop */ - MyNet alice(ec, "Alice", bob_addr); - MyNet bob(ec, "Bob", alice_addr); + alice = gen_mynet(ec, "Alice", bob_addr); + bob = gen_mynet(ec, "Bob", alice_addr); - /* message handler could be a normal function */ - alice.reg_handler(on_receive_ack); - bob.reg_handler(on_receive_ack); + msgnetwork_reg_handler(alice.net, MSG_OPCODE_HELLO, on_receive_hello); + msgnetwork_reg_handler(alice.net, MSG_OPCODE_HELLO, on_receive_hello); + msgnetwork_reg_handler(bob.net, MSG_OPCODE_HELLO, on_receive_hello); + msgnetwork_reg_handler(bob.net, MSG_OPCODE_HELLO, on_receive_hello); /* start all threads */ - alice.start(); - bob.start(); + msgnetwork_start(alice.net); + msgnetwork_start(bob.net); /* accept incoming connections */ - alice.listen(alice_addr); - bob.listen(bob_addr); + msgnetwork_listen(alice_addr); + msgnetwork_listen(bob_addr); /* try to connect once */ - alice.connect(bob_addr); - bob.connect(alice_addr); + msgnetwork_connect(bob_addr); + msgnetwork_connect(alice_addr); /* the main loop can be shutdown by ctrl-c or kill */ - auto shutdown = [&](int) {ec.stop();}; - salticidae::SigEvent ev_sigint(ec, shutdown); - salticidae::SigEvent ev_sigterm(ec, shutdown); - ev_sigint.add(SIGINT); - ev_sigterm.add(SIGTERM); + sigev_t *ev_sigint = sigev_new(ec, on_term_signal); + sigev_t *ev_sigterm = sigev_new(ec, on_term_signal); + sigev_add(ev_sigint, SIGINT); + sigev_add(ev_sigterm, SIGTERM); /* enter the main loop */ - ec.dispatch(); + eventcontext_dispatch(ec); return 0; } |