+ return (meshlink_node_t *)mesh->self;
+}
+
+meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) {
+ if(!mesh || !name) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ meshlink_node_t *node = NULL;
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+ node = (meshlink_node_t *)lookup_node(mesh, (char *)name); // TODO: make lookup_node() use const
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return node;
+}
+
+meshlink_submesh_t *meshlink_get_submesh(meshlink_handle_t *mesh, const char *name) {
+ if(!mesh || !name) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ meshlink_submesh_t *submesh = NULL;
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+ submesh = (meshlink_submesh_t *)lookup_submesh(mesh, name);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return submesh;
+}
+
+meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) {
+ if(!mesh || !nmemb || (*nmemb && !nodes)) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ meshlink_node_t **result;
+
+ //lock mesh->nodes
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
+ *nmemb = mesh->nodes->count;
+ result = realloc(nodes, *nmemb * sizeof(*nodes));
+
+ if(result) {
+ meshlink_node_t **p = result;
+
+ for splay_each(node_t, n, mesh->nodes) {
+ *p++ = (meshlink_node_t *)n;
+ }
+ } else {
+ *nmemb = 0;
+ free(nodes);
+ meshlink_errno = MESHLINK_ENOMEM;
+ }
+
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+ return result;
+}
+
+static meshlink_node_t **meshlink_get_all_nodes_by_condition(meshlink_handle_t *mesh, const void *condition, meshlink_node_t **nodes, size_t *nmemb, search_node_by_condition_t search_node) {
+ meshlink_node_t **result;
+
+ pthread_mutex_lock(&(mesh->mesh_mutex));
+
+ *nmemb = 0;
+
+ for splay_each(node_t, n, mesh->nodes) {
+ if(true == search_node(n, condition)) {
+ *nmemb = *nmemb + 1;
+ }
+ }
+
+ if(*nmemb == 0) {
+ free(nodes);
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return NULL;
+ }
+
+ result = realloc(nodes, *nmemb * sizeof(*nodes));
+
+ if(result) {
+ meshlink_node_t **p = result;
+
+ for splay_each(node_t, n, mesh->nodes) {
+ if(true == search_node(n, condition)) {
+ *p++ = (meshlink_node_t *)n;
+ }
+ }
+ } else {
+ *nmemb = 0;
+ free(nodes);
+ meshlink_errno = MESHLINK_ENOMEM;
+ }
+
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+ return result;
+}
+
+static bool search_node_by_dev_class(const node_t *node, const void *condition) {
+ dev_class_t *devclass = (dev_class_t *)condition;
+
+ if(*devclass == node->devclass) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool search_node_by_submesh(const node_t *node, const void *condition) {
+ if(condition == node->submesh) {
+ return true;
+ }
+
+ return false;
+}
+
+meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) {
+ if(!mesh || ((int)devclass < 0) || (devclass > _DEV_CLASS_MAX) || !nmemb) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ return meshlink_get_all_nodes_by_condition(mesh, &devclass, nodes, nmemb, search_node_by_dev_class);
+}
+
+meshlink_node_t **meshlink_get_all_nodes_by_submesh(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, meshlink_node_t **nodes, size_t *nmemb) {
+ if(!mesh || !submesh || !nmemb) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return NULL;
+ }
+
+ return meshlink_get_all_nodes_by_condition(mesh, submesh, nodes, nmemb, search_node_by_submesh);