Example #1
0
DSNode *dslink_node_get_path(DSNode *root, const char *path) {
    if (!root) {
        return NULL;
    } else if (strcmp(path, "/") == 0) {
        return root;
    } else if (*path == '/') {
        path++;
    }

    DSNode *node = root;
    const char *end = strchr(path, '/');
    if (end) {
        if (!node->children) {
            return NULL;
        }
        node = dslink_map_getl(node->children, (void *) path, end - path);
        return dslink_node_get_path(node, end);
    } else if (*path != '\0') {
        if (!node->children) {
            return NULL;
        }
        return dslink_map_get(node->children, (void *) path);
    }

    return node;
}
Example #2
0
int dslink_response_sub(DSLink *link, json_t *paths, json_t *rid) {
    if (dslink_response_send_closed(link, rid) != 0) {
        return DSLINK_ALLOC_ERR;
    }

    DSNode *root = link->responder->super_root;
    size_t index;
    json_t *value;
    json_array_foreach(paths, index, value) {
        const char *path = json_string_value(json_object_get(value, "path"));
        DSNode *node = dslink_node_get_path(root, path);
        if (!node) {
            continue;
        }
        uint32_t *sid = malloc(sizeof(uint32_t));
        if (!sid) {
            return DSLINK_ALLOC_ERR;
        }
        *sid = (uint32_t) json_integer_value(json_object_get(value, "sid"));
        void *tmp = sid;
        if (dslink_map_set(link->responder->value_path_subs,
                           (void *) node->path, &tmp) != 0) {
            free(sid);
            return 1;
        }
        if (tmp) {
            void *p = tmp;
            dslink_map_remove(link->responder->value_sid_subs, &p);
            free(tmp);
        }
        tmp = (void *) node->path;
        if (dslink_map_set(link->responder->value_sid_subs,
                           sid, &tmp) != 0) {
            tmp = (void *) node->path;
            dslink_map_remove(link->responder->value_path_subs, &tmp);
            free(sid);
            return 1;
        }

        dslink_response_send_val(link, node, *sid);
        if (node->on_subscribe) {
            node->on_subscribe(link, node);
        }
    }
    return 0;
}
Example #3
0
int dslink_response_unsub(DSLink *link, json_t *sids, json_t *rid) {
    size_t index;
    json_t *value;
    json_array_foreach(sids, index, value) {
        uint32_t sid = (uint32_t) json_integer_value(value);
        void *p = &sid;
        char *path = dslink_map_remove(link->responder->value_sid_subs, &p);
        if (path) {
            DSNode *node = dslink_node_get_path(link->responder->super_root,
                                                path);
            if (node && node->on_unsubscribe) {
                node->on_unsubscribe(link, node);
            }

            void *tmp = path;
            dslink_map_remove(link->responder->value_path_subs, &tmp);
            free(p);
        }
    }
Example #4
0
int dslink_request_handle(DSLink *link, json_t *req) {
    const char *method = json_string_value(json_object_get(req, "method"));
    if (!method) {
        return 1;
    }

    if (strcmp(method, "list") == 0) {
        const char *path = json_string_value(json_object_get(req, "path"));
        DSNode *node = dslink_node_get_path(link->responder->super_root, path);
        return dslink_response_list(link, req, node);
    } else if (strcmp(method, "subscribe") == 0) {
        json_t *paths = json_object_get(req, "paths");
        json_t *rid = json_object_get(req, "rid");
        return dslink_response_sub(link, paths, rid);
    } else if (strcmp(method, "unsubscribe") == 0) {
        json_t *sids = json_object_get(req, "sids");
        json_t *rid = json_object_get(req, "rid");
        return dslink_response_unsub(link, sids, rid);
    } else if (strcmp(method, "invoke") == 0) {
        const char *path = json_string_value(json_object_get(req, "path"));
        DSNode *node = dslink_node_get_path(link->responder->super_root, path);
        if (node && node->on_invocation) {
            Stream *stream = dslink_malloc(sizeof(Stream));
            if (!stream) {
                return 1;
            }
            stream->type = INVOCATION_STREAM;
            stream->path = dslink_strdup(node->path);

            ref_t *stream_ref = dslink_ref(stream, free_stream);

            json_t *jsonRid = json_object_get(req, "rid");
            json_t *params = json_object_get(req, "params");
            node->on_invocation(link, node, jsonRid, params, stream_ref);

            if (stream->unused != 1) {
                dslink_decref(stream_ref);
            } else {
                ref_t *rid = dslink_ref(dslink_malloc(sizeof(uint32_t)), dslink_free);
                {
                    uint32_t r = (uint32_t) json_integer_value(jsonRid);
                    *((uint32_t *) rid->data) = r;
                }

                if (dslink_map_set(link->responder->open_streams,
                                   rid,
                                   stream_ref) != 0) {
                    dslink_free(rid);
                    dslink_free(stream_ref);
                    free_stream(stream);
                    return 1;
                }
            }
        }
    } else if (strcmp(method, "set") == 0) {
        const char *path = json_string_value(json_object_get(req, "path"));
        json_t *value = json_object_get(req, "value");
        DSNode *node = dslink_node_get_path(link->responder->super_root, path);
        
        if (node) {
            ref_t *writable_ref = dslink_map_get(node->meta_data, "$writable");
            if (writable_ref && json_is_string((json_t*) writable_ref->data)) {
                if (node->on_value_set) {
                    node->on_value_set(link, node, value);
                } else {
                    dslink_node_update_value(link, node, value);
                }
            }
        }
    } else if (strcmp(method, "close") == 0) {
        json_t *rid = json_object_get(req, "rid");
        uint32_t ridi = (uint32_t) json_integer_value(rid);
        ref_t *stream_ref = dslink_map_remove_get(link->responder->open_streams, &ridi);
        if (stream_ref) {
            Stream *stream = stream_ref->data;

            DSNode *node = NULL;

            if (stream->path) {
                node = dslink_node_get_path(link->responder->super_root, stream->path);
            }

            if (stream->on_close != NULL) {
                stream->on_close(link, node, stream);
            }

            if (stream->type == LIST_STREAM) {
                dslink_map_remove(link->responder->list_subs, (void *) stream->path);
            }

            dslink_decref(stream_ref);
        }
    } else {
        log_warn("Unrecognized method: %s\n", method);
    }
    return 0;
}