+
+ /// Partially close a reliable stream channel.
+ /** This shuts down the read or write side of a channel, or both, without closing the handle.
+ * It can be used to inform the remote node that the local node has finished sending all data on the channel,
+ * but still allows waiting for incoming data from the remote node.
+ *
+ * @param channel A handle for the channel.
+ * @param direction Must be one of SHUT_RD, SHUT_WR or SHUT_RDWR.
+ */
+ void channel_shutdown(channel *channel, int direction) {
+ return meshlink_channel_shutdown(handle, channel, direction);
+ }
+
+ /// Close a reliable stream channel.
+ /** This informs the remote node that the local node has finished sending all data on the channel.
+ * It also causes the local node to stop accepting incoming data from the remote node.
+ * Afterwards, the channel handle is invalid and must not be used any more.
+ *
+ * @param channel A handle for the channel.
+ */
+ void channel_close(meshlink_channel_t *channel) {
+ return meshlink_channel_close(handle, channel);
+ }
+
+ /// Transmit data on a channel
+ /** This queues data to send to the remote node.
+ *
+ * @param channel A handle for the channel.
+ * @param data A pointer to a buffer containing data sent by the source.
+ * @param len The length of the data.
+ *
+ * @return The amount of data that was queued, which can be less than len, or a negative value in case of an error.
+ */
+ ssize_t channel_send(channel *channel, void *data, size_t len) {
+ return meshlink_channel_send(handle, channel, data, len);
+ }
+
+ /// Get the amount of bytes in the send buffer.
+ /** This returns the amount of bytes in the send buffer.
+ * These bytes have not been received by the peer yet.
+ *
+ * @param channel A handle for the channel.
+ *
+ * @return The amount of un-ACKed bytes in the send buffer.
+ */
+ size_t channel_get_sendq(channel *channel) {
+ return meshlink_channel_get_sendq(handle, channel);
+ }
+
+ /// Get the amount of bytes in the receive buffer.
+ /** This returns the amount of bytes in the receive buffer.
+ * These bytes have not been processed by the application yet.
+ *
+ * @param channel A handle for the channel.
+ *
+ * @return The amount of bytes in the receive buffer.
+ */
+ size_t channel_get_recvq(channel *channel) {
+ return meshlink_channel_get_recvq(handle, channel);
+ }
+
+ /// Enable or disable zeroconf discovery of local peers
+ /** This controls whether zeroconf discovery using the Catta library will be
+ * enabled to search for peers on the local network. By default, it is enabled.
+ *
+ * @param enable Set to true to enable discovery, false to disable.
+ */
+ void enable_discovery(bool enable = true) {
+ meshlink_enable_discovery(handle, enable);
+ }
+
+private:
+ // non-copyable:
+ mesh(const mesh &) /* TODO: C++11: = delete */;
+ void operator=(const mesh &) /* TODO: C++11: = delete */;
+
+ /// static callback trampolines:
+ static void receive_trampoline(meshlink_handle_t *handle, meshlink_node_t *source, const void *data, size_t length) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->receive(static_cast<node *>(source), data, length);
+ }
+
+ static void node_status_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer, bool reachable) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->node_status(static_cast<node *>(peer), reachable);
+ }
+
+ static void node_duplicate_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->node_duplicate(static_cast<node *>(peer));
+ }
+
+ static void log_trampoline(meshlink_handle_t *handle, log_level_t level, const char *message) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->log(level, message);
+ }
+
+ static bool channel_accept_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, uint16_t port, const void *data, size_t len) {
+ if(!(handle->priv)) {
+ return false;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ bool accepted = that->channel_accept(static_cast<meshlink::channel *>(channel), port, data, len);
+
+ if(accepted) {
+ meshlink_set_channel_receive_cb(handle, channel, &channel_receive_trampoline);
+ meshlink_set_channel_poll_cb(handle, channel, &channel_poll_trampoline);
+ }
+
+ return accepted;
+ }
+
+ static void channel_receive_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, const void *data, size_t len) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->channel_receive(static_cast<meshlink::channel *>(channel), data, len);
+ }
+
+ static void channel_poll_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, size_t len) {
+ if(!(handle->priv)) {
+ return;
+ }
+
+ meshlink::mesh *that = static_cast<mesh *>(handle->priv);
+ that->channel_poll(static_cast<meshlink::channel *>(channel), len);
+ }
+
+ meshlink_handle_t *handle;