aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <tederminant@gmail.com>2019-06-14 16:01:29 -0400
committerDeterminant <tederminant@gmail.com>2019-06-14 16:01:29 -0400
commit6c927588f78c663fded354fd696997d09fb5d697 (patch)
treed2367b60c81471a315d8f11fd107eb39b214e38b
parent2b23bd2e6b94edca0ef27d9560aedfc4459bd74b (diff)
handle errors in C bindings
-rw-r--r--include/salticidae/network.h8
-rw-r--r--include/salticidae/stream.h44
-rw-r--r--include/salticidae/util.h40
-rw-r--r--src/network.cpp49
-rw-r--r--src/stream.cpp97
-rw-r--r--src/util.cpp25
-rw-r--r--test/test_msgnet_c.c29
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 <getopt.h>
+#include <unistd.h>
+#include <fcntl.h>
+#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 <string>
#include <exception>
#include <cstdarg>
@@ -34,11 +55,6 @@
#include <vector>
#include <unordered_map>
#include <functional>
-#include <getopt.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#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);