X-Git-Url: http://git.meshlink.io/?p=meshlink;a=blobdiff_plain;f=src%2Fmeshlink%2B%2B.h;h=f5921363e0dffa550a5a38065bc8eaafc703829f;hp=4179a9ec248b274ec0681917436c9beb434486d0;hb=a5a8005b2d89712e124ab7295165a3e229abdad5;hpb=f712fdc0b3de22566cdf06954256c62f46f25542 diff --git a/src/meshlink++.h b/src/meshlink++.h index 4179a9ec..f5921363 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -27,6 +27,7 @@ namespace meshlink { class mesh; class node; class channel; +class submesh; /// Severity of log messages generated by MeshLink. typedef meshlink_log_level_t log_level_t; @@ -42,6 +43,13 @@ typedef meshlink_errno_t errno_t; */ typedef void (*receive_cb_t)(mesh *mesh, node *source, const void *data, size_t len); +/// A callback reporting the meta-connection attempt made by the host node to an another node. +/** @param mesh A handle which represents an instance of MeshLink. + * @param node A pointer to a meshlink_node_t describing the node to whom meta-connection is being tried. + * This pointer is valid until meshlink_close() is called. + */ +typedef void (*connection_try_cb_t)(mesh *mesh, node *node); + /// A callback reporting node status changes. /** @param mesh A handle which represents an instance of MeshLink. * @param node A pointer to a meshlink::node describing the node whose status changed. @@ -49,6 +57,14 @@ typedef void (*receive_cb_t)(mesh *mesh, node *source, const void *data, size_t */ typedef void (*node_status_cb_t)(mesh *mesh, node *node, bool reachable); +/// A callback reporting node path MTU changes. +/** @param mesh A handle which represents an instance of MeshLink. + * @param node A pointer to a meshlink_node_t describing the node whose status changed. + * This pointer is valid until meshlink_close() is called. + * @param pmtu The current path MTU to the node, or 0 if UDP communication is not (yet) possible. + */ +typedef void (*node_pmtu_cb_t)(mesh *mesh, node *node, uint16_t pmtu); + /// A callback reporting duplicate node detection. /** @param mesh A handle which represents an instance of MeshLink. * @param node A pointer to a meshlink_node_t describing the node which is duplicate. @@ -90,10 +106,37 @@ typedef void (*channel_receive_cb_t)(mesh *mesh, channel *channel, const void *d */ typedef void (*channel_poll_cb_t)(mesh *mesh, channel *channel, size_t len); +/// A callback for cleaning up buffers submitted for asynchronous I/O. +/** This callbacks signals that MeshLink has finished using this buffer. + * The ownership of the buffer is now back into the application's hands. + * + * @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the channel which used this buffer. + * @param data A pointer to a buffer containing the enqueued data. + * @param len The length of the buffer. + * @param priv A private pointer which was set by the application when submitting the buffer. + */ +typedef void (*aio_cb_t)(mesh *mesh, channel *channel, const void *data, size_t len, void *priv); + +/// A callback for asynchronous I/O to and from filedescriptors. +/** This callbacks signals that MeshLink has finished using this filedescriptor. + * + * @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the channel which used this filedescriptor. + * @param fd The filedescriptor that was used. + * @param len The length of the data that was successfully sent or received. + * @param priv A private pointer which was set by the application when submitting the buffer. + */ +typedef void (*aio_fd_cb_t)(mesh *mesh, channel *channel, int fd, size_t len, void *priv); + /// A class describing a MeshLink node. class node: public meshlink_node_t { }; +/// A class describing a MeshLink Sub-Mesh. +class submesh: public meshlink_submesh_t { +}; + /// A class describing a MeshLink channel. class channel: public meshlink_channel_t { public: @@ -101,6 +144,7 @@ public: static const uint32_t ORDERED = MESHLINK_CHANNEL_ORDERED; static const uint32_t FRAMED = MESHLINK_CHANNEL_FRAMED; static const uint32_t DROP_LATE = MESHLINK_CHANNEL_DROP_LATE; + static const uint32_t NO_PARTIAL = MESHLINK_CHANNEL_NO_PARTIAL; static const uint32_t TCP = MESHLINK_CHANNEL_TCP; static const uint32_t UDP = MESHLINK_CHANNEL_UDP; }; @@ -140,9 +184,9 @@ public: * @param confbase The directory in which MeshLink will store its configuration files. * @param name The name which this instance of the application will use in the mesh. * @param appname The application name which will be used in the mesh. - * @param dclass The device class which will be used in the mesh. + * @param devclass The device class which will be used in the mesh. * - * @return This function will return a pointer to a meshlink::mesh if MeshLink has succesfully set up its configuration files, NULL otherwise. + * @return This function will return a pointer to a meshlink::mesh if MeshLink has successfully set up its configuration files, NULL otherwise. */ bool open(const char *confbase, const char *name, const char *appname, dev_class_t devclass) { handle = meshlink_open(confbase, name, appname, devclass); @@ -195,6 +239,13 @@ public: (void)reachable; } + /// This functions is called whenever another node's path MTU changes. + virtual void node_pmtu(node *peer, uint16_t pmtu) { + /* do nothing */ + (void)peer; + (void)pmtu; + } + /// This functions is called whenever a duplicate node is detected. virtual void node_duplicate(node *peer) { /* do nothing */ @@ -208,7 +259,19 @@ public: (void)message; } - /// This functions is called whenever another node attemps to open a channel to the local node. + /// This functions is called whenever MeshLink has encountered a serious error. + virtual void error(meshlink_errno_t meshlink_errno) { + /* do nothing */ + (void)meshlink_errno; + } + + /// This functions is called whenever MeshLink a meta-connection attempt is made. + virtual void connection_try(node *peer) { + /* do nothing */ + (void)peer; + } + + /// This functions is called whenever another node attempts to open a channel to the local node. /** * If the channel is accepted, the poll_callback will be set to channel_poll and can be * changed using set_channel_poll_cb(). Likewise, the receive callback is set to @@ -274,14 +337,17 @@ public: /** This function causes MeshLink to open network sockets, make outgoing connections, and * create a new thread, which will handle all network I/O. * - * @return This function will return true if MeshLink has succesfully started its thread, false otherwise. + * @return This function will return true if MeshLink has successfully started its thread, false otherwise. */ bool start() { meshlink_set_receive_cb(handle, &receive_trampoline); meshlink_set_node_status_cb(handle, &node_status_trampoline); + meshlink_set_node_pmtu_cb(handle, &node_pmtu_trampoline); meshlink_set_node_duplicate_cb(handle, &node_duplicate_trampoline); meshlink_set_log_cb(handle, MESHLINK_DEBUG, &log_trampoline); + meshlink_set_error_cb(handle, &error_trampoline); meshlink_set_channel_accept_cb(handle, &channel_accept_trampoline); + meshlink_set_connection_try_cb(handle, &connection_try_trampoline); return meshlink_start(handle); } @@ -322,6 +388,18 @@ public: return (node *)meshlink_get_node(handle, name); } + /// Get a handle for a specific submesh. + /** This function returns a handle for the submesh with the given name. + * + * @param name The name of the submesh for which a handle is requested. + * + * @return A pointer to a meshlink::submesh which represents the requested submesh, + * or NULL if the requested submesh does not exist. + */ + submesh *get_submesh(const char *name) { + return (submesh *)meshlink_get_submesh(handle, name); + } + /// Get a handle for our own node. /** This function returns a handle for the local node. * @@ -446,6 +524,28 @@ public: return meshlink_get_external_address_for_family(handle, family); } + /** This function performs tries to discover the address of the local interface used for outgoing connection. + * + * Please note that this is function only returns a single address, + * even if the local node might have more than one external address. + * In that case, there is no control over which address will be selected. + * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT, + * there is no guarantee that the external address will be valid for an extended period of time. + * + * This function will fail if it couldn't find a local address for the given address family. + * If hostname resolving is requested, this function may block for a few seconds. + * + * @param family The address family to check, for example AF_INET or AF_INET6. If AF_UNSPEC is given, + * this might return the external address for any working address family. + * + * @return This function returns a pointer to a C string containing the discovered external address, + * or NULL if there was an error looking up the address. + * After get_external_address() returns, the application is free to overwrite or free this string. + */ + bool get_local_address(int family = AF_UNSPEC) { + return meshlink_get_local_address_for_family(handle, family); + } + /// Try to discover the external address for the local node, and add it to its list of addresses. /** This function is equivalent to: * @@ -461,8 +561,6 @@ public: /// Get the network port used by the local node. /** This function returns the network port that the local node is listening on. - * - * @param mesh A handle which represents an instance of MeshLink. * * @return This function returns the port number, or -1 in case of an error. */ @@ -482,7 +580,9 @@ public: * If the port is set to 0, then MeshLink will listen on a port * that is randomly assigned by the operating system every time open() is called. * - * @return This function returns true if the port was succesfully changed, false otherwise. + * @return This function returns true if the port was successfully changed + * to the desired port, false otherwise. If it returns false, there + * is no guarantee that MeshLink is listening on the old port. */ bool set_port(int port) { return meshlink_set_port(handle, port); @@ -504,19 +604,21 @@ public: * This URL should be passed by the application to the invitee in a way that no eavesdroppers can see the URL. * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. * + * @param submesh A handle to the submesh to put the invitee in. * @param name The name that the invitee will use in the mesh. + * @param flags A bitwise-or'd combination of flags that controls how the URL is generated. * * @return This function returns a string that contains the invitation URL. * The application should call free() after it has finished using the URL. */ - char *invite(const char *name) { - return meshlink_invite(handle, name); + char *invite(submesh *submesh, const char *name, uint32_t flags = 0) { + return meshlink_invite_ex(handle, submesh, name, flags); } /// Use an invitation to join a mesh. /** This function allows the local node to join an existing mesh using an invitation URL generated by another node. * An invitation can only be used if the local node has never connected to other nodes before. - * After a succesfully accepted invitation, the name of the local node may have changed. + * After a successfully accepted invitation, the name of the local node may have changed. * * This function may only be called on a mesh that has not been started yet and which is not already part of an existing mesh. * @@ -582,12 +684,48 @@ public: meshlink_set_channel_poll_cb(handle, channel, (meshlink_channel_poll_cb_t)cb); } + /// Set the send buffer size of a channel. + /** This function sets the desired size of the send buffer. + * The default size is 128 kB. + * + * @param channel A handle for the channel. + * @param size The desired size for the send buffer. + * If a NULL pointer is given, the callback will be disabled. + */ + void set_channel_sndbuf(channel *channel, size_t size) { + meshlink_set_channel_sndbuf(handle, channel, size); + } + + /// Set the receive buffer size of a channel. + /** This function sets the desired size of the receive buffer. + * The default size is 128 kB. + * + * @param channel A handle for the channel. + * @param size The desired size for the send buffer. + * If a NULL pointer is given, the callback will be disabled. + */ + void set_channel_rcvbuf(channel *channel, size_t size) { + meshlink_set_channel_rcvbuf(handle, channel, size); + } + + /// Set the connection timeout used for channels to the given node. + /** This sets the timeout after which unresponsive channels will be reported as closed. + * The timeout is set for all current and future channels to the given node. + * + * @param channel A handle for the channel. + * @param timeout The timeout in seconds after which unresponsive channels will be reported as closed. + * The default is 60 seconds. + */ + void set_node_channel_timeout(node *node, int timeout) { + meshlink_set_node_channel_timeout(handle, node, timeout); + } + /// Open a reliable stream channel to another node. /** This function is called whenever a remote node wants to open a channel to the local node. * The application then has to decide whether to accept or reject this channel. * * This function sets the channel poll callback to channel_poll_trampoline, which in turn - * calls channel_poll. To set a differnt, channel-specific poll callback, use set_channel_poll_cb. + * calls channel_poll. To set a different, channel-specific poll callback, use set_channel_poll_cb. * * @param node The node to which this channel is being initiated. * @param port The port number the peer wishes to connect to. @@ -604,9 +742,23 @@ public: return ch; } - /** - * @override - * Sets channel_receive_trampoline as cb, which in turn calls this->channel_receive( ... ). + /// Open a reliable stream channel to another node. + /** This function is called whenever a remote node wants to open a channel to the local node. + * The application then has to decide whether to accept or reject this channel. + * + * This function sets the channel receive callback to channel_receive_trampoline, + * which in turn calls channel_receive. + * + * This function sets the channel poll callback to channel_poll_trampoline, which in turn + * calls channel_poll. To set a different, channel-specific poll callback, use set_channel_poll_cb. + * + * @param node The node to which this channel is being initiated. + * @param port The port number the peer wishes to connect to. + * @param data A pointer to a buffer containing data to already queue for sending. + * @param len The length of the data. + * @param flags A bitwise-or'd combination of flags that set the semantics for this channel. + * + * @return A handle for the channel, or NULL in case of an error. */ channel *channel_open(node *node, uint16_t port, const void *data, size_t len, uint32_t flags = channel::TCP) { channel *ch = (channel *)meshlink_channel_open_ex(handle, node, port, &channel_receive_trampoline, data, len, flags); @@ -645,11 +797,109 @@ public: * @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. + * If MESHLINK_CHANNEL_NO_PARTIAL is set, then the result will either be len, + * 0 if the buffer is currently too full, or -1 if len is too big even for an empty buffer. */ ssize_t channel_send(channel *channel, void *data, size_t len) { return meshlink_channel_send(handle, channel, data, len); } + /// Transmit data on a channel asynchronously + /** This registers a buffer that will be used to send data to the remote node. + * Multiple buffers can be registered, in which case data will be sent in the order the buffers were registered. + * While there are still buffers with unsent data, the poll callback will not be called. + * + * @param channel A handle for the channel. + * @param data A pointer to a buffer containing data sent by the source, or NULL if there is no data to send. + * After meshlink_channel_aio_send() returns, the buffer may not be modified or freed by the application + * until the callback routine is called. + * @param len The length of the data, or 0 if there is no data to send. + * @param cb A pointer to the function which will be called when MeshLink has finished using the buffer. + * @param priv A private pointer which was set by the application when submitting the buffer. + * + * @return True if the buffer was enqueued, false otherwise. + */ + bool channel_aio_send(channel *channel, const void *data, size_t len, meshlink_aio_cb_t cb, void *priv) { + return meshlink_channel_aio_send(handle, channel, data, len, cb, priv); + } + + /// Transmit data on a channel asynchronously from a filedescriptor + /** This will read up to the specified length number of bytes from the given filedescriptor, and send it over the channel. + * The callback may be returned early if there is an error reading from the filedescriptor. + * While there is still with unsent data, the poll callback will not be called. + * + * @param channel A handle for the channel. + * @param fd A file descriptor from which data will be read. + * @param len The length of the data, or 0 if there is no data to send. + * @param cb A pointer to the function which will be called when MeshLink has finished using the filedescriptor. + * @param priv A private pointer which was set by the application when submitting the buffer. + * + * @return True if the buffer was enqueued, false otherwise. + */ + bool channel_aio_fd_send(channel *channel, int fd, size_t len, meshlink_aio_fd_cb_t cb, void *priv) { + return meshlink_channel_aio_fd_send(handle, channel, fd, len, cb, priv); + } + + /// Receive data on a channel asynchronously + /** This registers a buffer that will be filled with incoming channel data. + * Multiple buffers can be registered, in which case data will be received in the order the buffers were registered. + * While there are still buffers that have not been filled, the receive callback will not be called. + * + * @param channel A handle for the channel. + * @param data A pointer to a buffer that will be filled with incoming data. + * After meshlink_channel_aio_receive() returns, the buffer may not be modified or freed by the application + * until the callback routine is called. + * @param len The length of the data. + * @param cb A pointer to the function which will be called when MeshLink has finished using the buffer. + * @param priv A private pointer which was set by the application when submitting the buffer. + * + * @return True if the buffer was enqueued, false otherwise. + */ + bool channel_aio_receive(channel *channel, const void *data, size_t len, meshlink_aio_cb_t cb, void *priv) { + return meshlink_channel_aio_receive(handle, channel, data, len, cb, priv); + } + + /// Receive data on a channel asynchronously and send it to a filedescriptor + /** This will read up to the specified length number of bytes from the channel, and send it to the filedescriptor. + * The callback may be returned early if there is an error writing to the filedescriptor. + * While there is still unread data, the receive callback will not be called. + * + * @param channel A handle for the channel. + * @param fd A file descriptor to which data will be written. + * @param len The length of the data. + * @param cb A pointer to the function which will be called when MeshLink has finished using the filedescriptor. + * @param priv A private pointer which was set by the application when submitting the buffer. + * + * @return True if the buffer was enqueued, false otherwise. + */ + bool channel_aio_fd_receive(channel *channel, int fd, size_t len, meshlink_aio_fd_cb_t cb, void *priv) { + return meshlink_channel_aio_fd_receive(handle, channel, fd, len, cb, priv); + } + + /// 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. @@ -660,6 +910,16 @@ public: meshlink_enable_discovery(handle, enable); } + /// Set device class timeouts + /** This sets the ping interval and timeout for a given device class. + * + * @param devclass The device class to update + * @param pinginterval The interval between keepalive packets, in seconds. The default is 60. + * @param pingtimeout The required time within which a peer should respond, in seconds. The default is 5. + * The timeout must be smaller than the interval. + */ + void set_dev_class_timeouts(dev_class_t devclass, int pinginterval, int pingtimeout); + private: // non-copyable: mesh(const mesh &) /* TODO: C++11: = delete */; @@ -684,6 +944,15 @@ private: that->node_status(static_cast(peer), reachable); } + static void node_pmtu_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer, uint16_t pmtu) { + if(!(handle->priv)) { + return; + } + + meshlink::mesh *that = static_cast(handle->priv); + that->node_pmtu(static_cast(peer), pmtu); + } + static void node_duplicate_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer) { if(!(handle->priv)) { return; @@ -702,6 +971,24 @@ private: that->log(level, message); } + static void error_trampoline(meshlink_handle_t *handle, meshlink_errno_t meshlink_errno) { + if(!(handle->priv)) { + return; + } + + meshlink::mesh *that = static_cast(handle->priv); + that->error(meshlink_errno); + } + + static void connection_try_trampoline(meshlink_handle_t *handle, meshlink_node_t *peer) { + if(!(handle->priv)) { + return; + } + + meshlink::mesh *that = static_cast(handle->priv); + that->connection_try(static_cast(peer)); + } + 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; @@ -751,7 +1038,7 @@ static inline const char *strerror(errno_t err = meshlink_errno) { * @param confbase The directory in which MeshLink stores its configuration files. * After the function returns, the application is free to overwrite or free @a confbase @a. * - * @return This function will return true if the MeshLink instance was succesfully destroyed, false otherwise. + * @return This function will return true if the MeshLink instance was successfully destroyed, false otherwise. */ static inline bool destroy(const char *confbase) { return meshlink_destroy(confbase);