From 9f294eb2e0ae0bed8120fc34fd9782f2f0a9ac74 Mon Sep 17 00:00:00 2001
From: Determinant <tederminant@gmail.com>
Date: Mon, 3 Jun 2019 17:30:01 -0400
Subject: WIP: C bindings

---
 include/salticidae/event.h   |  6 +++++
 include/salticidae/msg.h     | 19 +++++++++++++++
 include/salticidae/netaddr.h | 18 +++++++++++++-
 include/salticidae/network.h | 57 +++++++++++++++++++++++++++++++++++++++++---
 include/salticidae/stream.h  | 37 ++++++++++++++++++++++++++++
 include/salticidae/type.h    |  6 +++++
 6 files changed, 139 insertions(+), 4 deletions(-)

(limited to 'include')

diff --git a/include/salticidae/event.h b/include/salticidae/event.h
index 946dda1..19bd250 100644
--- a/include/salticidae/event.h
+++ b/include/salticidae/event.h
@@ -35,6 +35,7 @@
 #include "salticidae/util.h"
 #include "salticidae/ref.h"
 
+#ifdef __cplusplus
 namespace salticidae {
 
 struct _event_context_deleter {
@@ -644,4 +645,9 @@ class ThreadCall {
 
 }
 
+using eventcontext_t = salticidae::EventContext;
+
+#else
+typedef struct eventcontext_t;
+#endif
 #endif
diff --git a/include/salticidae/msg.h b/include/salticidae/msg.h
index 03eb6dd..128e287 100644
--- a/include/salticidae/msg.h
+++ b/include/salticidae/msg.h
@@ -34,6 +34,7 @@
 #include "salticidae/stream.h"
 #include "salticidae/netaddr.h"
 
+#ifdef __cplusplus
 namespace salticidae {
 
 template<typename OpcodeType>
@@ -69,6 +70,14 @@ class MsgBase {
         set_checksum();
     }
 
+#ifdef SALTICIDAE_CBINDINGS
+    MsgBase(const OpcodeType &opcode, bytearray_t &&payload): magic(0x0) {
+        set_opcode(opcode);
+        set_payload(std::move(payload));
+        set_checksum();
+    }
+#endif
+
     MsgBase(const MsgBase &other):
             magic(other.magic),
             opcode(other.opcode),
@@ -258,4 +267,14 @@ const size_t MsgBase<OpcodeType>::header_size =
     0;
 }
 
+using msg_t = salticidae::MsgBase<_opcode_t>;
+#else
+typedef struct msg_t msg_t;
+#endif
+
+extern "C" {
+
+void msg_new();
+}
+
 #endif
diff --git a/include/salticidae/netaddr.h b/include/salticidae/netaddr.h
index 224d1d4..917c498 100644
--- a/include/salticidae/netaddr.h
+++ b/include/salticidae/netaddr.h
@@ -34,10 +34,10 @@
 #include "salticidae/util.h"
 #include "salticidae/stream.h"
 
+#ifdef __cplusplus
 namespace salticidae {
 
 /* TODO: IPv6 support */
-
 struct NetAddr {
     uint32_t ip;
     uint16_t port;
@@ -124,4 +124,20 @@ namespace std {
     };
 }
 
+using netaddr_t = salticidae::NetAddr;
+#else
+typedef struct netaddr_t netaddr_t;
+#endif
+
+extern "C" {
+
+netaddr_t *netaddr_new();
+netaddr_t *netaddr_new_from_ip_port(uint32_t ip, uint16_t port);
+netaddr_t *netaddr_new_from_sip_port(const char *ip, uint16_t port);
+netaddr_t *netaddr_new_from_sipport(const char *ip_port_addr);
+bool netaddr_is_eq(const netaddr_t *a, const netaddr_t *b);
+bool netaddr_is_null(const netaddr_t *self);
+
+}
+
 #endif
diff --git a/include/salticidae/network.h b/include/salticidae/network.h
index f3dd313..12fe720 100644
--- a/include/salticidae/network.h
+++ b/include/salticidae/network.h
@@ -30,8 +30,8 @@
 #include "salticidae/msg.h"
 #include "salticidae/conn.h"
 
+#ifdef __cplusplus
 namespace salticidae {
-
 /** Network of nodes who can send async messages.  */
 template<typename OpcodeType>
 class MsgNetwork: public ConnPool {
@@ -156,6 +156,9 @@ class MsgNetwork: public ConnPool {
             {
                 auto &msg = item.first;
                 auto &conn = item.second;
+#ifdef SALTICIDAE_CBINDINGS_INJECT_CALLBACK
+                salticidae_injected_msg_callback(&msg, conn.get());
+#else
                 auto it = handler_map.find(msg.get_opcode());
                 if (it == handler_map.end())
                     SALTICIDAE_LOG_WARN("unknown opcode: %s",
@@ -171,6 +174,7 @@ class MsgNetwork: public ConnPool {
 #endif
                     it->second(msg, conn);
                 }
+#endif
                 if (++cnt == burst_size) return true;
             }
             return false;
@@ -182,14 +186,23 @@ class MsgNetwork: public ConnPool {
         typename callback_traits<Func>::msg_type, DataStream &&>::value>::type
     reg_handler(Func handler) {
         using callback_t = callback_traits<Func>;
-        handler_map[callback_t::msg_type::opcode] = [handler](const Msg &msg, const conn_t &conn) {
+        set_handler(callback_t::msg_type::opcode,
+            [handler](const Msg &msg, const conn_t &conn) {
             handler(typename callback_t::msg_type(msg.get_payload()),
                     static_pointer_cast<typename callback_t::conn_type>(conn));
-        };
+        });
+    }
+
+    template<typename Func>
+    inline void set_handler(OpcodeType opcode, Func handler) {
+        handler_map[opcode] = handler;
     }
 
     template<typename MsgType>
     bool send_msg(MsgType &&msg, const conn_t &conn);
+#ifdef SALTICIDAE_CBINDINGS
+    inline bool send_msg(const Msg &msg, const conn_t &conn);
+#endif
     using ConnPool::listen;
     conn_t connect(const NetAddr &addr) {
         return static_pointer_cast<Conn>(ConnPool::connect(addr));
@@ -468,6 +481,11 @@ template<typename OpcodeType>
 template<typename MsgType>
 bool MsgNetwork<OpcodeType>::send_msg(MsgType &&_msg, const conn_t &conn) {
     Msg msg(std::forward<MsgType>(_msg));
+    return send_msg(msg, conn);
+}
+
+template<typename OpcodeType>
+inline bool MsgNetwork<OpcodeType>::send_msg(const Msg &msg, const conn_t &conn) {
     bytearray_t msg_data = msg.serialize();
     SALTICIDAE_LOG_DEBUG("wrote message %s to %s",
                 std::string(msg).c_str(),
@@ -764,4 +782,37 @@ const O PeerNetwork<O, _, OPCODE_PONG>::MsgPong::opcode = OPCODE_PONG;
 
 }
 
+using msgnetwork_t = salticidae::MsgNetwork<_opcode_t>;
+using msgnetwork_config_t = msgnetwork_t::Config;
+using msgnetwork_conn_t = msgnetwork_t::conn_t;
+
+#else
+typedef struct msg_t;
+typedef struct msgnetwork_t;
+typedef struct msgnetwork_config_t;
+typedef struct msgnetwork_conn_t;
+#endif
+
+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);
+
+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);
+
+#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
+}
+
 #endif
diff --git a/include/salticidae/stream.h b/include/salticidae/stream.h
index 5f54195..9eda2bd 100644
--- a/include/salticidae/stream.h
+++ b/include/salticidae/stream.h
@@ -29,6 +29,7 @@
 #include "salticidae/ref.h"
 #include "salticidae/crypto.h"
 
+#ifdef __cplusplus
 namespace salticidae {
 
 template<size_t N, typename T> class Blob;
@@ -466,4 +467,40 @@ namespace std {
     };
 }
 
+using uint256_t = salticidae::uint256_t;
+using datastream_t = salticidae::DataStream;
+
+#else
+typedef struct datastream_t;
+typedef struct uint256_t;
+#endif
+
+extern "C" {
+
+uint256_t *uint256_new();
+uint256_t *uint256_new_from_bytes(const uint8_t *arr);
+bool uint256_is_null(const uint256_t *self);
+bool uint256_is_eq(const uint256_t *a, const uint256_t *b);
+void uint256_serialize(const uint256_t *self, datastream_t *s);
+void uint256_unserialize(uint256_t *self, datastream_t *s);
+
+datastream_t *datastream_new();
+datastream_t *datastream_new_from_bytes(const uint8_t *begin, const uint8_t *end);
+void datastream_assign_by_copy(datastream_t *dst, const datastream_t *src);
+void datastream_assign_by_move(datastream_t *dst, datastream_t *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_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_data(datastream_t *self,
+                        uint8_t *begin, uint8_t *end);
+const uint8_t *datastream_get_data_inplace(datastream_t *self, size_t len);
+uint256_t *datastream_get_hash(const datastream_t *self);
+
+}
 #endif
diff --git a/include/salticidae/type.h b/include/salticidae/type.h
index 68deeb0..3ec202a 100644
--- a/include/salticidae/type.h
+++ b/include/salticidae/type.h
@@ -89,4 +89,10 @@ inline auto generic_bind(ReturnType(ClassType::* f)(Args...), FArgs&&... fargs)
 
 }
 
+#ifdef SALTICIDAE_CBINDINGS_STR_OP
+using _opcode_t = std::string;
+#else
+using _opcode_t = uint8_t;
+#endif
+
 #endif
-- 
cgit v1.2.3-70-g09d2