From 6c927588f78c663fded354fd696997d09fb5d697 Mon Sep 17 00:00:00 2001 From: Determinant Date: Fri, 14 Jun 2019 16:01:29 -0400 Subject: handle errors in C bindings --- include/salticidae/network.h | 8 ++-- include/salticidae/stream.h | 44 ++++++++++---------- include/salticidae/util.h | 40 ++++++++++++++---- src/network.cpp | 49 ++++++++++++++++++---- src/stream.cpp | 97 +++++++++++++++++++++++++++++--------------- src/util.cpp | 25 ++++++++++++ test/test_msgnet_c.c | 29 +++++++++---- 7 files changed, 210 insertions(+), 82 deletions(-) diff --git a/include/salticidae/network.h b/include/salticidae/network.h index fc33414..de7c32e 100644 --- a/include/salticidae/network.h +++ b/include/salticidae/network.h @@ -964,10 +964,10 @@ void msgnetwork_config_queue_capacity(msgnetwork_config_t *self, size_t cap); msgnetwork_t *msgnetwork_new(const eventcontext_t *ec, const msgnetwork_config_t *config); void msgnetwork_free(const msgnetwork_t *self); void msgnetwork_send_msg_by_move(msgnetwork_t *self, msg_t *_moved_msg, const msgnetwork_conn_t *conn); -msgnetwork_conn_t *msgnetwork_connect(msgnetwork_t *self, const netaddr_t *addr); +msgnetwork_conn_t *msgnetwork_connect(msgnetwork_t *self, const netaddr_t *addr, SalticidaeCError *err); msgnetwork_conn_t *msgnetwork_conn_copy(const msgnetwork_conn_t *self); void msgnetwork_conn_free(const msgnetwork_conn_t *self); -void msgnetwork_listen(msgnetwork_t *self, const netaddr_t *listen_addr); +void msgnetwork_listen(msgnetwork_t *self, const netaddr_t *listen_addr, SalticidaeCError *err); void msgnetwork_start(msgnetwork_t *self); void msgnetwork_terminate(msgnetwork_t *self, const msgnetwork_conn_t *conn); @@ -996,14 +996,14 @@ void peernetwork_free(const peernetwork_t *self); void peernetwork_add_peer(peernetwork_t *self, const netaddr_t *paddr); void peernetwork_del_peer(peernetwork_t *self, const netaddr_t *paddr); bool peernetwork_has_peer(const peernetwork_t *self, const netaddr_t *paddr); -const peernetwork_conn_t *peernetwork_get_peer_conn(const peernetwork_t *self, const netaddr_t *paddr); +const peernetwork_conn_t *peernetwork_get_peer_conn(const peernetwork_t *self, const netaddr_t *paddr, SalticidaeCError *cerror); msgnetwork_t *peernetwork_as_msgnetwork(peernetwork_t *self); msgnetwork_conn_t *msgnetwork_conn_new_from_peernetwork_conn(const peernetwork_conn_t *conn); peernetwork_conn_t *peernetwork_conn_copy(const peernetwork_conn_t *self); void peernetwork_conn_free(const peernetwork_conn_t *self); void peernetwork_send_msg_by_move(peernetwork_t *self, msg_t * _moved_msg, const netaddr_t *paddr); void peernetwork_multicast_msg_by_move(peernetwork_t *self, msg_t *_moved_msg, const netaddr_array_t *paddrs); -void peernetwork_listen(peernetwork_t *self, const netaddr_t *listen_addr); +void peernetwork_listen(peernetwork_t *self, const netaddr_t *listen_addr, SalticidaeCError *err); #ifdef __cplusplus } diff --git a/include/salticidae/stream.h b/include/salticidae/stream.h index cf007ac..37786b2 100644 --- a/include/salticidae/stream.h +++ b/include/salticidae/stream.h @@ -505,32 +505,32 @@ datastream_t *datastream_new(); datastream_t *datastream_new_from_bytes(const uint8_t *base, size_t size); void datastream_free(const datastream_t *self); -void datastream_assign_by_copy(datastream_t *dst, const datastream_t *src); -void datastream_assign_by_move(datastream_t *dst, datastream_t *_moved_src); +bool datastream_assign_by_copy(datastream_t *dst, const datastream_t *src); +bool datastream_assign_by_move(datastream_t *dst, datastream_t *_moved_src); uint8_t *datastream_data(datastream_t *self); void datastream_clear(datastream_t *self); size_t datastream_size(const datastream_t *self); -void datastream_put_u8(datastream_t *self, uint8_t val); -void datastream_put_u16(datastream_t *self, uint16_t val); -void datastream_put_u32(datastream_t *self, uint32_t val); -void datastream_put_u64(datastream_t *self, uint64_t val); - -void datastream_put_i8(datastream_t *self, int8_t val); -void datastream_put_i16(datastream_t *self, int16_t val); -void datastream_put_i32(datastream_t *self, int32_t val); -void datastream_put_i64(datastream_t *self, int64_t val); -void datastream_put_data(datastream_t *self, const uint8_t *base, size_t size); - -uint8_t datastream_get_u8(datastream_t *self); -uint16_t datastream_get_u16(datastream_t *self); -uint32_t datastream_get_u32(datastream_t *self); -uint64_t datastream_get_u64(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); -int64_t datastream_get_i64(datastream_t *self); +bool datastream_put_u8(datastream_t *self, uint8_t val); +bool datastream_put_u16(datastream_t *self, uint16_t val); +bool datastream_put_u32(datastream_t *self, uint32_t val); +bool datastream_put_u64(datastream_t *self, uint64_t val); + +bool datastream_put_i8(datastream_t *self, int8_t val); +bool datastream_put_i16(datastream_t *self, int16_t val); +bool datastream_put_i32(datastream_t *self, int32_t val); +bool datastream_put_i64(datastream_t *self, int64_t val); +bool datastream_put_data(datastream_t *self, const uint8_t *base, size_t size); + +uint8_t datastream_get_u8(datastream_t *self, bool *succ); +uint16_t datastream_get_u16(datastream_t *self, bool *succ); +uint32_t datastream_get_u32(datastream_t *self, bool *succ); +uint64_t datastream_get_u64(datastream_t *self, bool *succ); + +int8_t datastream_get_i8(datastream_t *self, bool *succ); +int16_t datastream_get_i16(datastream_t *self, bool *succ); +int32_t datastream_get_i32(datastream_t *self, bool *succ); +int64_t datastream_get_i64(datastream_t *self, bool *succ); const uint8_t *datastream_get_data_inplace(datastream_t *self, size_t len); uint256_t *datastream_get_hash(const datastream_t *self); diff --git a/include/salticidae/util.h b/include/salticidae/util.h index 41f681c..007fcc4 100644 --- a/include/salticidae/util.h +++ b/include/salticidae/util.h @@ -22,11 +22,32 @@ * SOFTWARE. */ -#ifndef _SALTICIDAE_COMMON_H -#define _SALTICIDAE_COMMON_H +#ifndef _SALTICIDAE_UTIL_H +#define _SALTICIDAE_UTIL_H + +#include +#include +#include +#include "salticidae/config.h" + +typedef struct SalticidaeCError { + int code; + int oscode; +} SalticidaeCError; + +#ifdef __cplusplus +extern "C" { +#endif + +SalticidaeCError salticidae_cerror_normal(); +SalticidaeCError salticidae_cerror_unknown(); +const char *salticidae_strerror(int code); #ifdef __cplusplus +} +#endif +#ifdef __cplusplus #include #include #include @@ -34,11 +55,6 @@ #include #include #include -#include -#include -#include - -#include "salticidae/config.h" #include "salticidae/ref.h" namespace salticidae { @@ -66,7 +82,8 @@ enum SalticidaeErrorCode { SALTI_ERROR_OPTNAME_ALREADY_EXISTS, SALTI_ERROR_OPT_UNKNOWN_ACTION, SALTI_ERROR_CONFIG_LINE_TOO_LONG, - SALTI_ERROR_OPT_INVALID + SALTI_ERROR_OPT_INVALID, + SALTI_ERROR_UNKNOWN }; extern const char *SALTICIDAE_ERROR_STRINGS[]; @@ -95,6 +112,12 @@ class SalticidaeError: public std::exception { const char *what() const throw() override { return msg.c_str(); } int get_code() const { return code; } int get_oscode() const { return oscode; } + SalticidaeCError get_cerr() const { + SalticidaeCError res; + res.code = code; + res.oscode = oscode; + return res; + } }; @@ -366,7 +389,6 @@ class Config { }; } - #endif #endif diff --git a/src/network.cpp b/src/network.cpp index 30ef0eb..91fc770 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -50,8 +50,17 @@ void msgnetwork_send_msg_by_move(msgnetwork_t *self, delete _moved_msg; } -msgnetwork_conn_t *msgnetwork_connect(msgnetwork_t *self, const netaddr_t *addr) { - return new msgnetwork_conn_t(self->connect(*addr)); +msgnetwork_conn_t *msgnetwork_connect(msgnetwork_t *self, const netaddr_t *addr, SalticidaeCError *cerror) { + try { + auto res = new msgnetwork_conn_t(self->connect(*addr)); + *cerror = salticidae_cerror_normal(); + return res; + } catch (const SalticidaeError &err) { + *cerror = err.get_cerr(); + } catch (const std::exception &err) { + *cerror = salticidae_cerror_unknown(); + } + return nullptr; } msgnetwork_conn_t *msgnetwork_conn_copy(const msgnetwork_conn_t *self) { @@ -61,8 +70,15 @@ msgnetwork_conn_t *msgnetwork_conn_copy(const msgnetwork_conn_t *self) { void msgnetwork_conn_free(const msgnetwork_conn_t *self) { delete self; } -void msgnetwork_listen(msgnetwork_t *self, const netaddr_t *listen_addr) { - self->listen(*listen_addr); +void msgnetwork_listen(msgnetwork_t *self, const netaddr_t *listen_addr, SalticidaeCError *cerror) { + try { + self->listen(*listen_addr); + *cerror = salticidae_cerror_normal(); + } catch (const SalticidaeError &err) { + *cerror = err.get_cerr(); + } catch (const std::exception &err) { + *cerror = salticidae_cerror_unknown(); + } } void msgnetwork_reg_handler(msgnetwork_t *self, @@ -143,8 +159,18 @@ bool peernetwork_has_peer(const peernetwork_t *self, const netaddr_t *paddr) { } const peernetwork_conn_t *peernetwork_get_peer_conn(const peernetwork_t *self, - const netaddr_t *paddr) { - return new peernetwork_conn_t(self->get_peer_conn(*paddr)); + const netaddr_t *paddr, + SalticidaeCError *cerror) { + try { + auto res = new peernetwork_conn_t(self->get_peer_conn(*paddr)); + *cerror = salticidae_cerror_normal(); + return res; + } catch (const SalticidaeError &err) { + *cerror = err.get_cerr(); + } catch (const std::exception &err) { + *cerror = salticidae_cerror_unknown(); + } + return nullptr; } msgnetwork_t *peernetwork_as_msgnetwork(peernetwork_t *self) { return self; } @@ -172,8 +198,15 @@ void peernetwork_multicast_msg_by_move(peernetwork_t *self, delete _moved_msg; } -void peernetwork_listen(peernetwork_t *self, const netaddr_t *listen_addr) { - self->listen(*listen_addr); +void peernetwork_listen(peernetwork_t *self, const netaddr_t *listen_addr, SalticidaeCError *cerror) { + try { + self->listen(*listen_addr); + *cerror = salticidae_cerror_normal(); + } catch (const SalticidaeError &err) { + *cerror = err.get_cerr(); + } catch (const std::exception &err) { + *cerror = salticidae_cerror_unknown(); + } } } diff --git a/src/stream.cpp b/src/stream.cpp index b14bd6a..fe715f1 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -23,19 +23,37 @@ void uint256_unserialize(uint256_t *self, datastream_t *s) { self->unserialize(*s); } -datastream_t *datastream_new() { return new datastream_t(); } +datastream_t *datastream_new() { + try { + return new datastream_t(); + } catch (...) { + return nullptr; + } +} + datastream_t *datastream_new_from_bytes(const uint8_t *base, size_t size) { - return new datastream_t(base, base + size); + try { + return new datastream_t(base, base + size); + } catch (...) { + return nullptr; + } } + void datastream_free(const datastream_t *self) { delete self; } -void datastream_assign_by_copy(datastream_t *dst, const datastream_t *src) { - *dst = *src; +bool datastream_assign_by_copy(datastream_t *dst, const datastream_t *src) { + try { + *dst = *src; + } catch (...) { return false; } + return true; } -void datastream_assign_by_move(datastream_t *dst, datastream_t *_moved_src) { - *dst = std::move(*_moved_src); - delete _moved_src; +bool datastream_assign_by_move(datastream_t *dst, datastream_t *_moved_src) { + try { + *dst = std::move(*_moved_src); + delete _moved_src; + } catch (...) { return false; } + return true; } uint8_t *datastream_data(datastream_t *self) { return self->data(); } @@ -44,42 +62,57 @@ void datastream_clear(datastream_t *self) { self->clear(); } size_t datastream_size(const datastream_t *self) { return self->size(); } -void datastream_put_u8(datastream_t *self, uint8_t val) { *self << val; } -void datastream_put_u16(datastream_t *self, uint16_t val) { *self << val; } -void datastream_put_u32(datastream_t *self, uint32_t val) { *self << val; } -void datastream_put_u64(datastream_t *self, uint64_t val) { *self << val; } - -void datastream_put_i8(datastream_t *self, int8_t val) { *self << val; } -void datastream_put_i16(datastream_t *self, int16_t val) { *self << val; } -void datastream_put_i32(datastream_t *self, int32_t val) { *self << val; } -void datastream_put_i64(datastream_t *self, int64_t val) { *self << val; } - -void datastream_put_data(datastream_t *self, const uint8_t *base, size_t size) { - self->put_data(base, base + size); +bool datastream_put_u8(datastream_t *self, uint8_t val) { try {*self << val; } catch (...) { return false; } return true; } +bool datastream_put_u16(datastream_t *self, uint16_t val) { try {*self << val; } catch (...) { return false; } return true; } +bool datastream_put_u32(datastream_t *self, uint32_t val) { try {*self << val; } catch (...) { return false; } return true; } +bool datastream_put_u64(datastream_t *self, uint64_t val) { try {*self << val; } catch (...) { return false; } return true; } + +bool datastream_put_i8(datastream_t *self, int8_t val) { try {*self << val; } catch (...) { return false; } return true; } +bool datastream_put_i16(datastream_t *self, int16_t val) { try {*self << val; } catch (...) { return false; } return true; } +bool datastream_put_i32(datastream_t *self, int32_t val) { try {*self << val; } catch (...) { return false; } return true; } +bool datastream_put_i64(datastream_t *self, int64_t val) { try {*self << val; } catch (...) { return false; } return true; } + +bool datastream_put_data(datastream_t *self, const uint8_t *base, size_t size) { + try { + self->put_data(base, base + size); + } catch (...) { return false; } + return true; } -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; } -uint64_t datastream_get_u64(datastream_t *self) { uint64_t val; *self >> val; return val; } +uint8_t datastream_get_u8(datastream_t *self, bool *succ) { uint8_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } +uint16_t datastream_get_u16(datastream_t *self, bool *succ) { uint16_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } +uint32_t datastream_get_u32(datastream_t *self, bool *succ) { uint32_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } +uint64_t datastream_get_u64(datastream_t *self, bool *succ) { uint64_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; 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; } -int64_t datastream_get_i64(datastream_t *self) { int64_t val; *self >> val; return val; } +int8_t datastream_get_i8(datastream_t *self, bool *succ) {int8_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } +int16_t datastream_get_i16(datastream_t *self, bool *succ) {int16_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } +int32_t datastream_get_i32(datastream_t *self, bool *succ) {int32_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } +int64_t datastream_get_i64(datastream_t *self, bool *succ) {int64_t val; try {*self >> val;} catch (...) {*succ = false;} *succ = true; return val; } const uint8_t *datastream_get_data_inplace(datastream_t *self, size_t len) { - return self->get_data_inplace(len); + try { + return self->get_data_inplace(len); + } catch (...) { + return nullptr; + } } uint256_t *datastream_get_hash(const datastream_t *self) { - return new uint256_t(self->get_hash()); + try { + return new uint256_t(self->get_hash()); + } catch (...) { + return nullptr; + } } bytearray_t *bytearray_new_moved_from_datastream(datastream_t *_moved_src) { - auto res = new bytearray_t(std::move(*_moved_src)); - delete _moved_src; - return res; + try { + auto res = new bytearray_t(std::move(*_moved_src)); + delete _moved_src; + return res; + } catch (...) { + return nullptr; + } } char *datastream_get_hex(datastream_t *self) { diff --git a/src/util.cpp b/src/util.cpp index f762b4c..874eb41 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -58,6 +58,31 @@ const char *TTY_COLOR_MAGENTA = "\x1b[35m"; const char *TTY_COLOR_CYAN = "\x1b[36m"; const char *TTY_COLOR_RESET = "\x1b[0m"; +extern "C" { + +SalticidaeCError salticidae_cerror_normal() { + SalticidaeCError res; + res.code = SALTI_NORMAL; + res.oscode = 0; + return res; +} + +SalticidaeCError salticidae_cerror_unknown() { + SalticidaeCError res; + res.code = SALTI_ERROR_UNKNOWN; + res.oscode = 0; + return res; +} + +const char *salticidae_strerror(int code) { + if (code < 0 || + code >= (int)(sizeof(SALTICIDAE_ERROR_STRINGS) / sizeof(const char *))) + return "invalid"; + return SALTICIDAE_ERROR_STRINGS[code]; +} + +} + void sec2tv(double t, struct timeval &tv) { tv.tv_sec = trunc(t); tv.tv_usec = trunc((t - tv.tv_sec) * 1e6); diff --git a/test/test_msgnet_c.c b/test/test_msgnet_c.c index 656bd80..b2fb35a 100644 --- a/test/test_msgnet_c.c +++ b/test/test_msgnet_c.c @@ -31,6 +31,14 @@ #include "salticidae/network.h" #include "salticidae/stream.h" +void check_err(SalticidaeCError *err) { + if (err->code) + { + fprintf(stderr, "error: %s\n", salticidae_strerror(err->code)); + exit(1); + } +} + /** Hello Message. */ const uint8_t MSG_OPCODE_HELLO = 0x0; const uint8_t MSG_OPCODE_ACK = 0x1; @@ -56,7 +64,8 @@ MsgHello msg_hello_unserialize(const msg_t *msg) { datastream_t *s = msg_consume_payload(msg); MsgHello res; uint32_t len; - len = datastream_get_u32(s); + bool flag; /* ignore the flag (assume all datastream operations are good) */ + len = datastream_get_u32(s, &flag); len = le32toh(len); char *name = (char *)malloc(len + 1); @@ -84,6 +93,7 @@ typedef struct MyNet { const char *name; } MyNet; MyNet alice, bob; +SalticidaeCError err; void on_receive_hello(const msg_t *_msg, const msgnetwork_conn_t *conn, void *userdata) { msgnetwork_t *net = msgnetwork_conn_get_net(conn); @@ -110,7 +120,7 @@ void conn_handler(const msgnetwork_conn_t *conn, bool connected, void *userdata) { if (msgnetwork_conn_get_mode(conn) == CONN_MODE_ACTIVE) { - printf("[%s] Connected, sending hello.", name); + printf("[%s] Connected, sending hello.\n", name); /* send the first message through this connection */ msg_t *hello = msg_hello_serialize(name, "Hello there!"); msgnetwork_send_msg_by_move(n->net, hello, conn); @@ -123,7 +133,8 @@ void conn_handler(const msgnetwork_conn_t *conn, bool connected, void *userdata) printf("[%s] Disconnected, retrying.\n", name); /* try to reconnect to the same address */ netaddr_t *addr = msgnetwork_conn_get_addr(conn); - msgnetwork_connect(net, addr); + msgnetwork_connect(net, addr, &err); + check_err(&err); netaddr_free(addr); } } @@ -166,12 +177,16 @@ int main() { msgnetwork_start(bob.net); /* accept incoming connections */ - msgnetwork_listen(alice.net, alice_addr); - msgnetwork_listen(bob.net, bob_addr); + msgnetwork_listen(alice.net, alice_addr, &err); + check_err(&err); + msgnetwork_listen(bob.net, bob_addr, &err); + check_err(&err); /* try to connect once */ - msgnetwork_conn_free(msgnetwork_connect(alice.net, bob_addr)); - msgnetwork_conn_free(msgnetwork_connect(bob.net, alice_addr)); + msgnetwork_conn_free(msgnetwork_connect(alice.net, bob_addr, &err)); + check_err(&err); + msgnetwork_conn_free(msgnetwork_connect(bob.net, alice_addr, &err)); + check_err(&err); netaddr_free(alice_addr); netaddr_free(bob_addr); -- cgit v1.2.3